mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 23:16:21 +00:00
Merge branch 'Dev' into feat/wired-fixes-apr08
This commit is contained in:
@@ -80,12 +80,10 @@ export const DraggableWindow: FC<DraggableWindowProps> = props => {
|
||||
const windowHeight = elementRef.current.offsetHeight;
|
||||
const viewportWidth = window.innerWidth;
|
||||
const viewportHeight = window.innerHeight;
|
||||
|
||||
const maxOutX = windowWidth * DRAG_OUTSIDE_PERCENT;
|
||||
const maxOutY = windowHeight * DRAG_OUTSIDE_PERCENT;
|
||||
|
||||
const clampedX = Math.max(-maxOutX, Math.min(newX, viewportWidth - windowWidth + maxOutX));
|
||||
const clampedY = Math.max(-maxOutY, Math.min(newY, viewportHeight - windowHeight + maxOutY));
|
||||
const clampedY = Math.max(BOUNDS_THRESHOLD_TOP, Math.min(newY, viewportHeight - windowHeight + maxOutY));
|
||||
|
||||
return { x: clampedX, y: clampedY };
|
||||
}, []);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { AvatarScaleType, AvatarSetType, GetAvatarRenderManager, NitroEventType } from '@nitrots/nitro-renderer';
|
||||
import { AvatarScaleType, AvatarSetType, GetAvatarRenderManager } from '@nitrots/nitro-renderer';
|
||||
import { CSSProperties, FC, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Base, BaseProps } from '../Base';
|
||||
import { useNitroEvent } from '../../hooks/events';
|
||||
|
||||
const AVATAR_CACHE_MAX_SIZE = 200;
|
||||
const AVATAR_IMAGE_CACHE: Map<string, string> = new Map();
|
||||
|
||||
export interface LayoutAvatarImageViewProps extends BaseProps<HTMLDivElement>
|
||||
@@ -19,18 +19,7 @@ export const LayoutAvatarImageView: FC<LayoutAvatarImageViewProps> = props =>
|
||||
const { figure = '', gender = '', headOnly = false, direction = 0, scale = 1, classNames = [], style = {}, ...rest } = props;
|
||||
const [ avatarUrl, setAvatarUrl ] = useState<string>(null);
|
||||
const [ isReady, setIsReady ] = useState<boolean>(false);
|
||||
const [ updateId, setUpdateId ] = useState<number>(0);
|
||||
const isDisposed = useRef(false);
|
||||
const figureKeyRef = useRef<string>(null);
|
||||
|
||||
useNitroEvent(NitroEventType.AVATAR_ASSET_LOADED, () =>
|
||||
{
|
||||
if(figureKeyRef.current)
|
||||
{
|
||||
AVATAR_IMAGE_CACHE.delete(figureKeyRef.current);
|
||||
setUpdateId(prev => prev + 1);
|
||||
}
|
||||
});
|
||||
|
||||
const getClassNames = useMemo(() =>
|
||||
{
|
||||
@@ -65,44 +54,48 @@ export const LayoutAvatarImageView: FC<LayoutAvatarImageViewProps> = props =>
|
||||
|
||||
const figureKey = [ figure, gender, direction, headOnly ].join('-');
|
||||
|
||||
figureKeyRef.current = figureKey;
|
||||
|
||||
if(AVATAR_IMAGE_CACHE.has(figureKey))
|
||||
{
|
||||
setAvatarUrl(AVATAR_IMAGE_CACHE.get(figureKey));
|
||||
}
|
||||
else
|
||||
{
|
||||
const avatarImage = GetAvatarRenderManager().createAvatarImage(figure, AvatarScaleType.LARGE, gender, {
|
||||
resetFigure: (figure: string) =>
|
||||
{
|
||||
if(isDisposed.current) return;
|
||||
|
||||
AVATAR_IMAGE_CACHE.delete(figureKey);
|
||||
setUpdateId(prev => prev + 1);
|
||||
},
|
||||
dispose: null,
|
||||
disposed: false
|
||||
});
|
||||
|
||||
let setType = AvatarSetType.FULL;
|
||||
|
||||
if(headOnly) setType = AvatarSetType.HEAD;
|
||||
|
||||
avatarImage.setDirection(setType, direction);
|
||||
|
||||
const imageUrl = avatarImage.processAsImageUrl(setType);
|
||||
|
||||
if(imageUrl && !isDisposed.current)
|
||||
const resetFigure = (_figure: string) =>
|
||||
{
|
||||
if(!avatarImage.isPlaceholder()) AVATAR_IMAGE_CACHE.set(figureKey, imageUrl);
|
||||
if(isDisposed.current) return;
|
||||
|
||||
setAvatarUrl(imageUrl);
|
||||
}
|
||||
const avatarImage = GetAvatarRenderManager().createAvatarImage(_figure, AvatarScaleType.LARGE, gender, { resetFigure: (figure: string) => resetFigure(figure), dispose: null, disposed: false });
|
||||
|
||||
avatarImage.dispose();
|
||||
let setType = AvatarSetType.FULL;
|
||||
|
||||
if(headOnly) setType = AvatarSetType.HEAD;
|
||||
|
||||
avatarImage.setDirection(setType, direction);
|
||||
|
||||
const imageUrl = avatarImage.processAsImageUrl(setType);
|
||||
|
||||
if(imageUrl && !isDisposed.current)
|
||||
{
|
||||
if(!avatarImage.isPlaceholder())
|
||||
{
|
||||
if(AVATAR_IMAGE_CACHE.size >= AVATAR_CACHE_MAX_SIZE)
|
||||
{
|
||||
const firstKey = AVATAR_IMAGE_CACHE.keys().next().value;
|
||||
AVATAR_IMAGE_CACHE.delete(firstKey);
|
||||
}
|
||||
|
||||
AVATAR_IMAGE_CACHE.set(figureKey, imageUrl);
|
||||
}
|
||||
|
||||
setAvatarUrl(imageUrl);
|
||||
}
|
||||
|
||||
avatarImage.dispose();
|
||||
};
|
||||
|
||||
resetFigure(figure);
|
||||
}
|
||||
}, [ figure, gender, direction, headOnly, isReady, updateId ]);
|
||||
}, [ figure, gender, direction, headOnly, isReady ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { GetRoomEngine, IGetImageListener, ImageResult, TextureUtils, Vector3d } from '@nitrots/nitro-renderer';
|
||||
import { CSSProperties, FC, useEffect, useMemo, useState } from 'react';
|
||||
import { CSSProperties, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { ProductTypeEnum } from '../../api';
|
||||
import { Base, BaseProps } from '../Base';
|
||||
|
||||
@@ -16,6 +16,23 @@ export const LayoutFurniImageView: FC<LayoutFurniImageViewProps> = props =>
|
||||
{
|
||||
const { productType = 's', productClassId = -1, direction = 2, extraData = '', scale = 1, style = {}, ...rest } = props;
|
||||
const [ imageElement, setImageElement ] = useState<HTMLImageElement>(null);
|
||||
const isMounted = useRef(true);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
isMounted.current = true;
|
||||
|
||||
return () => { isMounted.current = false; };
|
||||
}, []);
|
||||
|
||||
const updateImage = useCallback(async (texture: any) =>
|
||||
{
|
||||
if(!texture) return;
|
||||
|
||||
const image = await TextureUtils.generateImage(texture);
|
||||
|
||||
if(image && isMounted.current) setImageElement(image);
|
||||
}, []);
|
||||
|
||||
const getStyle = useMemo(() =>
|
||||
{
|
||||
@@ -42,10 +59,12 @@ export const LayoutFurniImageView: FC<LayoutFurniImageViewProps> = props =>
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
setImageElement(null);
|
||||
|
||||
let imageResult: ImageResult = null;
|
||||
|
||||
const listener: IGetImageListener = {
|
||||
imageReady: async (id, texture, image) => setImageElement(await TextureUtils.generateImage(texture)),
|
||||
imageReady: (result) => updateImage(result?.data),
|
||||
imageFailed: null
|
||||
};
|
||||
|
||||
@@ -59,12 +78,8 @@ export const LayoutFurniImageView: FC<LayoutFurniImageViewProps> = props =>
|
||||
break;
|
||||
}
|
||||
|
||||
if(!imageResult) return;
|
||||
|
||||
(async () => setImageElement(await TextureUtils.generateImage(imageResult.data)))();
|
||||
}, [ productType, productClassId, direction, extraData ]);
|
||||
|
||||
if(!imageElement) return null;
|
||||
if(imageResult?.data) updateImage(imageResult.data);
|
||||
}, [ productType, productClassId, direction, extraData, updateImage ]);
|
||||
|
||||
return <Base classNames={ [ 'furni-image' ] } style={ getStyle } { ...rest } />;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { GetRoomEngine, TextureUtils, Vector3d } from '@nitrots/nitro-renderer';
|
||||
import { CSSProperties, FC, useEffect, useMemo, useState } from 'react';
|
||||
import { CSSProperties, FC, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Base, BaseProps } from '../Base';
|
||||
|
||||
interface LayoutRoomObjectImageViewProps extends BaseProps<HTMLDivElement>
|
||||
@@ -15,6 +15,14 @@ export const LayoutRoomObjectImageView: FC<LayoutRoomObjectImageViewProps> = pro
|
||||
{
|
||||
const { roomId = -1, objectId = 1, category = -1, direction = 2, scale = 1, style = {}, ...rest } = props;
|
||||
const [ imageElement, setImageElement ] = useState<HTMLImageElement>(null);
|
||||
const isMounted = useRef(true);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
isMounted.current = true;
|
||||
|
||||
return () => { isMounted.current = false; };
|
||||
}, []);
|
||||
|
||||
const getStyle = useMemo(() =>
|
||||
{
|
||||
@@ -42,15 +50,23 @@ export const LayoutRoomObjectImageView: FC<LayoutRoomObjectImageViewProps> = pro
|
||||
useEffect(() =>
|
||||
{
|
||||
const imageResult = GetRoomEngine().getRoomObjectImage(roomId, objectId, category, new Vector3d(direction * 45), 64, {
|
||||
imageReady: async (id, texture, image) => setImageElement(await TextureUtils.generateImage(texture)),
|
||||
imageReady: async (id, texture, image) =>
|
||||
{
|
||||
const img = await TextureUtils.generateImage(texture);
|
||||
|
||||
if(img && isMounted.current) setImageElement(img);
|
||||
},
|
||||
imageFailed: null
|
||||
});
|
||||
|
||||
// needs (roomObjectImage.data.width > 140) || (roomObjectImage.data.height > 200) scale 1
|
||||
|
||||
if(!imageResult) return;
|
||||
|
||||
(async () => setImageElement(await TextureUtils.generateImage(imageResult.data)))();
|
||||
(async () =>
|
||||
{
|
||||
const img = await TextureUtils.generateImage(imageResult.data);
|
||||
|
||||
if(img && isMounted.current) setImageElement(img);
|
||||
})();
|
||||
}, [ roomId, objectId, category, direction, scale ]);
|
||||
|
||||
if(!imageElement) return null;
|
||||
|
||||
@@ -24,15 +24,13 @@ export const LayoutRoomPreviewerView: FC<{
|
||||
const width = elementRef.current.parentElement.clientWidth;
|
||||
const texture = TextureUtils.createRenderTexture(width, height);
|
||||
|
||||
const update = async (ticker: NitroTicker) =>
|
||||
const paintToDOM = () =>
|
||||
{
|
||||
if(!roomPreviewer || !elementRef.current) return;
|
||||
|
||||
roomPreviewer.updatePreviewRoomView();
|
||||
|
||||
const renderingCanvas = roomPreviewer.getRenderingCanvas();
|
||||
|
||||
if(!renderingCanvas.canvasUpdated) return;
|
||||
if(!renderingCanvas) return;
|
||||
|
||||
GetRenderer().render({
|
||||
target: texture,
|
||||
@@ -40,14 +38,29 @@ export const LayoutRoomPreviewerView: FC<{
|
||||
clear: true
|
||||
});
|
||||
|
||||
let canvas = GetRenderer().texture.generateCanvas(texture);
|
||||
const canvas = GetRenderer().texture.generateCanvas(texture);
|
||||
const base64 = canvas.toDataURL('image/png');
|
||||
|
||||
canvas = null;
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
|
||||
elementRef.current.style.backgroundImage = `url(${ base64 })`;
|
||||
};
|
||||
|
||||
const update = (ticker: NitroTicker) =>
|
||||
{
|
||||
if(!roomPreviewer || !elementRef.current) return;
|
||||
|
||||
roomPreviewer.updatePreviewRoomView();
|
||||
|
||||
const renderingCanvas = roomPreviewer.getRenderingCanvas();
|
||||
|
||||
if(renderingCanvas && renderingCanvas.canvasUpdated)
|
||||
{
|
||||
paintToDOM();
|
||||
}
|
||||
};
|
||||
|
||||
GetTicker().add(update);
|
||||
|
||||
const resizeObserver = new ResizeObserver(() =>
|
||||
@@ -58,7 +71,7 @@ export const LayoutRoomPreviewerView: FC<{
|
||||
|
||||
roomPreviewer.modifyRoomCanvas(width, height);
|
||||
|
||||
update(GetTicker());
|
||||
paintToDOM();
|
||||
});
|
||||
|
||||
roomPreviewer.getRoomCanvas(width, height);
|
||||
|
||||
Reference in New Issue
Block a user