nitro-v36-with-renderer-v36
/
src /
components /
catalog /
views /
page /
widgets /
CatalogViewProductWidgetView.tsx
CatalogViewProductWidgetView.tsx 9.9 Ko
Télécharger le fichier
import { GetAvatarRenderManager, GetSessionDataManager, RoomObjectVariable, Vector3d } from '@octane/renderer';
import { FC, useEffect } from 'react';
import { FurniCategory, GetProductIconUrl, Offer, ProductTypeEnum } from '../../../../../api';
import { AutoGrid, Column, LayoutChatStyleImageView, LayoutGridItem, LayoutHabbiconImageView, LayoutRoomPreviewerView } from '../../../../../common';
import { NativeTextTree } from '../../../../../common/native-text/NativeTextTree';
import { useCatalogData, useCatalogUiState } from '../../../../../hooks';
const PREVIEW_LIFT = 21;
// A habbicon shows above the avatar for 3 s and then fades, as in the room; the
// preview triggers it again on this cadence so it keeps playing.
const HABBICON_PREVIEW_REPEAT_MS = 4000;
// Extra lift for the habbicon preview, so the room sits higher in the view.
const HABBICON_PREVIEW_EXTRA_LIFT = 40;
const NEUTRAL_FLOOR = 'default';
const NEUTRAL_WALL = 'default';
const NEUTRAL_LANDSCAPE = 'default';
export const CatalogViewProductWidgetView: FC<{ height?: number }> = (props) => {
const { height = 240 } = props;
const { currentOffer = null, roomPreviewer = null } = useCatalogData();
const { purchaseOptions = null } = useCatalogUiState();
const { previewStuffData = null } = purchaseOptions;
useEffect(() => {
if (!currentOffer || currentOffer.pricingModel === Offer.PRICING_MODEL_BUNDLE || !roomPreviewer) return;
const product = currentOffer.product;
const clearViewOffset = () => {
roomPreviewer.addViewOffset.y = 0;
};
if (!product) {
clearViewOffset();
return;
}
roomPreviewer.addViewOffset.y = -(PREVIEW_LIFT + (product.isUniqueLimitedItem ? 15 : 0));
roomPreviewer.centerWallItems = true;
roomPreviewer.setAutomaticStateChange(false);
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
let animateFurnitureState = false;
let habbiconTimer: number = null;
const populate = () => {
switch (product.productType) {
case ProductTypeEnum.FLOOR: {
if (!product.furnitureData) {
roomPreviewer.reset(false);
return;
}
const furniData = GetSessionDataManager().getFloorItemData(product.furnitureData.id);
const isPurchasableClothing = product.furnitureData.specialType === FurniCategory.FIGURE_PURCHASABLE_SET;
if (isPurchasableClothing) {
const sessionDataManager = GetSessionDataManager();
const avatarRenderManager = GetAvatarRenderManager();
const customParams = furniData?.customParams ?? product.furnitureData.customParams ?? '';
const customParts = customParams
.split(',')
.map((value) => value.trim())
.filter((value) => /^\d+$/.test(value))
.map(Number);
const figureSets: number[] = [];
for (const part of customParts) {
if (!Number.isSafeInteger(part) || part <= 0) continue;
if (avatarRenderManager.isValidFigureSetForGender(part, sessionDataManager.gender)) figureSets.push(part);
}
const figureString = avatarRenderManager.getFigureStringWithFigureIds(sessionDataManager.figure, sessionDataManager.gender, figureSets);
roomPreviewer.updateObjectRoom(NEUTRAL_FLOOR, NEUTRAL_WALL, NEUTRAL_LANDSCAPE);
roomPreviewer.addAvatarIntoRoom(figureString || sessionDataManager.figure, 0);
roomPreviewer.zoomIn();
} else {
roomPreviewer.reset(true);
roomPreviewer.updateObjectRoom(NEUTRAL_FLOOR, NEUTRAL_WALL, NEUTRAL_LANDSCAPE);
roomPreviewer.addFurnitureIntoRoom(product.productClassId, new Vector3d(90), previewStuffData, product.extraParam);
animateFurnitureState = true;
}
return;
}
case ProductTypeEnum.WALL: {
if (!product.furnitureData) {
roomPreviewer.reset(false);
return;
}
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
switch (product.furnitureData.specialType) {
case FurniCategory.FLOOR:
roomPreviewer.reset(true);
roomPreviewer.updateObjectRoom(product.extraParam, NEUTRAL_WALL, NEUTRAL_LANDSCAPE);
return;
case FurniCategory.WALL_PAPER:
roomPreviewer.reset(true);
roomPreviewer.updateObjectRoom(NEUTRAL_FLOOR, product.extraParam, NEUTRAL_LANDSCAPE);
return;
case FurniCategory.LANDSCAPE: {
roomPreviewer.updateObjectRoom(NEUTRAL_FLOOR, NEUTRAL_WALL, product.extraParam);
const furniData = GetSessionDataManager().getWallItemDataByName('window_double_default');
if (furniData) roomPreviewer.addWallItemIntoRoom(furniData.id, new Vector3d(90), furniData.customParams);
else roomPreviewer.reset(false);
return;
}
default:
roomPreviewer.updateObjectRoom(NEUTRAL_FLOOR, NEUTRAL_WALL, NEUTRAL_LANDSCAPE);
roomPreviewer.addWallItemIntoRoom(product.productClassId, new Vector3d(90), product.extraParam);
animateFurnitureState = true;
return;
}
}
case ProductTypeEnum.ROBOT:
roomPreviewer.updateObjectRoom(NEUTRAL_FLOOR, NEUTRAL_WALL, NEUTRAL_LANDSCAPE);
roomPreviewer.addAvatarIntoRoom(product.extraParam, 0);
roomPreviewer.zoomIn();
return;
case ProductTypeEnum.HABBICON: {
// The own avatar with the habbicon above its head, the way the room shows it.
roomPreviewer.updateObjectRoom(NEUTRAL_FLOOR, NEUTRAL_WALL, NEUTRAL_LANDSCAPE);
roomPreviewer.addViewOffset.y = -(PREVIEW_LIFT + HABBICON_PREVIEW_EXTRA_LIFT);
roomPreviewer.addAvatarIntoRoom(GetSessionDataManager().figure, 0);
// Always the normal scale, whatever zoom an earlier preview or the zoom
// control left behind.
roomPreviewer.zoomIn();
let triggerSequence = 0;
const showHabbicon = () => {
const model = roomPreviewer.getRoomPreviewObject()?.model;
if (!model) return;
model.setValue(RoomObjectVariable.FIGURE_HABBICON, product.productClassId);
model.setValue(RoomObjectVariable.FIGURE_HABBICON_TRIGGER_SEQUENCE, ++triggerSequence);
};
showHabbicon();
habbiconTimer = window.setInterval(showHabbicon, HABBICON_PREVIEW_REPEAT_MS);
return;
}
case ProductTypeEnum.EFFECT:
roomPreviewer.updateObjectRoom(NEUTRAL_FLOOR, NEUTRAL_WALL, NEUTRAL_LANDSCAPE);
roomPreviewer.addAvatarIntoRoom(GetSessionDataManager().figure, product.productClassId);
roomPreviewer.zoomIn();
return;
default:
roomPreviewer.reset(false);
return;
}
};
populate();
roomPreviewer.setAutomaticStateChange(animateFurnitureState);
return () => {
if (habbiconTimer !== null) window.clearInterval(habbiconTimer);
clearViewOffset();
};
}, [currentOffer, previewStuffData, roomPreviewer]);
if (!currentOffer) return null;
if (currentOffer.pricingModel === Offer.PRICING_MODEL_BUNDLE) {
return (
<NativeTextTree>
<Column fit className="bg-muted p-2 rounded" overflow="hidden">
<AutoGrid fullWidth className="octane-catalog-layout-bundle-grid" columnCount={4}>
{currentOffer.products.length > 0 &&
currentOffer.products.map((product, index) => {
const iconUrl = GetProductIconUrl(product, currentOffer);
return (
<LayoutGridItem key={index} itemCount={product.productCount}>
{product.productType === ProductTypeEnum.HABBICON ? (
<LayoutHabbiconImageView id={product.productClassId} />
) : product.productType === ProductTypeEnum.CHAT_STYLE ? (
<LayoutChatStyleImageView styleId={product.extraParam} />
) : (
iconUrl && <img alt="" className="octane-catalog-grid-offer-icon" draggable={false} src={iconUrl} />
)}
</LayoutGridItem>
);
})}
</AutoGrid>
</Column>
</NativeTextTree>
);
}
return <LayoutRoomPreviewerView height={height} roomPreviewer={roomPreviewer} />;
};
