Update some stuff to use async

This commit is contained in:
Bill 2023-07-11 22:07:45 -04:00
parent f0049d6aa5
commit 3b4c443ea6
20 changed files with 237 additions and 167 deletions

View File

@ -189,7 +189,7 @@ export class AvatarEditorGridPartItem implements IAvatarImageListener
return container; return container;
} }
private updateThumbVisualization(): void private async updateThumbVisualization(): Promise<void>
{ {
if(!this._isInitalized) return; if(!this._isInitalized) return;
@ -212,7 +212,7 @@ export class AvatarEditorGridPartItem implements IAvatarImageListener
if(this._isDisabled) this.setAlpha(container, 0.2); if(this._isDisabled) this.setAlpha(container, 0.2);
this._imageUrl = TextureUtils.generateImageUrl(container); this._imageUrl = await TextureUtils.generateImageUrl(container);
if(this.notify) this.notify(); if(this.notify) this.notify();
} }

View File

@ -9,7 +9,6 @@ export class AvatarInfoFurni implements IAvatarInfo
public category: number = 0; public category: number = 0;
public name: string = ''; public name: string = '';
public description: string = ''; public description: string = '';
public image: HTMLImageElement = null;
public isWallItem: boolean = false; public isWallItem: boolean = false;
public isStickie: boolean = false; public isStickie: boolean = false;
public isRoomOwner: boolean = false; public isRoomOwner: boolean = false;

View File

