Skip to content
Merged

Dev #215

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/avatar/src/AvatarAssetDownloadManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ export class AvatarAssetDownloadManager
this._figureListeners.set(figure, listeners);
}

listeners.push(listener);
if(listeners.indexOf(listener) === -1) listeners.push(listener);
}

this._incompleteFigures.set(figure, pendingLibraries);
Expand Down
11 changes: 8 additions & 3 deletions packages/avatar/src/AvatarStructure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@ export class AvatarStructure

if(!action) return [];

const activePartTypes = this._partSetsData.getActiveParts(action.definition);
let activePartTypes = this._partSetsData.getActiveParts(action.definition);
let activePartTypesCopied = false;
const partContainers: AvatarImagePartContainer[] = [];
let defaultFrames: any[] = [0];
const animationAction = this._animationData.getAction(action.definition);
Expand All @@ -357,6 +358,12 @@ export class AvatarStructure
{
for(const dynamicPart of geometryBodyPart.getDynamicParts(avatar))
{
if(!activePartTypesCopied)
{
activePartTypes = activePartTypes.slice();
activePartTypesCopied = true;
}

activePartTypes.push(dynamicPart.id);
}
}
Expand All @@ -370,8 +377,6 @@ export class AvatarStructure
const mainAction = avatar?.getMainAction?.();
const isSittingPosture = (mainAction?.definition?.assetPartDefinition === 'sit')
|| (action.definition.assetPartDefinition === 'sit');
// Effect 77 = "Riding". While in the saddle the companion/buddy ('pt') part
// is hidden the same way it is while sitting.
const isRidingPosture = (avatar?.getEffectId?.() === 77);
const hidePetPart = isSittingPosture || isRidingPosture;

Expand Down
2 changes: 1 addition & 1 deletion packages/avatar/src/EffectAssetDownloadManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export class EffectAssetDownloadManager

if(!listeners) listeners = [];

listeners.push(listener);
if(listeners.indexOf(listener) === -1) listeners.push(listener);

this._effectListeners.set(id.toString(), listeners);
}
Expand Down
5 changes: 4 additions & 1 deletion packages/avatar/src/alias/AssetAliasCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class AssetAliasCollection
private _aliases: Map<string, AssetAlias>;
private _avatarRenderManager: AvatarRenderManager;
private _missingAssetNames: string[];
private _processedCollections: WeakSet<object> = new WeakSet();

