You've already forked Nitro_Render_V3
mirror of
https://github.com/duckietm/Nitro_Render_V3.git
synced 2026-06-20 07:26:18 +00:00
🆙 Patch GlTextureSystem & Fix effects like BBRed
- Monkey-patch the renderer's GlTextureSystem to prevent crashes from destroyed textures
This commit is contained in:
@@ -291,8 +291,6 @@ export class AvatarImage implements IAvatarImage, IAvatarEffectListener
|
|||||||
clear: true
|
clear: true
|
||||||
});
|
});
|
||||||
|
|
||||||
container.destroy();
|
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
this._activeTexture.source.hitMap = null;
|
this._activeTexture.source.hitMap = null;
|
||||||
|
|
||||||
@@ -585,7 +583,7 @@ export class AvatarImage implements IAvatarImage, IAvatarEffectListener
|
|||||||
this._effectIdInUse = -1;
|
this._effectIdInUse = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(effectChanged) this._cache.disposeInactiveActions();
|
if(effectChanged) this._cache.disposeInactiveActions(0);
|
||||||
|
|
||||||
if(this._lastActionsString != this._currentActionsString)
|
if(this._lastActionsString != this._currentActionsString)
|
||||||
{
|
{
|
||||||
@@ -653,6 +651,11 @@ export class AvatarImage implements IAvatarImage, IAvatarEffectListener
|
|||||||
if(animation.hasDirectionData()) this._directionOffset = animation.directionData.offset;
|
if(animation.hasDirectionData()) this._directionOffset = animation.directionData.offset;
|
||||||
|
|
||||||
if(animation.hasAvatarData()) this._avatarSpriteData = animation.avatarData;
|
if(animation.hasAvatarData()) this._avatarSpriteData = animation.avatarData;
|
||||||
|
|
||||||
|
if(!this._isAnimating && (animation.spriteData?.length > 0 || animation.hasAvatarData()))
|
||||||
|
{
|
||||||
|
this._isAnimating = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ interface IWindowReflectionAvatarState
|
|||||||
id: number;
|
id: number;
|
||||||
texture: Texture;
|
texture: Texture;
|
||||||
location: IVector3D;
|
location: IVector3D;
|
||||||
|
verticalOffset: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RoomWindowReflectionState
|
export class RoomWindowReflectionState
|
||||||
@@ -14,7 +15,7 @@ export class RoomWindowReflectionState
|
|||||||
private static _avatars: Map<number, IWindowReflectionAvatarState> = new Map();
|
private static _avatars: Map<number, IWindowReflectionAvatarState> = new Map();
|
||||||
private static _updateId: number = 0;
|
private static _updateId: number = 0;
|
||||||
|
|
||||||
public static setAvatar(id: number, texture: Texture, location: IVector3D): void
|
public static setAvatar(id: number, texture: Texture, location: IVector3D, verticalOffset: number = 0): void
|
||||||
{
|
{
|
||||||
if(!texture || !location) return;
|
if(!texture || !location) return;
|
||||||
|
|
||||||
@@ -25,7 +26,8 @@ export class RoomWindowReflectionState
|
|||||||
this._avatars.set(id, {
|
this._avatars.set(id, {
|
||||||
id,
|
id,
|
||||||
texture,
|
texture,
|
||||||
location: storedLocation
|
location: storedLocation,
|
||||||
|
verticalOffset
|
||||||
});
|
});
|
||||||
|
|
||||||
// Always bump updateId so reflected walk cycles stay frame-synced
|
// Always bump updateId so reflected walk cycles stay frame-synced
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
private _isAvatarReady: boolean;
|
private _isAvatarReady: boolean;
|
||||||
private _needsUpdate: boolean;
|
private _needsUpdate: boolean;
|
||||||
private _geometryUpdateCounter: number;
|
private _geometryUpdateCounter: number;
|
||||||
|
private _reflectionVerticalOffset: number;
|
||||||
|
|
||||||
private _additions: Map<number, IAvatarAddition>;
|
private _additions: Map<number, IAvatarAddition>;
|
||||||
|
|
||||||
@@ -127,6 +128,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
this._isAvatarReady = false;
|
this._isAvatarReady = false;
|
||||||
this._needsUpdate = false;
|
this._needsUpdate = false;
|
||||||
this._geometryUpdateCounter = -1;
|
this._geometryUpdateCounter = -1;
|
||||||
|
this._reflectionVerticalOffset = 0;
|
||||||
|
|
||||||
this._additions = new Map();
|
this._additions = new Map();
|
||||||
}
|
}
|
||||||
@@ -329,8 +331,6 @@ 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)
|
||||||
@@ -451,6 +451,17 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
_local_21++;
|
_local_21++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const avatarSprite = this.getSprite(AvatarVisualization.SPRITE_INDEX_AVATAR);
|
||||||
|
|
||||||
|
if(avatarSprite?.texture)
|
||||||
|
{
|
||||||
|
const baseOffsetY = (-(avatarSprite.texture.height) + (scale / 4));
|
||||||
|
|
||||||
|
this._reflectionVerticalOffset = avatarSprite.offsetY - baseOffsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateWindowReflectionSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1007,7 +1018,7 @@ export class AvatarVisualization extends RoomObjectSpriteVisualization implement
|
|||||||
|
|
||||||
if(sprite?.texture)
|
if(sprite?.texture)
|
||||||
{
|
{
|
||||||
RoomWindowReflectionState.setAvatar(this.object.id, sprite.texture, this.object.getLocation());
|
RoomWindowReflectionState.setAvatar(this.object.id, sprite.texture, this.object.getLocation(), this._reflectionVerticalOffset);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ export class RoomPlane implements IRoomPlane
|
|||||||
private _windowMasks: { leftSideLoc: number; rightSideLoc: number }[] = [];
|
private _windowMasks: { leftSideLoc: number; rightSideLoc: number }[] = [];
|
||||||
private _lastWindowReflectionUpdateId: number = -1;
|
private _lastWindowReflectionUpdateId: number = -1;
|
||||||
private _windowReflectionFirstSeenAt: Map<number, number> = new Map();
|
private _windowReflectionFirstSeenAt: Map<number, number> = new Map();
|
||||||
private _windowReflectionLastVisible: Map<number, { texture: Texture; location: IVector3D }> = new Map();
|
private _windowReflectionLastVisible: Map<number, { texture: Texture; location: IVector3D; verticalOffset: number }> = new Map();
|
||||||
private _windowReflectionFadeOut: Map<number, { texture: Texture; location: IVector3D; startedAt: number }> = new Map();
|
private _windowReflectionFadeOut: Map<number, { texture: Texture; location: IVector3D; verticalOffset: number; 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)
|
||||||
{
|
{
|
||||||
@@ -884,8 +884,8 @@ export class RoomPlane implements IRoomPlane
|
|||||||
const container = new Container();
|
const container = new Container();
|
||||||
const visibleAvatarIds = new Set<number>();
|
const visibleAvatarIds = new Set<number>();
|
||||||
|
|
||||||
const addReflectionSprite = (texture: Texture, location: IVector3D, alpha: number): boolean => {
|
const addReflectionSprite = (texture: Texture, location: IVector3D, alpha: number, verticalOffset: number = 0): boolean => {
|
||||||
if(!texture?.source || !location || alpha < 0) return false;
|
if(!texture?.source || texture.source.destroyed || !texture.source.style || !location || alpha < 0) return false;
|
||||||
|
|
||||||
const relative = Vector3d.dif(location, this._location);
|
const relative = Vector3d.dif(location, this._location);
|
||||||
const planeDistance = Math.abs(Vector3d.scalarProjection(relative, this._normal));
|
const planeDistance = Math.abs(Vector3d.scalarProjection(relative, this._normal));
|
||||||
@@ -906,7 +906,7 @@ export class RoomPlane implements IRoomPlane
|
|||||||
if(!closestMask || (closestMask.score > 3)) return false;
|
if(!closestMask || (closestMask.score > 3)) return false;
|
||||||
|
|
||||||
const x = (canvasWidth - ((canvasWidth * leftSideLoc) / this._leftSide.length));
|
const x = (canvasWidth - ((canvasWidth * leftSideLoc) / this._leftSide.length));
|
||||||
const y = (canvasHeight - ((canvasHeight * rightSideLoc) / this._rightSide.length));
|
const y = (canvasHeight - ((canvasHeight * rightSideLoc) / this._rightSide.length)) + verticalOffset;
|
||||||
|
|
||||||
const sprite = new Sprite(texture);
|
const sprite = new Sprite(texture);
|
||||||
sprite.anchor.set(0.5, 1);
|
sprite.anchor.set(0.5, 1);
|
||||||
@@ -922,7 +922,7 @@ export class RoomPlane implements IRoomPlane
|
|||||||
|
|
||||||
for(const avatar of avatars)
|
for(const avatar of avatars)
|
||||||
{
|
{
|
||||||
if(!avatar?.texture?.source || !avatar.location) continue;
|
if(!avatar?.texture?.source || avatar.texture.source.destroyed || !avatar.texture.source.style || !avatar.location) continue;
|
||||||
|
|
||||||
let firstSeenAt = this._windowReflectionFirstSeenAt.get(avatar.id);
|
let firstSeenAt = this._windowReflectionFirstSeenAt.get(avatar.id);
|
||||||
|
|
||||||
@@ -935,7 +935,7 @@ export class RoomPlane implements IRoomPlane
|
|||||||
const progress = (elapsed / fadeDurationMs);
|
const progress = (elapsed / fadeDurationMs);
|
||||||
const alpha = (0.4 * progress);
|
const alpha = (0.4 * progress);
|
||||||
|
|
||||||
if(!addReflectionSprite(avatar.texture, avatar.location, alpha)) continue;
|
if(!addReflectionSprite(avatar.texture, avatar.location, alpha, avatar.verticalOffset || 0)) continue;
|
||||||
|
|
||||||
if(!this._windowReflectionFirstSeenAt.has(avatar.id)) this._windowReflectionFirstSeenAt.set(avatar.id, firstSeenAt);
|
if(!this._windowReflectionFirstSeenAt.has(avatar.id)) this._windowReflectionFirstSeenAt.set(avatar.id, firstSeenAt);
|
||||||
|
|
||||||
@@ -947,7 +947,8 @@ export class RoomPlane implements IRoomPlane
|
|||||||
|
|
||||||
this._windowReflectionLastVisible.set(avatar.id, {
|
this._windowReflectionLastVisible.set(avatar.id, {
|
||||||
texture: avatar.texture,
|
texture: avatar.texture,
|
||||||
location: storedLocation
|
location: storedLocation,
|
||||||
|
verticalOffset: avatar.verticalOffset || 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -955,7 +956,7 @@ export class RoomPlane implements IRoomPlane
|
|||||||
{
|
{
|
||||||
if(visibleAvatarIds.has(id) || this._windowReflectionFadeOut.has(id)) continue;
|
if(visibleAvatarIds.has(id) || this._windowReflectionFadeOut.has(id)) continue;
|
||||||
|
|
||||||
if(!lastVisible.texture?.source)
|
if(!lastVisible.texture?.source || lastVisible.texture.source.destroyed || !lastVisible.texture.source.style)
|
||||||
{
|
{
|
||||||
this._windowReflectionLastVisible.delete(id);
|
this._windowReflectionLastVisible.delete(id);
|
||||||
this._windowReflectionFirstSeenAt.delete(id);
|
this._windowReflectionFirstSeenAt.delete(id);
|
||||||
@@ -966,6 +967,7 @@ export class RoomPlane implements IRoomPlane
|
|||||||
this._windowReflectionFadeOut.set(id, {
|
this._windowReflectionFadeOut.set(id, {
|
||||||
texture: lastVisible.texture,
|
texture: lastVisible.texture,
|
||||||
location: lastVisible.location,
|
location: lastVisible.location,
|
||||||
|
verticalOffset: lastVisible.verticalOffset,
|
||||||
startedAt: now
|
startedAt: now
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -986,7 +988,7 @@ export class RoomPlane implements IRoomPlane
|
|||||||
|
|
||||||
const alpha = (0.4 * (1 - (elapsed / fadeDurationMs)));
|
const alpha = (0.4 * (1 - (elapsed / fadeDurationMs)));
|
||||||
|
|
||||||
if(!addReflectionSprite(fadeOut.texture, fadeOut.location, alpha)) this._windowReflectionFadeOut.delete(id);
|
if(!addReflectionSprite(fadeOut.texture, fadeOut.location, alpha, fadeOut.verticalOffset)) this._windowReflectionFadeOut.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!container.children.length)
|
if(!container.children.length)
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ export class RoomSpriteCanvas implements IRoomRenderingCanvas
|
|||||||
const texture = sprite.texture;
|
const texture = sprite.texture;
|
||||||
const baseTexture = texture && texture.source;
|
const baseTexture = texture && texture.source;
|
||||||
|
|
||||||
if(!texture || !baseTexture || baseTexture.destroyed) continue;
|
if(!texture || !baseTexture) continue;
|
||||||
|
|
||||||
const spriteX = ((x + sprite.offsetX) + this._screenOffsetX);
|
const spriteX = ((x + sprite.offsetX) + this._screenOffsetX);
|
||||||
const spriteY = ((y + sprite.offsetY) + this._screenOffsetY);
|
const spriteY = ((y + sprite.offsetY) + this._screenOffsetY);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class ExtendedSprite extends Sprite
|
|||||||
|
|
||||||
public setTexture(texture: Texture): void
|
public setTexture(texture: Texture): void
|
||||||
{
|
{
|
||||||
if(!texture || texture.source?.destroyed) texture = Texture.EMPTY;
|
if(!texture) texture = Texture.EMPTY;
|
||||||
|
|
||||||
if(texture === this.texture) return;
|
if(texture === this.texture) return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,57 @@
|
|||||||
import { AutoDetectOptions, Renderer, autoDetectRenderer } from 'pixi.js';
|
import { AutoDetectOptions, Renderer, Texture, autoDetectRenderer } from 'pixi.js';
|
||||||
|
|
||||||
let renderer: Renderer = null;
|
let renderer: Renderer = null;
|
||||||
|
|
||||||
|
const patchGlTextureSystem = (r: Renderer): void =>
|
||||||
|
{
|
||||||
|
const textureSystem = (r as any).texture;
|
||||||
|
|
||||||
|
if(!textureSystem) return;
|
||||||
|
|
||||||
|
const proto = Object.getPrototypeOf(textureSystem);
|
||||||
|
|
||||||
|
if(!proto) return;
|
||||||
|
|
||||||
|
const origUpdateStyle = proto.updateStyle;
|
||||||
|
|
||||||
|
if(origUpdateStyle && !proto.__patchedUpdateStyle)
|
||||||
|
{
|
||||||
|
proto.updateStyle = function(source: any, firstCreation: boolean)
|
||||||
|
{
|
||||||
|
if(!source || source.destroyed || !source.style) return;
|
||||||
|
|
||||||
|
return origUpdateStyle.call(this, source, firstCreation);
|
||||||
|
};
|
||||||
|
|
||||||
|
proto.__patchedUpdateStyle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const origBindSource = proto.bindSource;
|
||||||
|
|
||||||
|
if(origBindSource && !proto.__patchedBindSource)
|
||||||
|
{
|
||||||
|
proto.bindSource = function(source: any, location = 0)
|
||||||
|
{
|
||||||
|
if(!source || source.destroyed || !source.style)
|
||||||
|
{
|
||||||
|
source = Texture.EMPTY.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
return origBindSource.call(this, source, location);
|
||||||
|
};
|
||||||
|
|
||||||
|
proto.__patchedBindSource = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const PrepareRenderer = async (options: Partial<AutoDetectOptions>): Promise<Renderer> =>
|
export const PrepareRenderer = async (options: Partial<AutoDetectOptions>): Promise<Renderer> =>
|
||||||
{
|
{
|
||||||
renderer = await autoDetectRenderer(options);
|
renderer = await autoDetectRenderer(options);
|
||||||
|
|
||||||
renderer.events?.destroy();
|
renderer.events?.destroy();
|
||||||
|
|
||||||
|
patchGlTextureSystem(renderer);
|
||||||
|
|
||||||
return renderer;
|
return renderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user