@ -1,4 +1,4 @@
import { GetTickerTime, IFurnitureData, IRoomModerationSettings, IRoomPetData, IRoomUserData, ObjectDataFactory, PetFigureData, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectType, RoomObjectVariable, RoomTradingLevelEnum, RoomWidgetEnumItemExtradataParameter, Vector3d } from '@nitrots/nitro-renderer'; import { GetTickerTime, IFurnitureData, IRoomModerationSettings, IRoomPetData, IRoomUserData, ObjectDataFactory, PetFigureData, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectType, RoomObjectVariable, RoomTradingLevelEnum, RoomWidgetEnumItemExtradataParameter } from '@nitrots/nitro-renderer';
import { GetRoomEngine, GetRoomSession, GetSessionDataManager, IsOwnerOfFurniture } from '../../nitro'; import { GetRoomEngine, GetRoomSession, GetSessionDataManager, IsOwnerOfFurniture } from '../../nitro';
import { LocalizeText } from '../../utils'; import { LocalizeText } from '../../utils';
import { AvatarInfoFurni } from './AvatarInfoFurni'; import { AvatarInfoFurni } from './AvatarInfoFurni';
@ -72,24 +72,20 @@ export class AvatarInfoUtilities
public static getFurniInfo(objectId: number, category: number): AvatarInfoFurni public static getFurniInfo(objectId: number, category: number): AvatarInfoFurni
{ {
const roomSession = GetRoomSession(); const roomSession = GetRoomSession();
const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, objectId, category);
if(!roomObject) return null;
const furniInfo = new AvatarInfoFurni(AvatarInfoFurni.FURNI); const furniInfo = new AvatarInfoFurni(AvatarInfoFurni.FURNI);
furniInfo.id = objectId; furniInfo.id = objectId;
furniInfo.category = category; furniInfo.category = category;
const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, objectId, category);
if(!roomObject) return;
const model = roomObject.model; const model = roomObject.model;
if(model.getValue<string>(RoomWidgetEnumItemExtradataParameter.INFOSTAND_EXTRA_PARAM)) if(model.getValue<string>(RoomWidgetEnumItemExtradataParameter.INFOSTAND_EXTRA_PARAM)) furniInfo.extraParam = model.getValue<string>(RoomWidgetEnumItemExtradataParameter.INFOSTAND_EXTRA_PARAM);
{
furniInfo.extraParam = model.getValue<string>(RoomWidgetEnumItemExtradataParameter.INFOSTAND_EXTRA_PARAM);
}
const dataFormat = model.getValue<number>(RoomObjectVariable.FURNITURE_DATA_FORMAT); const objectData = ObjectDataFactory.getData(model.getValue<number>(RoomObjectVariable.FURNITURE_DATA_FORMAT));
const objectData = ObjectDataFactory.getData(dataFormat);
objectData.initializeFromRoomObjectModel(model); objectData.initializeFromRoomObjectModel(model);
@ -141,14 +137,14 @@ export class AvatarInfoUtilities
furniInfo.expiration = ((expiryTime < 0) ? expiryTime : Math.max(0, (expiryTime - ((GetTickerTime() - expiryTimestamp) / 1000)))); furniInfo.expiration = ((expiryTime < 0) ? expiryTime : Math.max(0, (expiryTime - ((GetTickerTime() - expiryTimestamp) / 1000))));
let roomObjectImage = GetRoomEngine().getRoomObjectImage(roomSession.roomId, objectId, category, new Vector3d(180), 64, null); /* let roomObjectImage = GetRoomEngine().getRoomObjectImage(roomSession.roomId, objectId, category, new Vector3d(180), 64, null);
if(!roomObjectImage.data || (roomObjectImage.data.width > 140) || (roomObjectImage.data.height > 200)) if(!roomObjectImage.data || (roomObjectImage.data.width > 140) || (roomObjectImage.data.height > 200))
{ {
roomObjectImage = GetRoomEngine().getRoomObjectImage(roomSession.roomId, objectId, category, new Vector3d(180), 1, null); roomObjectImage = GetRoomEngine().getRoomObjectImage(roomSession.roomId, objectId, category, new Vector3d(180), 1, null);
} }
furniInfo.image = roomObjectImage.getImage(); furniInfo.image = roomObjectImage.getImage(); */
furniInfo.isWallItem = (category === RoomObjectCategory.WALL); furniInfo.isWallItem = (category === RoomObjectCategory.WALL);
furniInfo.isRoomOwner = roomSession.isRoomOwner; furniInfo.isRoomOwner = roomSession.isRoomOwner;
furniInfo.roomControllerLevel = roomSession.controllerLevel; furniInfo.roomControllerLevel = roomSession.controllerLevel;
@ -159,11 +155,7 @@ export class AvatarInfoUtilities
const guildId = model.getValue<number>(RoomObjectVariable.FURNITURE_GUILD_CUSTOMIZED_GUILD_ID); const guildId = model.getValue<number>(RoomObjectVariable.FURNITURE_GUILD_CUSTOMIZED_GUILD_ID);
if(guildId !== 0) if(guildId !== 0) furniInfo.groupId = guildId;
{
furniInfo.groupId = guildId;
//this.container.connection.send(new GroupInformationComposer(guildId, false));
}
if(IsOwnerOfFurniture(roomObject)) furniInfo.isOwner = true; if(IsOwnerOfFurniture(roomObject)) furniInfo.isOwner = true;
@ -174,11 +166,7 @@ export class AvatarInfoUtilities
{ {
const roomSession = GetRoomSession(); const roomSession = GetRoomSession();
let userInfoType = AvatarInfoUser.OWN_USER; const userInfo = new AvatarInfoUser((userData.webID === GetSessionDataManager().userId) ? AvatarInfoUser.OWN_USER : AvatarInfoUser.PEER);
if(userData.webID !== GetSessionDataManager().userId) userInfoType = AvatarInfoUser.PEER;
const userInfo = new AvatarInfoUser(userInfoType);
userInfo.isSpectatorMode = roomSession.isSpectator; userInfo.isSpectatorMode = roomSession.isSpectator;
userInfo.name = userData.name; userInfo.name = userData.name;
@ -192,7 +180,7 @@ export class AvatarInfoUtilities
if(roomObject) userInfo.carryItem = (roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_CARRY_OBJECT) || 0); if(roomObject) userInfo.carryItem = (roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_CARRY_OBJECT) || 0);
if(userInfoType === AvatarInfoUser.OWN_USER) userInfo.allowNameChange = GetSessionDataManager().canChangeName; if(userInfo.type === AvatarInfoUser.OWN_USER) userInfo.allowNameChange = GetSessionDataManager().canChangeName;
userInfo.amIOwner = roomSession.isRoomOwner; userInfo.amIOwner = roomSession.isRoomOwner;
userInfo.isGuildRoom = roomSession.isGuildRoom; userInfo.isGuildRoom = roomSession.isGuildRoom;
@ -200,14 +188,11 @@ export class AvatarInfoUtilities
userInfo.amIAnyRoomController = GetSessionDataManager().isModerator; userInfo.amIAnyRoomController = GetSessionDataManager().isModerator;
userInfo.isAmbassador = GetSessionDataManager().isAmbassador; userInfo.isAmbassador = GetSessionDataManager().isAmbassador;
if(userInfoType === AvatarInfoUser.PEER) if(userInfo.type === AvatarInfoUser.PEER)
{ {
if(roomObject) if(roomObject)
{ {
const flatControl = roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_FLAT_CONTROL); userInfo.targetRoomControllerLevel = roomObject.model.getValue<number>(RoomObjectVariable.FIGURE_FLAT_CONTROL);
if(flatControl !== null) userInfo.targetRoomControllerLevel = flatControl;
userInfo.canBeMuted = this.canBeMuted(userInfo); userInfo.canBeMuted = this.canBeMuted(userInfo);
userInfo.canBeKicked = this.canBeKicked(userInfo); userInfo.canBeKicked = this.canBeKicked(userInfo);
userInfo.canBeBanned = this.canBeBanned(userInfo); userInfo.canBeBanned = this.canBeBanned(userInfo);
@ -234,7 +219,7 @@ export class AvatarInfoUtilities
userInfo.canTrade = (roomController || targetController); userInfo.canTrade = (roomController || targetController);
break; break;
} }
case RoomTradingLevelEnum.NO_TRADING: case RoomTradingLevelEnum.FREE_TRADING:
userInfo.canTrade = true; userInfo.canTrade = true;
break; break;
default: default:

View File

@ -0,0 +1,70 @@
import { AvatarFigurePartType, AvatarScaleType, AvatarSetType, PetFigureData, TextureUtils, Vector3d } from '@nitrots/nitro-renderer';
import { GetAvatarRenderManager, GetRoomEngine } from '../../nitro';
export class ChatBubbleUtilities
{
public static AVATAR_COLOR_CACHE: Map<string, number> = new Map();
public static AVATAR_IMAGE_CACHE: Map<string, string> = new Map();
public static PET_IMAGE_CACHE: Map<string, string> = new Map();
private static placeHolderImageUrl: string = '';
public static async setFigureImage(figure: string): Promise<string>
{
const avatarImage = GetAvatarRenderManager().createAvatarImage(figure, AvatarScaleType.LARGE, null, {
resetFigure: figure => this.setFigureImage(figure),
dispose: () =>
{},
disposed: false
});
if(!avatarImage) return null;
const isPlaceholder = avatarImage.isPlaceholder();
if(isPlaceholder && this.placeHolderImageUrl?.length) return this.placeHolderImageUrl;
figure = avatarImage.getFigure().getFigureString();
const image = await avatarImage.getCroppedImage(AvatarSetType.HEAD);
const color = avatarImage.getPartColor(AvatarFigurePartType.CHEST);
if(isPlaceholder) this.placeHolderImageUrl = image.src;
this.AVATAR_COLOR_CACHE.set(figure, ((color && color.rgb) || 16777215));
this.AVATAR_IMAGE_CACHE.set(figure, image.src);
avatarImage.dispose();
return image.src;
}
public static async getUserImage(figure: string): Promise<string>
{
let existing = this.AVATAR_IMAGE_CACHE.get(figure);
if(!existing) existing = await this.setFigureImage(figure);
return existing;
}
public static async getPetImage(figure: string, direction: number, _arg_3: boolean, scale: number = 64, posture: string = null)
{
let existing = this.PET_IMAGE_CACHE.get((figure + posture));
if(existing) return existing;
const figureData = new PetFigureData(figure);
const typeId = figureData.typeId;
const image = GetRoomEngine().getRoomObjectPetImage(typeId, figureData.paletteId, figureData.color, new Vector3d((direction * 45)), scale, null, false, 0, figureData.customParts, posture);
if(image)
{
existing = await TextureUtils.generateImageUrl(image.data);
this.PET_IMAGE_CACHE.set((figure + posture), existing);
}
return existing;
}
}

View File

@ -6,6 +6,7 @@ export * from './AvatarInfoUser';
export * from './AvatarInfoUtilities'; export * from './AvatarInfoUtilities';
export * from './BotSkillsEnum'; export * from './BotSkillsEnum';
export * from './ChatBubbleMessage'; export * from './ChatBubbleMessage';
export * from './ChatBubbleUtilities';
export * from './ChatMessageTypeEnum'; export * from './ChatMessageTypeEnum';
export * from './DimmerFurnitureWidgetPresetItem'; export * from './DimmerFurnitureWidgetPresetItem';
export * from './DoChatsOverlap'; export * from './DoChatsOverlap';

View File

@ -280,7 +280,8 @@
} }
} }
.furni-image { .furni-image,
.room-object-image {
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@ -68,11 +68,14 @@ export const LayoutAvatarImageView: FC<LayoutAvatarImageViewProps> = props =>
avatarImage.setDirection(setType, direction); avatarImage.setDirection(setType, direction);
const image = avatarImage.getCroppedImage(setType); (async () =>
{
const image = await avatarImage.getCroppedImage(setType);
if(image) setAvatarUrl(image.src); if(image) setAvatarUrl(image.src);
avatarImage.dispose(); avatarImage.dispose();
})();
}, [ figure, gender, direction, headOnly, randomValue ]); }, [ figure, gender, direction, headOnly, randomValue ]);
useEffect(() => useEffect(() =>

View File

@ -37,7 +37,7 @@ export const LayoutBadgeImageView: FC<LayoutBadgeImageViewProps> = props =>
if(imageElement) if(imageElement)
{ {
newStyle.backgroundImage = `url(${ (isGroup) ? imageElement.src : GetConfiguration<string>('badge.asset.url').replace('%badgename%', badgeCode.toString())})`; newStyle.backgroundImage = `url(${ (isGroup) ? imageElement.src : GetConfiguration<string>('badge.asset.url').replace('%badgename%', badgeCode.toString()) })`;
newStyle.width = imageElement.width; newStyle.width = imageElement.width;
newStyle.height = imageElement.height; newStyle.height = imageElement.height;
@ -55,7 +55,7 @@ export const LayoutBadgeImageView: FC<LayoutBadgeImageViewProps> = props =>
if(Object.keys(style).length) newStyle = { ...newStyle, ...style }; if(Object.keys(style).length) newStyle = { ...newStyle, ...style };
return newStyle; return newStyle;
}, [ imageElement, scale, style ]); }, [ badgeCode, isGroup, imageElement, scale, style ]);
useEffect(() => useEffect(() =>
{ {
@ -63,11 +63,11 @@ export const LayoutBadgeImageView: FC<LayoutBadgeImageViewProps> = props =>
let didSetBadge = false; let didSetBadge = false;
const onBadgeImageReadyEvent = (event: BadgeImageReadyEvent) => const onBadgeImageReadyEvent = async (event: BadgeImageReadyEvent) =>
{ {
if(event.badgeId !== badgeCode) return; if(event.badgeId !== badgeCode) return;
const element = TextureUtils.generateImage(new NitroSprite(event.image)); const element = await TextureUtils.generateImage(new NitroSprite(event.image));
element.onload = () => setImageElement(element); element.onload = () => setImageElement(element);
@ -82,9 +82,12 @@ export const LayoutBadgeImageView: FC<LayoutBadgeImageViewProps> = props =>
if(texture && !didSetBadge) if(texture && !didSetBadge)
{ {
const element = TextureUtils.generateImage(new NitroSprite(texture)); (async () =>
{
const element = await TextureUtils.generateImage(new NitroSprite(texture));
element.onload = () => setImageElement(element); element.onload = () => setImageElement(element);
})();
} }
return () => GetSessionDataManager().events.removeEventListener(BadgeImageReadyEvent.IMAGE_READY, onBadgeImageReadyEvent); return () => GetSessionDataManager().events.removeEventListener(BadgeImageReadyEvent.IMAGE_READY, onBadgeImageReadyEvent);

View File

@ -46,15 +46,7 @@ export const LayoutFurniImageView: FC<LayoutFurniImageViewProps> = props =>
let imageResult: ImageResult = null; let imageResult: ImageResult = null;
const listener: IGetImageListener = { const listener: IGetImageListener = {
imageReady: (id, texture, image) => imageReady: async (id, texture, image) => setImageElement(await TextureUtils.generateImage(texture)),
{
if(!image && texture)
{
image = TextureUtils.generateImage(texture);
}
image.onload = () => setImageElement(image);
},
imageFailed: null imageFailed: null
}; };
@ -68,12 +60,9 @@ export const LayoutFurniImageView: FC<LayoutFurniImageViewProps> = props =>
break; break;
} }
if(imageResult) if(!imageResult) return;
{
const image = imageResult.getImage();
image.onload = () => setImageElement(image); (async () => setImageElement(await TextureUtils.generateImage(imageResult.data)))();
}
}, [ productType, productClassId, direction, extraData ]); }, [ productType, productClassId, direction, extraData ]);
if(!imageElement) return null; if(!imageElement) return null;