constructor(avatarRenderManager: AvatarRenderManager, assets: IAssetManager)
{
Expand All @@ -32,7 +33,9 @@ export class AssetAliasCollection
{
for(const collection of this._assets.collections.values())
{
if(!collection) continue;
if(!collection || this._processedCollections.has(collection)) continue;

this._processedCollections.add(collection);

const aliases = collection.data && collection.data.aliases;

Expand Down
13 changes: 8 additions & 5 deletions packages/avatar/src/cache/AvatarImageCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { ImageData } from './ImageData';
export class AvatarImageCache
{
private static DEFAULT_MAX_CACHE_STORAGE_TIME_MS: number = 60000;
// Shared read-only defaults for the per-frame hot path — never mutate.
private static EMPTY_REMOVE_DATA: string[] = [];
private static EMPTY_ITEMS: Map<string, string> = new Map();

private _structure: AvatarStructure;
private _avatar: IAvatarImage;
Expand Down Expand Up @@ -176,9 +179,7 @@ export class AvatarImageCache

public getImageContainer(key: string, frameNumber: number, forceRefresh: boolean = false): AvatarImageBodyPartContainer
{
const bodyPartCache = this.getBodyPartCache(key) || new AvatarImageBodyPartCache();

this._cache.set(key, bodyPartCache);
const bodyPartCache = this.getBodyPartCache(key);

let direction = bodyPartCache.getDirection();
let action = bodyPartCache.getAction();
Expand All @@ -187,9 +188,11 @@ export class AvatarImageCache
if(action.definition.startFromFrameZero) adjustedFrameCount -= action.startFrame;

let adjustedAction = action;
let removeData: string[] = [];
let items: Map<string, string> = new Map();
let removeData: string[] = AvatarImageCache.EMPTY_REMOVE_DATA;
let items: Map<string, string> = AvatarImageCache.EMPTY_ITEMS;

// NOT a shared scratch: the (cached) image container stores this
// Point by reference via its offset setter.
const positionOffset = new Point();

if(action.definition.isAnimation)
Expand Down
6 changes: 5 additions & 1 deletion packages/room/src/RoomInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,12 @@ export class RoomInstance implements IRoomInstance

if(!objects.length) continue;

for(const object of objects.getValues())
const total = objects.length;

for(let index = 0; index < total; index++)
{
const object = objects.getWithIndex(index);

if(!object) continue;

const logic = object.logic;
Expand Down
3 changes: 2 additions & 1 deletion packages/room/src/object/visualization/RoomObjectSprite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ export class RoomObjectSprite implements IRoomObjectSprite
return this._height;
}

// Per-sprite zoom multiplier (1 = native). Applied on top of the room zoom.
public get scale(): number
{
return this._scale;
Expand Down Expand Up @@ -360,6 +359,8 @@ export class RoomObjectSprite implements IRoomObjectSprite

public set filters(filters: Filter[])
{
if(this._filters === filters) return;

this._filters = filters;

this._updateCounter++;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AlphaTolerance, AvatarAction, AvatarGuideStatus, AvatarSetType, IAdvancedMap, IAvatarEffectListener, IAvatarImage, IAvatarImageListener, IGraphicAsset, IObjectVisualizationData, IRoomGeometry, IRoomObject, IRoomObjectModel, RoomObjectSpriteType, RoomObjectVariable } from '@octane/api';
import { GetAssetManager } from '@octane/assets';
import { AdvancedMap, GetRenderer } from '@octane/utils';
import { AdvancedMap, GetRenderer, Vector3d } from '@octane/utils';
import { Container, RenderTexture, Sprite, Texture } from 'pixi.js';
import { RoomObjectSpriteVisualization } from '../RoomObjectSpriteVisualization';
import { RoomWindowReflectionState } from '../RoomWindowReflectionState';
Expand Down Expand Up @@ -87,6 +87,9 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
private _reflectionOppositeDirection: number;
private _reflectionOppositeBaseTexture: Texture;
private _windowReflectionPushed: boolean;
private _lastReflectionPushedTexture: Texture;
private _lastReflectionPushedDirection: number;
private _lastReflectionPushedLocation: Vector3d;

private _additions: Map<number, IAvatarAddition>;

Expand Down Expand Up @@ -146,6 +149,9 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
this._reflectionOppositeDirection = -1;
this._reflectionOppositeBaseTexture = null;
this._windowReflectionPushed = false;
this._lastReflectionPushedTexture = null;
this._lastReflectionPushedDirection = -1;
this._lastReflectionPushedLocation = new Vector3d();

this._additions = new Map();
}
Expand Down Expand Up @@ -191,6 +197,13 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement

if(this.object) RoomWindowReflectionState.removeAvatar(this.object.id, this.object.model?.getValue<string>(RoomObjectVariable.OBJECT_ROOM_ID));

if(this._additions)
{
for(const addition of this._additions.values()) addition?.dispose();

this._additions.clear();
}

this._shadow = null;
this._disposed = true;
}
Expand Down Expand Up @@ -305,7 +318,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
}
else
{
this.updateWindowReflectionSource();
this.updateWindowReflectionSource(true);

return;
}
Expand Down Expand Up @@ -1140,14 +1153,25 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
return target;
}

private updateWindowReflectionSource(): void
private updateWindowReflectionSource(skipIfUnchanged: boolean = false): void
{
if(!this.object) return;

const sprite = this.getSprite(AvatarVisualization.SPRITE_INDEX_AVATAR);

if(sprite?.texture)
{
if(skipIfUnchanged && this._windowReflectionPushed)
{
const location = this.object.getLocation();

if((sprite.texture === this._lastReflectionPushedTexture) &&
(this.object.getDirection().x === this._lastReflectionPushedDirection) &&
(location.x === this._lastReflectionPushedLocation.x) &&
(location.y === this._lastReflectionPushedLocation.y) &&
(location.z === this._lastReflectionPushedLocation.z)) return;
}

const roomId = this.object.model?.getValue<string>(RoomObjectVariable.OBJECT_ROOM_ID);

if(!RoomWindowReflectionState.hasZones || !RoomWindowReflectionState.isNearAnyZone(this.object.getLocation(), roomId))
Expand All @@ -1157,6 +1181,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
RoomWindowReflectionState.removeAvatar(this.object.id, roomId);

this._windowReflectionPushed = false;
this._lastReflectionPushedTexture = null;
}

return;
Expand Down Expand Up @@ -1206,13 +1231,17 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
RoomWindowReflectionState.setAvatar(this.object.id, sprite.texture, this.object.getLocation(), this._reflectionVerticalOffset, this.object.getDirection().x, oppositeTexture, roomId);

this._windowReflectionPushed = true;
this._lastReflectionPushedTexture = sprite.texture;
this._lastReflectionPushedDirection = this.object.getDirection().x;
this._lastReflectionPushedLocation.assign(this.object.getLocation());

return;
}

RoomWindowReflectionState.removeAvatar(this.object.id, this.object.model?.getValue<string>(RoomObjectVariable.OBJECT_ROOM_ID));

this._windowReflectionPushed = false;
this._lastReflectionPushedTexture = null;
}

private clearAvatar(): void
Expand Down Expand Up @@ -1247,6 +1276,8 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
if(this.object) RoomWindowReflectionState.removeAvatar(this.object.id, this.object.model?.getValue<string>(RoomObjectVariable.OBJECT_ROOM_ID));

this._windowReflectionPushed = false;
this._lastReflectionPushedTexture = null;
this._lastReflectionPushedDirection = -1;
}

