You've already forked Nitro_Render_V3
mirror of
https://github.com/duckietm/Nitro_Render_V3.git
synced 2026-06-20 15:36:18 +00:00
🆙 Windows 100% done!
- Background color added - Fixed one missing window - Better cloud animation - (NEW) real miror view in windows
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
import { IVector3D } from '@nitrots/api';
|
||||||
|
import { Vector3d } from '@nitrots/utils';
|
||||||
|
import { Texture } from 'pixi.js';
|
||||||
|
|
||||||
|
interface IWindowReflectionAvatarState
|
||||||
|
{
|
||||||
|
id: number;
|
||||||
|
texture: Texture;
|
||||||
|
location: IVector3D;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RoomWindowReflectionState
|
||||||
|
{
|
||||||
|
private static _avatars: Map<number, IWindowReflectionAvatarState> = new Map();
|
||||||
|
private static _updateId: number = 0;
|
||||||
|
|
||||||
|
public static setAvatar(id: number, texture: Texture, location: IVector3D): void
|
||||||
|
{
|
||||||
|
if(!texture || !location) return;
|
||||||
|
|
||||||
|
const storedLocation = new Vector3d();
|
||||||
|
|
||||||
|
storedLocation.assign(location);
|
||||||
|
|
||||||
|
this._avatars.set(id, {
|
||||||
|
id,
|
||||||
|
texture,
|
||||||
|
location: storedLocation
|
||||||
|
});
|
||||||
|
|
||||||
|
this._updateId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static removeAvatar(id: number): void
|
||||||
|
{
|
||||||
|
if(this._avatars.delete(id)) this._updateId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getAvatars(): IWindowReflectionAvatarState[]
|
||||||
|
{
|
||||||
|
return Array.from(this._avatars.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static get updateId(): number
|
||||||
|
{
|
||||||
|
return this._updateId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { GetAssetManager } from '@nitrots/assets';
|
|||||||
import { AdvancedMap } from '@nitrots/utils';
|
import { AdvancedMap } from '@nitrots/utils';
|
||||||
import { Texture } from 'pixi.js';
|
import { Texture } from 'pixi.js';
|
||||||
import { RoomObjectSpriteVisualization } from '../RoomObjectSpriteVisualization';
|
import { RoomObjectSpriteVisualization } from '../RoomObjectSpriteVisualization';
|
||||||
|
import { RoomWindowReflectionState } from '../RoomWindowReflectionState';
|
||||||
import { AvatarVisualizationData } from './AvatarVisualizationData';
|
import { AvatarVisualizationData } from './AvatarVisualizationData';
|
||||||
import { ExpressionAdditionFactory, FloatingIdleZAddition, GameClickTargetAddition, GuideStatusBubbleAddition, IAvatarAddition, MutedBubbleAddition, NumberBubbleAddition, TypingBubbleAddition } from './additions';
|
import { ExpressionAdditionFactory, FloatingIdleZAddition, GameClickTargetAddition, GuideStatusBubbleAddition, IAvatarAddition, MutedBubbleAddition, NumberBubbleAddition, TypingBubbleAddition } from './additions';
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
this._isLaying = false;
|
this._isLaying = false;
|
||||||
this._layInside = false;
|
this._layInside = false;
|
||||||
this._isAnimating = false;
|
this._isAnimating = false;
|
||||||
this._extraSpritesStartIndex = 2;
|
this._extraSpritesStartIndex = AvatarVisualization.INITIAL_RESERVED_SPRITES;
|
||||||
this._forcedAnimFrames = 0;
|
this._forcedAnimFrames = 0;
|
||||||
this._updatesUntilFrameUpdate = 0;
|
this._updatesUntilFrameUpdate = 0;
|
||||||
|
|
||||||
@@ -151,6 +152,8 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
|
|
||||||
if(this._avatarImage) this._avatarImage.dispose();
|
if(this._avatarImage) this._avatarImage.dispose();
|
||||||
|
|
||||||
|
if(this.object) RoomWindowReflectionState.removeAvatar(this.object.id);
|
||||||
|
|
||||||
this._shadow = null;
|
this._shadow = null;
|
||||||
this._disposed = true;
|
this._disposed = true;
|
||||||
}
|
}
|
||||||
@@ -265,6 +268,8 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
this.updateWindowReflectionSource();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +278,6 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
if(!_local_20 || (_local_20.length < 3)) _local_20 = AvatarVisualization.DEFAULT_CANVAS_OFFSETS;
|
if(!_local_20 || (_local_20.length < 3)) _local_20 = AvatarVisualization.DEFAULT_CANVAS_OFFSETS;
|
||||||
|
|
||||||
const sprite = this.getSprite(AvatarVisualization.SPRITE_INDEX_AVATAR);
|
const sprite = this.getSprite(AvatarVisualization.SPRITE_INDEX_AVATAR);
|
||||||
|
|
||||||
if(sprite)
|
if(sprite)
|
||||||
{
|
{
|
||||||
const highlightEnabled = ((this.object.model.getValue<number>(RoomObjectVariable.FIGURE_HIGHLIGHT_ENABLE) === 1) && (this.object.model.getValue<number>(RoomObjectVariable.FIGURE_HIGHLIGHT) === 1));
|
const highlightEnabled = ((this.object.model.getValue<number>(RoomObjectVariable.FIGURE_HIGHLIGHT_ENABLE) === 1) && (this.object.model.getValue<number>(RoomObjectVariable.FIGURE_HIGHLIGHT) === 1));
|
||||||
@@ -325,6 +329,8 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateWindowReflectionSource();
|
||||||
|
|
||||||
const typingBubble = this.getAddition(AvatarVisualization.TYPING_BUBBLE_ID) as TypingBubbleAddition;
|
const typingBubble = this.getAddition(AvatarVisualization.TYPING_BUBBLE_ID) as TypingBubbleAddition;
|
||||||
|
|
||||||
if(typingBubble)
|
if(typingBubble)
|
||||||
@@ -993,6 +999,22 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
this.clearAvatar();
|
this.clearAvatar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateWindowReflectionSource(): void
|
||||||
|
{
|
||||||
|
if(!this.object) return;
|
||||||
|
|
||||||
|
const sprite = this.getSprite(AvatarVisualization.SPRITE_INDEX_AVATAR);
|
||||||
|
|
||||||
|
if(sprite?.texture)
|
||||||
|
{
|
||||||
|
RoomWindowReflectionState.setAvatar(this.object.id, sprite.texture, this.object.getLocation());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomWindowReflectionState.removeAvatar(this.object.id);
|
||||||
|
}
|
||||||
|
|
||||||
private clearAvatar(): void
|
private clearAvatar(): void
|
||||||
{
|
{
|
||||||
const sprite = this.getSprite(AvatarVisualization.AVATAR_LAYER_ID);
|
const sprite = this.getSprite(AvatarVisualization.AVATAR_LAYER_ID);
|
||||||
@@ -1003,6 +1025,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
sprite.alpha = 255;
|
sprite.alpha = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(const avatar of this._cachedAvatars.getValues()) avatar && avatar.dispose();
|
for(const avatar of this._cachedAvatars.getValues()) avatar && avatar.dispose();
|
||||||
|
|
||||||
for(const avatar of this._cachedAvatarEffects.getValues()) avatar && avatar.dispose();
|
for(const avatar of this._cachedAvatarEffects.getValues()) avatar && avatar.dispose();
|
||||||
@@ -1011,6 +1034,8 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
this._cachedAvatarEffects.reset();
|
this._cachedAvatarEffects.reset();
|
||||||
|
|
||||||
this._avatarImage = null;
|
this._avatarImage = null;
|
||||||
|
|
||||||
|
if(this.object) RoomWindowReflectionState.removeAvatar(this.object.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAddition(id: number): IAvatarAddition
|
private getAddition(id: number): IAvatarAddition
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { GetAssetManager } from '@nitrots/assets';
|
|||||||
import { GetRenderer, GetTexturePool, PlaneMaskFilter, Vector3d } from '@nitrots/utils';
|
import { GetRenderer, GetTexturePool, PlaneMaskFilter, Vector3d } from '@nitrots/utils';
|
||||||
import { Container, Filter, Graphics, Matrix, Point, RenderTexture, Sprite, Texture, TilingSprite } from 'pixi.js';
|
import { Container, Filter, Graphics, Matrix, Point, RenderTexture, Sprite, Texture, TilingSprite } from 'pixi.js';
|
||||||
import { RoomGeometry } from '../../../utils';
|
import { RoomGeometry } from '../../../utils';
|
||||||
|
import { RoomWindowReflectionState } from '../RoomWindowReflectionState';
|
||||||
import { PlaneVisualizationAnimationLayer } from './animated';
|
import { PlaneVisualizationAnimationLayer } from './animated';
|
||||||
import { RoomPlaneBitmapMask } from './RoomPlaneBitmapMask';
|
import { RoomPlaneBitmapMask } from './RoomPlaneBitmapMask';
|
||||||
import { RoomPlaneRectangleMask } from './RoomPlaneRectangleMask';
|
import { RoomPlaneRectangleMask } from './RoomPlaneRectangleMask';
|
||||||
@@ -88,6 +89,10 @@ export class RoomPlane implements IRoomPlane
|
|||||||
private _lastLandscapeDebugSignature: string = null;
|
private _lastLandscapeDebugSignature: string = null;
|
||||||
private _hasWindowMask: boolean = false;
|
private _hasWindowMask: boolean = false;
|
||||||
private _windowMasks: { leftSideLoc: number; rightSideLoc: number }[] = [];
|
private _windowMasks: { leftSideLoc: number; rightSideLoc: number }[] = [];
|
||||||
|
private _lastWindowReflectionUpdateId: number = -1;
|
||||||
|
private _windowReflectionFirstSeenAt: Map<number, number> = new Map();
|
||||||
|
private _windowReflectionLastVisible: Map<number, { texture: Texture; location: IVector3D }> = new Map();
|
||||||
|
private _windowReflectionFadeOut: Map<number, { texture: Texture; location: IVector3D; startedAt: number }> = new Map();
|
||||||
|
|
||||||
constructor(origin: IVector3D, location: IVector3D, leftSide: IVector3D, rightSide: IVector3D, type: number, usesMask: boolean, secondaryNormals: IVector3D[], randomSeed: number, textureOffsetX: number = 0, textureOffsetY: number = 0, textureMaxX: number = 0, textureMaxY: number = 0)
|
constructor(origin: IVector3D, location: IVector3D, leftSide: IVector3D, rightSide: IVector3D, type: number, usesMask: boolean, secondaryNormals: IVector3D[], randomSeed: number, textureOffsetX: number = 0, textureOffsetY: number = 0, textureMaxX: number = 0, textureMaxY: number = 0)
|
||||||
{
|
{
|
||||||
@@ -259,7 +264,6 @@ export class RoomPlane implements IRoomPlane
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to "default" plane if the requested landscape plane wasn't found
|
|
||||||
if(!plane && planeType === RoomPlane.TYPE_LANDSCAPE)
|
if(!plane && planeType === RoomPlane.TYPE_LANDSCAPE)
|
||||||
{
|
{
|
||||||
const roomCollection2 = GetAssetManager().getCollection('room');
|
const roomCollection2 = GetAssetManager().getCollection('room');
|
||||||
@@ -334,7 +338,6 @@ export class RoomPlane implements IRoomPlane
|
|||||||
let backgroundColor: number = null;
|
let backgroundColor: number = null;
|
||||||
if(backgroundColorStr)
|
if(backgroundColorStr)
|
||||||
{
|
{
|
||||||
// Convert hex string like "#FEFEFE" to number
|
|
||||||
backgroundColor = parseInt(backgroundColorStr.replace('#', ''), 16);
|
backgroundColor = parseInt(backgroundColorStr.replace('#', ''), 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,10 +517,8 @@ export class RoomPlane implements IRoomPlane
|
|||||||
|
|
||||||
this._landscapeRenderWidth = width;
|
this._landscapeRenderWidth = width;
|
||||||
this._landscapeRenderHeight = height;
|
this._landscapeRenderHeight = height;
|
||||||
// Use total landscape width for animation canvas, but always use actual height
|
|
||||||
// The renderMaxY is often too small (e.g., 160) while actual height is much larger (e.g., 755)
|
|
||||||
this._animationCanvasWidth = renderMaxX || width;
|
this._animationCanvasWidth = renderMaxX || width;
|
||||||
this._animationCanvasHeight = height; // Always use actual landscape height for animations
|
this._animationCanvasHeight = height;
|
||||||
this._landscapeOffsetX = renderOffsetX;
|
this._landscapeOffsetX = renderOffsetX;
|
||||||
this._landscapeOffsetY = renderOffsetY;
|
this._landscapeOffsetY = renderOffsetY;
|
||||||
|
|
||||||
@@ -601,18 +602,31 @@ export class RoomPlane implements IRoomPlane
|
|||||||
|
|
||||||
this._planeTexture.source.label = `room_plane_${ this._uniqueId.toString() }`;
|
this._planeTexture.source.label = `room_plane_${ this._uniqueId.toString() }`;
|
||||||
|
|
||||||
|
let reflectionUpdate = false;
|
||||||
|
|
||||||
|
if(this._type === RoomPlane.TYPE_LANDSCAPE && this._windowMasks.length)
|
||||||
|
{
|
||||||
|
const reflectionUpdateId = RoomWindowReflectionState.updateId;
|
||||||
|
|
||||||
|
if(reflectionUpdateId !== this._lastWindowReflectionUpdateId)
|
||||||
|
{
|
||||||
|
this._lastWindowReflectionUpdateId = reflectionUpdateId;
|
||||||
|
reflectionUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let animationUpdate = false;
|
let animationUpdate = false;
|
||||||
if(this._isAnimated && this._type === RoomPlane.TYPE_LANDSCAPE)
|
if(this._isAnimated && this._type === RoomPlane.TYPE_LANDSCAPE)
|
||||||
{
|
{
|
||||||
const timeSinceLastUpdate = timeSinceStartMs - this._lastAnimationUpdate;
|
const timeSinceLastUpdate = timeSinceStartMs - this._lastAnimationUpdate;
|
||||||
if(timeSinceLastUpdate >= RoomPlane.ANIMATION_UPDATE_INTERVAL || needsUpdate)
|
if(timeSinceLastUpdate >= RoomPlane.ANIMATION_UPDATE_INTERVAL || needsUpdate || reflectionUpdate)
|
||||||
{
|
{
|
||||||
animationUpdate = true;
|
animationUpdate = true;
|
||||||
this._lastAnimationUpdate = timeSinceStartMs;
|
this._lastAnimationUpdate = timeSinceStartMs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(needsUpdate || animationUpdate)
|
if(needsUpdate || animationUpdate || reflectionUpdate)
|
||||||
{
|
{
|
||||||
const isLandscape = (this._type === RoomPlane.TYPE_LANDSCAPE);
|
const isLandscape = (this._type === RoomPlane.TYPE_LANDSCAPE);
|
||||||
const hasLandscapeLayeredRendering = (isLandscape && (this._landscapeBackgroundTexture !== null || this._landscapeForegroundTexture !== null || this._animationLayers.length > 0 || this._landscapeBackgroundColor !== null));
|
const hasLandscapeLayeredRendering = (isLandscape && (this._landscapeBackgroundTexture !== null || this._landscapeForegroundTexture !== null || this._animationLayers.length > 0 || this._landscapeBackgroundColor !== null));
|
||||||
@@ -649,17 +663,20 @@ export class RoomPlane implements IRoomPlane
|
|||||||
this.renderLandscapeLayer(this._landscapeBackgroundTexture, this._landscapeBackgroundTint, this._landscapeBaseAlignBottom);
|
this.renderLandscapeLayer(this._landscapeBackgroundTexture, this._landscapeBackgroundTint, this._landscapeBaseAlignBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render animation layers (clouds) - between background and foreground
|
|
||||||
if(this._isAnimated && this._type === RoomPlane.TYPE_LANDSCAPE && this._animationLayers.length > 0)
|
if(this._isAnimated && this._type === RoomPlane.TYPE_LANDSCAPE && this._animationLayers.length > 0)
|
||||||
{
|
{
|
||||||
this.renderAnimationLayers(timeSinceStartMs, geometry);
|
this.renderAnimationLayers(timeSinceStartMs, geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render foreground layer for landscapes on top of background and clouds
|
|
||||||
if(this._type === RoomPlane.TYPE_LANDSCAPE && this._landscapeForegroundTexture)
|
if(this._type === RoomPlane.TYPE_LANDSCAPE && this._landscapeForegroundTexture)
|
||||||
{
|
{
|
||||||
this.renderLandscapeLayer(this._landscapeForegroundTexture, this._landscapeForegroundTint, this._landscapeForegroundAlignBottom);
|
this.renderLandscapeLayer(this._landscapeForegroundTexture, this._landscapeForegroundTint, this._landscapeForegroundAlignBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this._type === RoomPlane.TYPE_LANDSCAPE && this._windowMasks.length)
|
||||||
|
{
|
||||||
|
this.renderWindowReflections();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -794,7 +811,6 @@ export class RoomPlane implements IRoomPlane
|
|||||||
|
|
||||||
if(canvasWidth <= 0 || canvasHeight <= 0) return;
|
if(canvasWidth <= 0 || canvasHeight <= 0) return;
|
||||||
|
|
||||||
// Create a solid color rectangle to fill the background
|
|
||||||
const colorGraphics = new Graphics();
|
const colorGraphics = new Graphics();
|
||||||
colorGraphics.rect(0, 0, canvasWidth, canvasHeight);
|
colorGraphics.rect(0, 0, canvasWidth, canvasHeight);
|
||||||
colorGraphics.fill(this._landscapeBackgroundColor);
|
colorGraphics.fill(this._landscapeBackgroundColor);
|
||||||
@@ -851,6 +867,145 @@ export class RoomPlane implements IRoomPlane
|
|||||||
colorGraphics.destroy();
|
colorGraphics.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderWindowReflections(): void
|
||||||
|
{
|
||||||
|
if(!this._planeTexture || !this._leftSide || !this._rightSide || !this._normal) return;
|
||||||
|
|
||||||
|
if(this._leftSide.length <= 0 || this._rightSide.length <= 0) return;
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
const fadeDurationMs = 150;
|
||||||
|
const avatars = RoomWindowReflectionState.getAvatars();
|
||||||
|
const canvasWidth = this._landscapeRenderWidth;
|
||||||
|
const canvasHeight = this._landscapeRenderHeight;
|
||||||
|
|
||||||
|
if(canvasWidth <= 0 || canvasHeight <= 0) return;
|
||||||
|
|
||||||
|
const container = new Container();
|
||||||
|
const visibleAvatarIds = new Set<number>();
|
||||||
|
|
||||||
|
const addReflectionSprite = (texture: Texture, location: IVector3D, alpha: number): boolean => {
|
||||||
|
if(!texture || !location || alpha < 0) return false;
|
||||||
|
|
||||||
|
const relative = Vector3d.dif(location, this._location);
|
||||||
|
const planeDistance = Math.abs(Vector3d.scalarProjection(relative, this._normal));
|
||||||
|
|
||||||
|
if(planeDistance > 0.8) return false;
|
||||||
|
|
||||||
|
const leftSideLoc = Vector3d.scalarProjection(relative, this._leftSide);
|
||||||
|
const rightSideLoc = Vector3d.scalarProjection(relative, this._rightSide);
|
||||||
|
|
||||||
|
const closestMask = this._windowMasks.reduce((best, mask) => {
|
||||||
|
const score = Math.abs(mask.leftSideLoc - leftSideLoc) + Math.abs(mask.rightSideLoc - rightSideLoc);
|
||||||
|
|
||||||
|
if(!best || (score < best.score)) return { mask, score };
|
||||||
|
|
||||||
|
return best;
|
||||||
|
}, null as { mask: { leftSideLoc: number; rightSideLoc: number }; score: number } | null);
|
||||||
|
|
||||||
|
if(!closestMask || (closestMask.score > 3)) return false;
|
||||||
|
|
||||||
|
const x = (canvasWidth - ((canvasWidth * leftSideLoc) / this._leftSide.length));
|
||||||
|
const y = (canvasHeight - ((canvasHeight * rightSideLoc) / this._rightSide.length));
|
||||||
|
|
||||||
|
const sprite = new Sprite(texture);
|
||||||
|
sprite.anchor.set(0.5, 1);
|
||||||
|
sprite.position.set(Math.trunc(x), Math.trunc(y));
|
||||||
|
sprite.scale.set(1, 1);
|
||||||
|
sprite.tint = 0xCFE3FF;
|
||||||
|
sprite.alpha = alpha;
|
||||||
|
|
||||||
|
container.addChild(sprite);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
for(const avatar of avatars)
|
||||||
|
{
|
||||||
|
if(!avatar?.texture || !avatar.location) continue;
|
||||||
|
|
||||||
|
let firstSeenAt = this._windowReflectionFirstSeenAt.get(avatar.id);
|
||||||
|
|
||||||
|
if(firstSeenAt === undefined)
|
||||||
|
{
|
||||||
|
firstSeenAt = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
const elapsed = Math.min(fadeDurationMs, Math.max(0, (now - firstSeenAt)));
|
||||||
|
const progress = (elapsed / fadeDurationMs);
|
||||||
|
const alpha = (0.4 * progress);
|
||||||
|
|
||||||
|
if(!addReflectionSprite(avatar.texture, avatar.location, alpha)) continue;
|
||||||
|
|
||||||
|
if(!this._windowReflectionFirstSeenAt.has(avatar.id)) this._windowReflectionFirstSeenAt.set(avatar.id, firstSeenAt);
|
||||||
|
|
||||||
|
visibleAvatarIds.add(avatar.id);
|
||||||
|
this._windowReflectionFadeOut.delete(avatar.id);
|
||||||
|
|
||||||
|
const storedLocation = new Vector3d();
|
||||||
|
storedLocation.assign(avatar.location);
|
||||||
|
|
||||||
|
this._windowReflectionLastVisible.set(avatar.id, {
|
||||||
|
texture: avatar.texture,
|
||||||
|
location: storedLocation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const [id, lastVisible] of this._windowReflectionLastVisible)
|
||||||
|
{
|
||||||
|
if(visibleAvatarIds.has(id) || this._windowReflectionFadeOut.has(id)) continue;
|
||||||
|
|
||||||
|
this._windowReflectionFadeOut.set(id, {
|
||||||
|
texture: lastVisible.texture,
|
||||||
|
location: lastVisible.location,
|
||||||
|
startedAt: now
|
||||||
|
});
|
||||||
|
|
||||||
|
this._windowReflectionLastVisible.delete(id);
|
||||||
|
this._windowReflectionFirstSeenAt.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const [id, fadeOut] of this._windowReflectionFadeOut)
|
||||||
|
{
|
||||||
|
const elapsed = (now - fadeOut.startedAt);
|
||||||
|
|
||||||
|
if(elapsed >= fadeDurationMs)
|
||||||
|
{
|
||||||
|
this._windowReflectionFadeOut.delete(id);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const alpha = (0.4 * (1 - (elapsed / fadeDurationMs)));
|
||||||
|
|
||||||
|
if(!addReflectionSprite(fadeOut.texture, fadeOut.location, alpha)) this._windowReflectionFadeOut.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!container.children.length)
|
||||||
|
{
|
||||||
|
container.destroy({ children: true });
|
||||||
|
|
||||||
|
if(!avatars.length)
|
||||||
|
{
|
||||||
|
this._windowReflectionFirstSeenAt.clear();
|
||||||
|
this._windowReflectionLastVisible.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this._maskFilter) container.filters = [this._maskFilter];
|
||||||
|
|
||||||
|
GetRenderer().render({
|
||||||
|
target: this._planeTexture,
|
||||||
|
container,
|
||||||
|
transform: this.getMatrixForDimensions(canvasWidth, canvasHeight),
|
||||||
|
clear: false
|
||||||
|
});
|
||||||
|
|
||||||
|
container.destroy({ children: true });
|
||||||
|
}
|
||||||
|
|
||||||
private updateCorners(geometry: IRoomGeometry): void
|
private updateCorners(geometry: IRoomGeometry): void
|
||||||
{
|
{
|
||||||
this._cornerA.assign(geometry.getScreenPosition(this._location));
|
this._cornerA.assign(geometry.getScreenPosition(this._location));
|
||||||
|
|||||||
Reference in New Issue
Block a user