View File

@ -6,7 +6,7 @@ import { DraggableWindow } from '../draggable-window';
interface LayoutMiniCameraViewProps interface LayoutMiniCameraViewProps
{ {
roomId: number; roomId: number;
textureReceiver: (texture: NitroRenderTexture) => void; textureReceiver: (texture: NitroRenderTexture) => Promise<void>;
onClose: () => void; onClose: () => void;
} }

View File

@ -68,7 +68,7 @@ export const LayoutPetImageView: FC<LayoutPetImageViewProps> = props =>
if(petTypeId === 16) petHeadOnly = false; if(petTypeId === 16) petHeadOnly = false;
const imageResult = GetRoomEngine().getRoomObjectPetImage(petTypeId, petPaletteId, petColor1, new Vector3d((direction * 45)), 64, { const imageResult = GetRoomEngine().getRoomObjectPetImage(petTypeId, petPaletteId, petColor1, new Vector3d((direction * 45)), 64, {
imageReady: (id, texture, image) => imageReady: async (id, texture, image) =>
{ {
if(isDisposed.current) return; if(isDisposed.current) return;
@ -81,7 +81,7 @@ export const LayoutPetImageView: FC<LayoutPetImageViewProps> = props =>
else if(texture) else if(texture)
{ {
setPetUrl(TextureUtils.generateImageUrl(texture)); setPetUrl(await TextureUtils.generateImageUrl(texture));
setWidth(texture.width); setWidth(texture.width);
setHeight(texture.height); setHeight(texture.height);
} }
@ -94,14 +94,17 @@ export const LayoutPetImageView: FC<LayoutPetImageViewProps> = props =>
if(imageResult) if(imageResult)
{ {
const image = imageResult.getImage(); (async () =>
if(image)
{ {
setPetUrl(image.src); const image = await imageResult.getImage();
setWidth(image.width);
setHeight(image.height); if(image)
} {
setPetUrl(image.src);
setWidth(image.width);
setHeight(image.height);
}
})();
} }
}, [ figure, typeId, paletteId, petColor, customParts, posture, headOnly, direction ]); }, [ figure, typeId, paletteId, petColor, customParts, posture, headOnly, direction ]);

View File

@ -0,0 +1,61 @@
import { TextureUtils, Vector3d } from '@nitrots/nitro-renderer';
import { CSSProperties, FC, useEffect, useMemo, useState } from 'react';
import { BaseProps } from '..';
import { GetRoomEngine } from '../../api';
import { Base } from '../Base';
interface LayoutRoomObjectImageViewProps extends BaseProps<HTMLDivElement>
{
roomId: number;
objectId: number;
category: number;
direction?: number;
scale?: number;
}
export const LayoutRoomObjectImageView: FC<LayoutRoomObjectImageViewProps> = props =>
{
const { roomId = -1, objectId = 1, category = -1, direction = 2, scale = 1, style = {}, ...rest } = props;
const [ imageElement, setImageElement ] = useState<HTMLImageElement>(null);
const getStyle = useMemo(() =>
{
let newStyle: CSSProperties = {};
if(imageElement?.src?.length)
{
newStyle.backgroundImage = `url('${ imageElement.src }')`;
newStyle.width = imageElement.width;
newStyle.height = imageElement.height;
}
if(scale !== 1)
{
newStyle.transform = `scale(${ scale })`;
if(!(scale % 1)) newStyle.imageRendering = 'pixelated';
}
if(Object.keys(style).length) newStyle = { ...newStyle, ...style };
return newStyle;
}, [ imageElement, scale, style ]);
useEffect(() =>
{
const imageResult = GetRoomEngine().getRoomObjectImage(roomId, objectId, category, new Vector3d(direction * 45), 64, {
imageReady: async (id, texture, image) => setImageElement(await TextureUtils.generateImage(texture)),
imageFailed: null
});
// needs (roomObjectImage.data.width > 140) || (roomObjectImage.data.height > 200) scale 1
if(!imageResult) return;
(async () => setImageElement(await TextureUtils.generateImage(imageResult.data)))();
}, [ roomId, objectId, category, direction, scale ]);
if(!imageElement) return null;
return <Base classNames={ [ 'furni-image' ] } style={ getStyle } { ...rest } />;
}

View File

@ -26,7 +26,7 @@ export const LayoutRoomPreviewerView: FC<LayoutRoomPreviewerViewProps> = props =
{ {
if(!roomPreviewer) return; if(!roomPreviewer) return;
const update = (time: number) => const update = async (time: number) =>
{ {
if(!roomPreviewer || !renderingCanvas || !elementRef.current) return; if(!roomPreviewer || !renderingCanvas || !elementRef.current) return;
@ -34,7 +34,7 @@ export const LayoutRoomPreviewerView: FC<LayoutRoomPreviewerViewProps> = props =
if(!renderingCanvas.canvasUpdated) return; if(!renderingCanvas.canvasUpdated) return;
elementRef.current.style.backgroundImage = `url(${ TextureUtils.generateImageUrl(renderingCanvas.master) })`; elementRef.current.style.backgroundImage = `url(${ await TextureUtils.generateImageUrl(renderingCanvas.master) })`;
} }
if(!renderingCanvas) if(!renderingCanvas)

View File

@ -16,8 +16,9 @@ export * from './LayoutNotificationBubbleView';
export * from './LayoutPetImageView'; export * from './LayoutPetImageView';
export * from './LayoutProgressBar'; export * from './LayoutProgressBar';
export * from './LayoutRarityLevelView'; export * from './LayoutRarityLevelView';
export * from './LayoutRoomObjectImageView';
export * from './LayoutRoomPreviewerView'; export * from './LayoutRoomPreviewerView';
export * from './LayoutRoomThumbnailView'; export * from './LayoutRoomThumbnailView';
export * from './LayoutTrophyView'; export * from './LayoutTrophyView';
export * from './limited-edition';
export * from './UserProfileIconView'; export * from './UserProfileIconView';
export * from './limited-edition';

View File

@ -32,7 +32,7 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
return new NitroRectangle(Math.floor(frameBounds.x), Math.floor(frameBounds.y), Math.floor(frameBounds.width), Math.floor(frameBounds.height)); return new NitroRectangle(Math.floor(frameBounds.x), Math.floor(frameBounds.y), Math.floor(frameBounds.width), Math.floor(frameBounds.height));
} }
const takePicture = () => const takePicture = async () =>
{ {
if(selectedPictureIndex > -1) if(selectedPictureIndex > -1)
{ {
@ -52,7 +52,7 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
} }
PlaySound(SoundNames.CAMERA_SHUTTER); PlaySound(SoundNames.CAMERA_SHUTTER);
clone.push(new CameraPicture(texture, TextureUtils.generateImageUrl(texture))); clone.push(new CameraPicture(texture, await TextureUtils.generateImageUrl(texture)));
setCameraRoll(clone); setCameraRoll(clone);
} }

View File

@ -26,6 +26,7 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
const [ selectedEffects, setSelectedEffects ] = useState<IRoomCameraWidgetSelectedEffect[]>([]); const [ selectedEffects, setSelectedEffects ] = useState<IRoomCameraWidgetSelectedEffect[]>([]);
const [ effectsThumbnails, setEffectsThumbnails ] = useState<CameraPictureThumbnail[]>([]); const [ effectsThumbnails, setEffectsThumbnails ] = useState<CameraPictureThumbnail[]>([]);
const [ isZoomed, setIsZoomed ] = useState(false); const [ isZoomed, setIsZoomed ] = useState(false);
const [ currentPictureUrl, setCurrentPictureUrl ] = useState<string>('');
const getColorMatrixEffects = useMemo(() => const getColorMatrixEffects = useMemo(() =>
{ {
@ -83,11 +84,6 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
}); });
}, [ getCurrentEffectIndex, setSelectedEffects ]); }, [ getCurrentEffectIndex, setSelectedEffects ]);
const getCurrentPictureUrl = useMemo(() =>
{
return GetRoomCameraWidgetManager().applyEffects(picture.texture, selectedEffects, isZoomed).src;
}, [ picture, selectedEffects, isZoomed ]);
const processAction = useCallback((type: string, effectName: string = null) => const processAction = useCallback((type: string, effectName: string = null) =>
{ {
switch(type) switch(type)
@ -99,7 +95,7 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
onCancel(); onCancel();
return; return;
case 'checkout': case 'checkout':
onCheckout(getCurrentPictureUrl); onCheckout(currentPictureUrl);
return; return;
case 'change_tab': case 'change_tab':
setCurrentTab(String(effectName)); setCurrentTab(String(effectName));
@ -143,32 +139,50 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
setSelectedEffects([]); setSelectedEffects([]);
return; return;
case 'download': { case 'download': {
const image = new Image(); (async () =>
{
const image = new Image();
image.src = getCurrentPictureUrl image.src = currentPictureUrl
const newWindow = window.open(''); const newWindow = window.open('');
newWindow.document.write(image.outerHTML); newWindow.document.write(image.outerHTML);
})();
return; return;
} }
case 'zoom': case 'zoom':
setIsZoomed(!isZoomed); setIsZoomed(!isZoomed);
return; return;
} }
}, [ isZoomed, availableEffects, selectedEffectName, getCurrentPictureUrl, getSelectedEffectIndex, onCancel, onCheckout, onClose, setIsZoomed, setSelectedEffects ]); }, [ isZoomed, availableEffects, selectedEffectName, currentPictureUrl, getSelectedEffectIndex, onCancel, onCheckout, onClose, setIsZoomed, setSelectedEffects ]);
useEffect(() => useEffect(() =>
{ {
const thumbnails: CameraPictureThumbnail[] = []; (async () =>
for(const effect of availableEffects)
{ {
thumbnails.push(new CameraPictureThumbnail(effect.name, GetRoomCameraWidgetManager().applyEffects(picture.texture, [ new RoomCameraWidgetSelectedEffect(effect, 1) ], false).src)); const thumbnails: CameraPictureThumbnail[] = [];
}
setEffectsThumbnails(thumbnails); for await (const effect of availableEffects)
{
const image = await GetRoomCameraWidgetManager().applyEffects(picture.texture, [ new RoomCameraWidgetSelectedEffect(effect, 1) ], false);
thumbnails.push(new CameraPictureThumbnail(effect.name, image.src));
}
setEffectsThumbnails(thumbnails);
})();
}, [ picture, availableEffects ]); }, [ picture, availableEffects ]);
useEffect(() =>
{
(async () =>
{
const imageUrl = await GetRoomCameraWidgetManager().applyEffects(picture.texture, selectedEffects, isZoomed);
setCurrentPictureUrl(imageUrl.src);
})();
}, [ picture, selectedEffects, isZoomed ]);
return ( return (
<NitroCardView className="nitro-camera-editor"> <NitroCardView className="nitro-camera-editor">
<NitroCardHeaderView headerText={ LocalizeText('camera.editor.button.text') } onCloseClick={ event => processAction('close') } /> <NitroCardHeaderView headerText={ LocalizeText('camera.editor.button.text') } onCloseClick={ event => processAction('close') } />
@ -185,7 +199,7 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
</Column> </Column>
<Column size={ 7 } justifyContent="between" overflow="hidden"> <Column size={ 7 } justifyContent="between" overflow="hidden">
<Column center> <Column center>
<LayoutImage imageUrl={ getCurrentPictureUrl } className="picture-preview" /> <LayoutImage imageUrl={ currentPictureUrl } className="picture-preview" />
{ selectedEffectName && { selectedEffectName &&
<Column center fullWidth gap={ 1 }> <Column center fullWidth gap={ 1 }>
<Text>{ LocalizeText('camera.effect.name.' + selectedEffectName) }</Text> <Text>{ LocalizeText('camera.effect.name.' + selectedEffectName) }</Text>

View File

@ -2,7 +2,7 @@ import { CrackableDataType, GroupInformationComposer, GroupInformationEvent, Now
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { FaTimes } from 'react-icons/fa'; import { FaTimes } from 'react-icons/fa';
import { AvatarInfoFurni, CreateLinkEvent, GetGroupInformation, GetNitroInstance, GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../../api'; import { AvatarInfoFurni, CreateLinkEvent, GetGroupInformation, GetNitroInstance, GetRoomEngine, LocalizeText, SendMessageComposer } from '../../../../../api';
import { Base, Button, Column, Flex, LayoutBadgeImageView, LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, Text, UserProfileIconView } from '../../../../../common'; import { Base, Button, Column, Flex, LayoutBadgeImageView, LayoutLimitedEditionCompactPlateView, LayoutRarityLevelView, LayoutRoomObjectImageView, Text, UserProfileIconView } from '../../../../../common';
import { useMessageEvent, useRoom, useSoundEvent } from '../../../../../hooks'; import { useMessageEvent, useRoom, useSoundEvent } from '../../../../../hooks';
interface InfoStandWidgetFurniViewProps interface InfoStandWidgetFurniViewProps
@ -347,8 +347,9 @@ export const InfoStandWidgetFurniView: FC<InfoStandWidgetFurniViewProps> = props
<div className="position-absolute end-0"> <div className="position-absolute end-0">
<LayoutRarityLevelView level={ avatarInfo.stuffData.rarityLevel } /> <LayoutRarityLevelView level={ avatarInfo.stuffData.rarityLevel } />
</div> } </div> }
{ avatarInfo.image && avatarInfo.image.src.length && <Flex fullWidth center>
<img className="d-block mx-auto" src={ avatarInfo.image.src } alt="" /> } <LayoutRoomObjectImageView roomId={ roomSession.roomId } objectId={ avatarInfo.id } category={ avatarInfo.category } />
</Flex>
</Flex> </Flex>
<hr className="m-0" /> <hr className="m-0" />
</Column> </Column>

View File

@ -29,9 +29,9 @@ export const RoomThumbnailWidgetView: FC<{}> = props =>
} }
}); });
const receiveTexture = (texture: NitroRenderTexture) => const receiveTexture = async (texture: NitroRenderTexture) =>
{ {
GetRoomEngine().saveTextureAsScreenshot(texture, true); await GetRoomEngine().saveTextureAsScreenshot(texture, true);
setIsVisible(false); setIsVisible(false);
} }