private getAddition(id: number): IAvatarAddition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type HabbiconRuntimeAsset = {
export class HabbiconAssetManager
{
private static _instance: HabbiconAssetManager = null;
private static MAX_COMPOSED_TEXTURES: number = 256;
private static FRAME_SIZE: number = 40;
private static OUTLINE_SIZE: number = 2;
private static SHADOW_PADDING: number = 5;
Expand Down Expand Up @@ -153,7 +154,13 @@ export class HabbiconAssetManager

const existing = this._composedTextures.get(cacheKey);

if(existing) return existing;
if(existing)
{
this._composedTextures.delete(cacheKey);
this._composedTextures.set(cacheKey, existing);

return existing;
}

const composed = this.composeBubbleCanvas(source, sourceAlpha, backgroundAlpha, mirrored);

Expand All @@ -163,6 +170,16 @@ export class HabbiconAssetManager

this._composedTextures.set(cacheKey, texture);

while(this._composedTextures.size > HabbiconAssetManager.MAX_COMPOSED_TEXTURES)
{
const oldestKey = this._composedTextures.keys().next().value;
const oldest = this._composedTextures.get(oldestKey);

this._composedTextures.delete(oldestKey);

if(oldest && !oldest.destroyed) oldest.destroy(true);
}

return texture;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ export class HabbiconBubbleAddition implements IAvatarAddition
return Math.round((1 - progress) * HabbiconBubbleAddition.INTRO_START_OFFSET_Y);
}

private quantizeAlpha(alpha: number): number
{
return Math.min(255, Math.round(alpha / 8) * 8);
}

private resolveAlpha(now: number): number
{
if(!this._startedAt || this._sourceFadeOutAt <= this._startedAt) return 255;
Expand All @@ -307,7 +312,7 @@ export class HabbiconBubbleAddition implements IAvatarAddition

if(this._sourceHideAt > this._startedAt && now >= this._sourceHideAt) return 0;

return Math.round(255 * Math.min(fadeIn, fadeOut));
return this.quantizeAlpha(Math.round(255 * Math.min(fadeIn, fadeOut)));
}

private resolveBackgroundAlpha(now: number): number
Expand All @@ -317,7 +322,7 @@ export class HabbiconBubbleAddition implements IAvatarAddition
const fadeIn = Math.min(1, Math.max(0, (now - this._startedAt) / HabbiconBubbleAddition.FADE_IN_DURATION_MS));
const fadeOut = now < this._backgroundFadeOutAt ? 1 : 1 - Math.min(1, Math.max(0, (now - this._backgroundFadeOutAt) / HabbiconBubbleAddition.BACKGROUND_FADE_OUT_DURATION_MS));

return Math.round(255 * Math.min(fadeIn, fadeOut));
return this.quantizeAlpha(Math.round(255 * Math.min(fadeIn, fadeOut)));
}

private resolveFrameAnchorCompensationX(): number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class FurnitureDynamicThumbnailVisualization extends IsometricImageFurniV
const texture = Texture.from(image);
texture.source.scaleMode = 'linear';

this.setThumbnailImages(texture, thumbnailUrl);
this.setThumbnailImages(texture, thumbnailUrl, true);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class FurnitureParticleSystem

if(this._canvasTexture)
{
this._canvasTexture.destroy();
this._canvasTexture.destroy(true);
this._canvasTexture = null;
}

Expand All @@ -71,8 +71,17 @@ export class FurnitureParticleSystem
this._particleSprite = null;
}

this._blackOverlayAlphaTransform = null;
this._particleColorTransform = null;
if(this._blackOverlayAlphaTransform)
{
this._blackOverlayAlphaTransform.destroy();
this._blackOverlayAlphaTransform = null;
}

if(this._particleColorTransform)
{
this._particleColorTransform.destroy();
this._particleColorTransform = null;
}
this._identityMatrix = null;
this._translationMatrix = null;
}
Expand Down Expand Up @@ -111,7 +120,7 @@ export class FurnitureParticleSystem

if(this._canvasTexture && ((this._canvasTexture.width !== this._roomSprite.width) || (this._canvasTexture.height !== this._roomSprite.height)))
{
this._canvasTexture.destroy();
this._canvasTexture.destroy(true);
this._canvasTexture = null;
}

Expand Down Expand Up @@ -310,7 +319,7 @@ export class FurnitureParticleSystem

if(this._canvasTexture)
{
this._canvasTexture.destroy();
this._canvasTexture.destroy(true);
this._canvasTexture = null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,14 @@ export class FurnitureVisualization extends RoomObjectSpriteVisualization
sprite.posture = this.getPostureForAsset(scale, assetData.source);
sprite.clickHandling = this._clickHandling;

const chooserFilters = (sprite.filters || []).filter(f => f instanceof ChooserSelectionFilter);
const currentFilters = sprite.filters;

sprite.filters = chooserFilters.length > 0 ? [...this._filters, ...chooserFilters] : this._filters;
if((currentFilters && currentFilters.length) || this._filters.length)
{
const chooserFilters = (currentFilters || []).filter(f => f instanceof ChooserSelectionFilter);

sprite.filters = chooserFilters.length > 0 ? [...this._filters, ...chooserFilters] : this._filters;
}
}
else
{
Expand Down
Loading
Loading