View File

@ -258,7 +258,7 @@ const useNotificationState = () =>
simpleAlert( LocalizeText(('opening.hours.' + (parser.userThrowOutAtClose ? 'disconnected' : 'closed')), [ 'h', 'm' ], [ getTimeZeroPadded(parser.openHour), getTimeZeroPadded(parser.openMinute) ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title')); simpleAlert( LocalizeText(('opening.hours.' + (parser.userThrowOutAtClose ? 'disconnected' : 'closed')), [ 'h', 'm' ], [ getTimeZeroPadded(parser.openHour), getTimeZeroPadded(parser.openMinute) ]), NotificationAlertType.DEFAULT, null, null, LocalizeText('opening.hours.title'));
}); });
useMessageEvent<PetReceivedMessageEvent>(PetReceivedMessageEvent, event => useMessageEvent<PetReceivedMessageEvent>(PetReceivedMessageEvent, async event =>
{ {
const parser = event.getParser(); const parser = event.getParser();
@ -268,7 +268,7 @@ const useNotificationState = () =>
const imageResult = GetRoomEngine().getRoomObjectPetImage(parser.pet.typeId, parser.pet.paletteId, parseInt(parser.pet.color, 16), new Vector3d(45 * 3), 64, null, true); const imageResult = GetRoomEngine().getRoomObjectPetImage(parser.pet.typeId, parser.pet.paletteId, parseInt(parser.pet.color, 16), new Vector3d(45 * 3), 64, null, true);
if(imageResult) imageUrl = imageResult.getImage().src; if(imageResult) imageUrl = (await imageResult.getImage())?.src;
showSingleBubble(text, NotificationBubbleType.PETLEVEL, imageUrl); showSingleBubble(text, NotificationBubbleType.PETLEVEL, imageUrl);
}); });
@ -284,7 +284,7 @@ const useNotificationState = () =>
setAlerts(prevValue => [ alertItem, ...prevValue ]); setAlerts(prevValue => [ alertItem, ...prevValue ]);
}); });
useMessageEvent<PetLevelNotificationEvent>(PetLevelNotificationEvent, event => useMessageEvent<PetLevelNotificationEvent>(PetLevelNotificationEvent, async event =>
{ {
const parser = event.getParser(); const parser = event.getParser();
@ -292,7 +292,7 @@ const useNotificationState = () =>
const imageResult = GetRoomEngine().getRoomObjectPetImage(parser.figureData.typeId, parser.figureData.paletteId, parseInt(parser.figureData.color, 16), new Vector3d(45 * 3), 64, null, true); const imageResult = GetRoomEngine().getRoomObjectPetImage(parser.figureData.typeId, parser.figureData.paletteId, parseInt(parser.figureData.color, 16), new Vector3d(45 * 3), 64, null, true);
if(imageResult) imageUrl = imageResult.getImage().src; if(imageResult) imageUrl = (await imageResult.getImage())?.src;
showSingleBubble(LocalizeText('notifications.text.petlevel', [ 'pet_name', 'level' ], [ parser.petName, parser.level.toString() ]), NotificationBubbleType.PETLEVEL, imageUrl); showSingleBubble(LocalizeText('notifications.text.petlevel', [ 'pet_name', 'level' ], [ parser.petName, parser.level.toString() ]), NotificationBubbleType.PETLEVEL, imageUrl);
}); });

View File

@ -1,14 +1,10 @@
import { AvatarFigurePartType, AvatarScaleType, AvatarSetType, GetGuestRoomResultEvent, NitroPoint, PetFigureData, RoomChatSettings, RoomChatSettingsEvent, RoomDragEvent, RoomObjectCategory, RoomObjectType, RoomObjectVariable, RoomSessionChatEvent, RoomUserData, SystemChatStyleEnum, TextureUtils, Vector3d } from '@nitrots/nitro-renderer'; import { GetGuestRoomResultEvent, NitroPoint, PetFigureData, RoomChatSettings, RoomChatSettingsEvent, RoomDragEvent, RoomObjectCategory, RoomObjectType, RoomObjectVariable, RoomSessionChatEvent, RoomUserData, SystemChatStyleEnum } from '@nitrots/nitro-renderer';
import { useEffect, useMemo, useRef, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import { ChatBubbleMessage, ChatEntryType, ChatHistoryCurrentDate, GetAvatarRenderManager, GetConfiguration, GetRoomEngine, GetRoomObjectScreenLocation, IRoomChatSettings, LocalizeText, PlaySound, RoomChatFormatter } from '../../../api'; import { ChatBubbleMessage, ChatBubbleUtilities, ChatEntryType, ChatHistoryCurrentDate, GetConfiguration, GetRoomEngine, GetRoomObjectScreenLocation, IRoomChatSettings, LocalizeText, PlaySound, RoomChatFormatter } from '../../../api';
import { useMessageEvent, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../events'; import { useMessageEvent, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../events';
import { useRoom } from '../useRoom'; import { useRoom } from '../useRoom';
import { useChatHistory } from './../../chat-history'; import { useChatHistory } from './../../chat-history';
const avatarColorCache: Map<string, number> = new Map();
const avatarImageCache: Map<string, string> = new Map();
const petImageCache: Map<string, string> = new Map();
const useChatWidgetState = () => const useChatWidgetState = () =>
{ {
const [ chatMessages, setChatMessages ] = useState<ChatBubbleMessage[]>([]); const [ chatMessages, setChatMessages ] = useState<ChatBubbleMessage[]>([]);
@ -38,64 +34,7 @@ const useChatWidgetState = () =>
} }
}, [ chatSettings ]); }, [ chatSettings ]);
const setFigureImage = (figure: string) => useRoomSessionManagerEvent<RoomSessionChatEvent>(RoomSessionChatEvent.CHAT_EVENT, async event =>
{
const avatarImage = GetAvatarRenderManager().createAvatarImage(figure, AvatarScaleType.LARGE, null, {
resetFigure: figure =>
{
if(isDisposed.current) return;
setFigureImage(figure);
},
dispose: () =>
{},
disposed: false
});
if(!avatarImage) return;
const image = avatarImage.getCroppedImage(AvatarSetType.HEAD);
const color = avatarImage.getPartColor(AvatarFigurePartType.CHEST);
avatarColorCache.set(figure, ((color && color.rgb) || 16777215));
avatarImage.dispose();
avatarImageCache.set(figure, image.src);
return image.src;
}
const getUserImage = (figure: string) =>
{
let existing = avatarImageCache.get(figure);
if(!existing) existing = setFigureImage(figure);
return existing;
}
const getPetImage = (figure: string, direction: number, _arg_3: boolean, scale: number = 64, posture: string = null) =>
{
let existing = petImageCache.get((figure + posture));
if(existing) return existing;
const figureData = new PetFigureData(figure);
const typeId = figureData.typeId;
const image = GetRoomEngine().getRoomObjectPetImage(typeId, figureData.paletteId, figureData.color, new Vector3d((direction * 45)), scale, null, false, 0, figureData.customParts, posture);
if(image)
{
existing = TextureUtils.generateImageUrl(image.data);
petImageCache.set((figure + posture), existing);
}
return existing;
}
useRoomSessionManagerEvent<RoomSessionChatEvent>(RoomSessionChatEvent.CHAT_EVENT, event =>
{ {
const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, event.objectId, RoomObjectCategory.UNIT); const roomObject = GetRoomEngine().getRoomObject(roomSession.roomId, event.objectId, RoomObjectCategory.UNIT);
const bubbleLocation = roomObject ? GetRoomObjectScreenLocation(roomSession.roomId, roomObject?.id, RoomObjectCategory.UNIT) : new NitroPoint(); const bubbleLocation = roomObject ? GetRoomObjectScreenLocation(roomSession.roomId, roomObject?.id, RoomObjectCategory.UNIT) : new NitroPoint();
@ -119,11 +58,11 @@ const useChatWidgetState = () =>
switch(userType) switch(userType)
{ {
case RoomObjectType.PET: case RoomObjectType.PET:
imageUrl = getPetImage(figure, 2, true, 64, roomObject.model.getValue<string>(RoomObjectVariable.FIGURE_POSTURE)); imageUrl = await ChatBubbleUtilities.getPetImage(figure, 2, true, 64, roomObject.model.getValue<string>(RoomObjectVariable.FIGURE_POSTURE));
petType = new PetFigureData(figure).typeId; petType = new PetFigureData(figure).typeId;
break; break;
case RoomObjectType.USER: case RoomObjectType.USER:
imageUrl = getUserImage(figure); imageUrl = await ChatBubbleUtilities.getUserImage(figure);
break; break;
case RoomObjectType.RENTABLE_BOT: case RoomObjectType.RENTABLE_BOT:
case RoomObjectType.BOT: case RoomObjectType.BOT:
@ -131,7 +70,7 @@ const useChatWidgetState = () =>
break; break;
} }
avatarColor = avatarColorCache.get(figure); avatarColor = ChatBubbleUtilities.AVATAR_COLOR_CACHE.get(figure);
username = userData.name; username = userData.name;
} }