979 lines
30 KiB
TypeScript
979 lines
30 KiB
TypeScript
import { Renderer, RenderTexture, Resource, Texture } from '@pixi/core';
|
|
import { Matrix, Point } from '@pixi/math';
|
|
import { Sprite } from '@pixi/sprite';
|
|
import { IRoomGeometry, IRoomPlane, IVector3D, Vector3d } from '../../../../../api';
|
|
import { PixiApplicationProxy, RoomTextureUtils, TextureUtils } from '../../../../../pixi-proxy';
|
|
import { ColorConverter } from '../../../../../room';
|
|
import { PlaneMaskManager } from './mask';
|
|
import { PlaneDrawingData } from './PlaneDrawingData';
|
|
import { IPlaneRasterizer } from './rasterizer';
|
|
import { RoomPlaneBitmapMask } from './RoomPlaneBitmapMask';
|
|
import { RoomPlaneRectangleMask } from './RoomPlaneRectangleMask';
|
|
import { PlaneBitmapData, Randomizer } from './utils';
|
|
|
|
export class RoomPlane implements IRoomPlane
|
|
{
|
|
private static ZERO_POINT: Point = new Point(0, 0);
|
|
public static TYPE_UNDEFINED: number = 0;
|
|
public static TYPE_WALL: number = 1;
|
|
public static TYPE_FLOOR: number = 2;
|
|
public static TYPE_LANDSCAPE: number = 3;
|
|
private static _uniqueIdCounter: number = 1;
|
|
|
|
private _disposed: boolean;
|
|
private _randomSeed: number;
|
|
private _origin: Vector3d;
|
|
private _location: Vector3d;
|
|
private _leftSide: Vector3d;
|
|
private _rightSide: Vector3d;
|
|
private _normal: Vector3d;
|
|
private _secondaryNormals: Vector3d[];
|
|
private _geometryUpdateId: number;
|
|
private _type: number;
|
|
private _isVisible: boolean;
|
|
private _bitmapData: RenderTexture;
|
|
private _hasTexture: boolean;
|
|
private _offset: Point;
|
|
private _relativeDepth: number;
|
|
private _color: number;
|
|
private _rasterizer: IPlaneRasterizer;
|
|
private _maskManager: PlaneMaskManager = null;
|
|
private _id: string;
|
|
private _uniqueId: number;
|
|
private _textureOffsetX: number;
|
|
private _textureOffsetY: number;
|
|
private _textureMaxX: number;
|
|
private _textureMaxY: number;
|
|
private _textures: Map<string, PlaneBitmapData>;
|
|
private _activeTexture: PlaneBitmapData;
|
|
private _useMask: boolean;
|
|
private _bitmapMasks: RoomPlaneBitmapMask[];
|
|
private _rectangleMasks: RoomPlaneRectangleMask[];
|
|
private _maskChanged: boolean;
|
|
private _maskBitmapData: RenderTexture;
|
|
private _maskPixels: Uint8Array;
|
|
private _bitmapMasksOld: RoomPlaneBitmapMask[];
|
|
private _rectangleMasksOld: RoomPlaneRectangleMask[];
|
|
private _cornerA: Vector3d;
|
|
private _cornerB: Vector3d;
|
|
private _cornerC: Vector3d;
|
|
private _cornerD: Vector3d;
|
|
private _width: number = 0;
|
|
private _height: number = 0;
|
|
private _canBeVisible: boolean;
|
|
|
|
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)
|
|
{
|
|
this._secondaryNormals = [];
|
|
this._bitmapMasks = [];
|
|
this._rectangleMasks = [];
|
|
this._bitmapMasksOld = [];
|
|
this._rectangleMasksOld = [];
|
|
this._randomSeed = randomSeed;
|
|
this._bitmapData = null;
|
|
this._maskBitmapData = null;
|
|
this._maskChanged = false;
|
|
this._activeTexture = null;
|
|
this._origin = new Vector3d();
|
|
this._origin.assign(origin);
|
|
this._location = new Vector3d();
|
|
this._location.assign(location);
|
|
this._leftSide = new Vector3d();
|
|
this._leftSide.assign(leftSide);
|
|
this._rightSide = new Vector3d();
|
|
this._rightSide.assign(rightSide);
|
|
this._normal = Vector3d.crossProduct(this._leftSide, this._rightSide);
|
|
|
|
if(this._normal.length > 0)
|
|
{
|
|
this._normal.multiply((1 / this._normal.length));
|
|
}
|
|
|
|
if(secondaryNormals != null)
|
|
{
|
|
for(const entry of secondaryNormals)
|
|
{
|
|
if(!entry) continue;
|
|
|
|
const vector = new Vector3d();
|
|
|
|
vector.assign(entry);
|
|
|
|
this._secondaryNormals.push(vector);
|
|
}
|
|
}
|
|
this._disposed = false;
|
|
this._isVisible = false;
|
|
this._id = null;
|
|
this._hasTexture = true;
|
|
this._geometryUpdateId = -1;
|
|
this._offset = new Point();
|
|
this._relativeDepth = 0;
|
|
this._type = type;
|
|
this._color = 0;
|
|
this._rasterizer = null;
|
|
this._canBeVisible = true;
|
|
this._textures = new Map();
|
|
this._cornerA = new Vector3d();
|
|
this._cornerB = new Vector3d();
|
|
this._cornerC = new Vector3d();
|
|
this._cornerD = new Vector3d();
|
|
this._width = 0;
|
|
this._height = 0;
|
|
this._textureOffsetX = textureOffsetX;
|
|
this._textureOffsetY = textureOffsetY;
|
|
this._textureMaxX = textureMaxX;
|
|
this._textureMaxY = textureMaxY;
|
|
this._useMask = usesMask;
|
|
this._uniqueId = ++RoomPlane._uniqueIdCounter;
|
|
}
|
|
|
|
private static blend(a: number, b: number): number
|
|
{
|
|
return ColorConverter.colorize(b, (a | 0xFF000000)) & 0xFFFFFF;
|
|
}
|
|
|
|
public set canBeVisible(k: boolean)
|
|
{
|
|
if(k !== this._canBeVisible)
|
|
{
|
|
if(!this._canBeVisible) this.resetTextureCache();
|
|
|
|
this._canBeVisible = k;
|
|
}
|
|
}
|
|
|
|
public get canBeVisible(): boolean
|
|
{
|
|
return this._canBeVisible;
|
|
}
|
|
|
|
public get bitmapData(): Texture<Resource>
|
|
{
|
|
if(!this.visible || !this._bitmapData) return null;
|
|
|
|
return this._bitmapData;
|
|
}
|
|
|
|
public get maskBitmapData(): RenderTexture
|
|
{
|
|
if(!this.visible || !this._maskBitmapData) return null;
|
|
|
|
return this._maskBitmapData;
|
|
}
|
|
|
|
public get visible(): boolean
|
|
{
|
|
return (this._isVisible && this._canBeVisible);
|
|
}
|
|
|
|
public get offset(): Point
|
|
{
|
|
return this._offset;
|
|
}
|
|
|
|
public get relativeDepth(): number
|
|
{
|
|
return this._relativeDepth;
|
|
}
|
|
|
|
public get color(): number
|
|
{
|
|
return this._color;
|
|
}
|
|
|
|
public set color(k: number)
|
|
{
|
|
this._color = k;
|
|
}
|
|
|
|
public get type(): number
|
|
{
|
|
return this._type;
|
|
}
|
|
|
|
public get leftSide(): IVector3D
|
|
{
|
|
return this._leftSide;
|
|
}
|
|
|
|
public get rightSide(): IVector3D
|
|
{
|
|
return this._rightSide;
|
|
}
|
|
|
|
public get location(): IVector3D
|
|
{
|
|
return this._location;
|
|
}
|
|
|
|
public get normal(): IVector3D
|
|
{
|
|
return this._normal;
|
|
}
|
|
|
|
public get hasTexture(): boolean
|
|
{
|
|
return this._hasTexture;
|
|
}
|
|
|
|
public set hasTexture(k: boolean)
|
|
{
|
|
this._hasTexture = k;
|
|
}
|
|
|
|
public set rasterizer(k: IPlaneRasterizer)
|
|
{
|
|
this._rasterizer = k;
|
|
}
|
|
|
|
public set maskManager(k: PlaneMaskManager)
|
|
{
|
|
this._maskManager = k;
|
|
}
|
|
|
|
public set id(k: string)
|
|
{
|
|
if(k === this._id) return;
|
|
|
|
this.resetTextureCache();
|
|
this._id = k;
|
|
}
|
|
|
|
public get uniqueId(): number
|
|
{
|
|
return this._uniqueId;
|
|
}
|
|
|
|
public dispose(): void
|
|
{
|
|
if(this._bitmapData)
|
|
{
|
|
this._bitmapData.destroy(true);
|
|
|
|
this._bitmapData = null;
|
|
}
|
|
|
|
if(this._textures)
|
|
{
|
|
for(const bitmap of this._textures.values())
|
|
{
|
|
if(!bitmap) continue;
|
|
|
|
if(bitmap.texture) bitmap.texture.destroy();
|
|
|
|
bitmap.dispose();
|
|
}
|
|
|
|
this._textures = null;
|
|
}
|
|
|
|
this._activeTexture = null;
|
|
this._location = null;
|
|
this._origin = null;
|
|
this._leftSide = null;
|
|
this._rightSide = null;
|
|
this._normal = null;
|
|
this._rasterizer = null;
|
|
this._cornerA = null;
|
|
this._cornerB = null;
|
|
this._cornerC = null;
|
|
this._cornerD = null;
|
|
this._bitmapMasks = null;
|
|
this._rectangleMasks = null;
|
|
this._maskPixels = null;
|
|
|
|
if(this._maskBitmapData)
|
|
{
|
|
this._maskBitmapData.destroy(true);
|
|
|
|
this._maskBitmapData = null;
|
|
}
|
|
|
|
this._disposed = true;
|
|
}
|
|
|
|
public copyBitmapData(k: Texture<Resource>): Texture<Resource>
|
|
{
|
|
if(!this.visible || !this._bitmapData || !k) return null;
|
|
|
|
if((this._bitmapData.width !== k.width) || (this._bitmapData.height !== k.height)) return null;
|
|
|
|
//k.copyPixels(this._bitmapData, this._bitmapData.rect, RoomPlane.ZERO_POINT);
|
|
return k;
|
|
}
|
|
|
|
private cacheTexture(k: string, _arg_2: PlaneBitmapData): boolean
|
|
{
|
|
const existing = this._textures.get(k);
|
|
|
|
if(existing)
|
|
{
|
|
this._textures.delete(k);
|
|
|
|
existing.dispose();
|
|
}
|
|
|
|
this._activeTexture = _arg_2;
|
|
this._textures.set(k, _arg_2);
|
|
|
|
return true;
|
|
}
|
|
|
|
private resetTextureCache(k: RenderTexture = null): void
|
|
{
|
|
if(this._textures && this._textures.size)
|
|
{
|
|
for(const bitmap of this._textures.values())
|
|
{
|
|
if(!bitmap) continue;
|
|
|
|
bitmap.dispose();
|
|
}
|
|
|
|
this._textures.clear();
|
|
}
|
|
|
|
this._activeTexture = null;
|
|
}
|
|
|
|
private getTextureIdentifier(k: number): string
|
|
{
|
|
if(this._rasterizer) return this._rasterizer.getTextureIdentifier(k, this.normal);
|
|
|
|
return k.toString();
|
|
}
|
|
|
|
private needsNewTexture(k: IRoomGeometry, _arg_2: number): boolean
|
|
{
|
|
if(!k) return false;
|
|
|
|
let planeBitmap = this._activeTexture;
|
|
|
|
if(!planeBitmap)
|
|
{
|
|
planeBitmap = this._textures.get(this.getTextureIdentifier(k.scale));
|
|
}
|
|
|
|
this.updateMaskChangeStatus();
|
|
|
|
if(this._canBeVisible && ((!planeBitmap || ((planeBitmap.timeStamp >= 0) && (_arg_2 > planeBitmap.timeStamp))) || this._maskChanged)) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
private getTexture(geometry: IRoomGeometry, timeSinceStartMs: number): RenderTexture
|
|
{
|
|
if(!geometry) return null;
|
|
|
|
let bitmapData: PlaneBitmapData = null;
|
|
|
|
if(this.needsNewTexture(geometry, timeSinceStartMs))
|
|
{
|
|
const identifier = this.getTextureIdentifier(geometry.scale);
|
|
const width = this._leftSide.length * geometry.scale;
|
|
const height = this._rightSide.length * geometry.scale;
|
|
const normal = geometry.getCoordinatePosition(this._normal);
|
|
|
|
if(this._activeTexture)
|
|
{
|
|
bitmapData = this._activeTexture;
|
|
}
|
|
else
|
|
{
|
|
bitmapData = this._textures.get(identifier);
|
|
}
|
|
|
|
let texture: RenderTexture = null;
|
|
|
|
if(bitmapData) texture = bitmapData.texture;
|
|
|
|
if(this._rasterizer)
|
|
{
|
|
bitmapData = this._rasterizer.render(this._uniqueId.toString(), texture, this._id, width, height, geometry.scale, normal, this._hasTexture, this._textureOffsetX, this._textureOffsetY, this._textureMaxX, this._textureMaxY, timeSinceStartMs);
|
|
|
|
if(bitmapData && texture && (bitmapData?.texture !== texture)) texture.destroy(true);
|
|
}
|
|
else
|
|
{
|
|
const renderTexture = RoomTextureUtils.createAndFillRenderTexture(width, height);
|
|
|
|
bitmapData = new PlaneBitmapData(renderTexture, -1);
|
|
}
|
|
|
|
if(bitmapData)
|
|
{
|
|
this.updateMask(bitmapData.texture, geometry);
|
|
this.cacheTexture(identifier, bitmapData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(this._activeTexture)
|
|
{
|
|
bitmapData = this._activeTexture;
|
|
}
|
|
else
|
|
{
|
|
bitmapData = this._textures.get(this.getTextureIdentifier(geometry.scale));
|
|
}
|
|
}
|
|
|
|
if(bitmapData)
|
|
{
|
|
this._activeTexture = bitmapData;
|
|
|
|
return bitmapData.texture;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private resolveMasks(k: IRoomGeometry): PlaneDrawingData
|
|
{
|
|
if(!this._useMask) return null;
|
|
|
|
const drawingData = new PlaneDrawingData();
|
|
|
|
const index = 0;
|
|
|
|
while(index < this._bitmapMasks.length)
|
|
{
|
|
const mask = this._bitmapMasks[index];
|
|
|
|
if(mask)
|
|
{
|
|
const planeMask = this._maskManager.getMask(mask.type);
|
|
|
|
if(planeMask)
|
|
{
|
|
const assetName = planeMask.getAssetName(k.scale);
|
|
|
|
if(assetName)
|
|
{
|
|
const position = k.getCoordinatePosition(this._normal);
|
|
const asset = planeMask.getGraphicAsset(k.scale, position);
|
|
|
|
if(asset)
|
|
{
|
|
const x = (this._maskBitmapData.width * (1 - (mask.leftSideLoc / this._leftSide.length)));
|
|
const y = (this._maskBitmapData.height * (1 - (mask.rightSideLoc / this._rightSide.length)));
|
|
|
|
drawingData.addMask(assetName, new Point((x + asset.offsetX), (y + asset.offsetY)), asset.flipH, asset.flipV);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return drawingData;
|
|
}
|
|
|
|
private screenWidth(k: IRoomGeometry): number
|
|
{
|
|
const _local_2 = k.getScreenPoint(new Vector3d(0, 0, 0));
|
|
const _local_3 = k.getScreenPoint(new Vector3d(0, 1, 0));
|
|
|
|
return Math.round((this._leftSide.length * Math.abs((_local_2.x - _local_3.x))));
|
|
}
|
|
|
|
public getDrawingDatas(geometry: IRoomGeometry): PlaneDrawingData[]
|
|
{
|
|
const drawingDatas: PlaneDrawingData[] = [];
|
|
|
|
if(this._isVisible)
|
|
{
|
|
const maskData = this.resolveMasks(geometry);
|
|
const layers = this._rasterizer.getLayers(this._id);
|
|
|
|
for(const layer of layers)
|
|
{
|
|
if(this._hasTexture && layer.getMaterial())
|
|
{
|
|
const normal = geometry.getCoordinatePosition(this._normal);
|
|
const cellMatrix = layer.getMaterial().getMaterialCellMatrix(normal);
|
|
const data = new PlaneDrawingData(maskData, RoomPlane.blend(this._color, layer.getColor()), cellMatrix.isBottomAligned());
|
|
|
|
Randomizer.setSeed(this._randomSeed);
|
|
|
|
for(const column of cellMatrix.getColumns(this.screenWidth(geometry)))
|
|
{
|
|
const assetNames: string[] = [];
|
|
|
|
for(const cell of column.getCells())
|
|
{
|
|
const name = cell.getAssetName(normal);
|
|
|
|
if(name) assetNames.push(name);
|
|
}
|
|
|
|
if(assetNames.length > 0)
|
|
{
|
|
if(!column.isRepeated()) assetNames.push('');
|
|
|
|
data.addAssetColumn(assetNames);
|
|
}
|
|
}
|
|
|
|
if(data.assetNameColumns.length > 0) drawingDatas.push(data);
|
|
}
|
|
else
|
|
{
|
|
const data = new PlaneDrawingData(maskData, RoomPlane.blend(this._color, layer.getColor()));
|
|
|
|
drawingDatas.push(data);
|
|
}
|
|
}
|
|
|
|
if(!drawingDatas.length) drawingDatas.push(new PlaneDrawingData(maskData, this._color));
|
|
}
|
|
|
|
return drawingDatas;
|
|
}
|
|
|
|
// private _Str_25956(k:PlaneBitmapData): void
|
|
// {
|
|
// }
|
|
|
|
public update(geometry: IRoomGeometry, timeSinceStartMs: number): boolean
|
|
{
|
|
if(!geometry || this._disposed) return false;
|
|
|
|
let geometryChanged = false;
|
|
|
|
if(this._geometryUpdateId != geometry.updateId) geometryChanged = true;
|
|
|
|
if(!geometryChanged || !this._canBeVisible)
|
|
{
|
|
if(!this.visible) return false;
|
|
}
|
|
|
|
if(geometryChanged)
|
|
{
|
|
this._activeTexture = null;
|
|
|
|
let cosAngle = 0;
|
|
|
|
cosAngle = Vector3d.cosAngle(geometry.directionAxis, this.normal);
|
|
|
|
if(cosAngle > -0.001)
|
|
{
|
|
if(this._isVisible)
|
|
{
|
|
this._isVisible = false;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
let i = 0;
|
|
|
|
while(i < this._secondaryNormals.length)
|
|
{
|
|
cosAngle = Vector3d.cosAngle(geometry.directionAxis, this._secondaryNormals[i]);
|
|
|
|
if(cosAngle > -0.001)
|
|
{
|
|
if(this._isVisible)
|
|
{
|
|
this._isVisible = false;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
this.updateCorners(geometry);
|
|
|
|
const originPos = geometry.getScreenPosition(this._origin);
|
|
const originZ = originPos.z;
|
|
|
|
let relativeDepth = (Math.max(this._cornerA.z, this._cornerB.z, this._cornerC.z, this._cornerD.z) - originZ);
|
|
|
|
if(this._type === RoomPlane.TYPE_FLOOR)
|
|
{
|
|
relativeDepth = (relativeDepth - ((this._location.z + Math.min(0, this._leftSide.z, this._rightSide.z)) * 8));
|
|
}
|
|
|
|
if(this._type === RoomPlane.TYPE_LANDSCAPE)
|
|
{
|
|
relativeDepth = (relativeDepth + 0.02);
|
|
}
|
|
|
|
this._relativeDepth = relativeDepth;
|
|
this._isVisible = true;
|
|
this._geometryUpdateId = geometry.updateId;
|
|
}
|
|
|
|
if(geometryChanged || this.needsNewTexture(geometry, timeSinceStartMs))
|
|
{
|
|
if(!this._bitmapData || (this._width !== this._bitmapData.width) || (this._height !== this._bitmapData.height))
|
|
{
|
|
if(this._bitmapData)
|
|
{
|
|
if((this._width !== this._bitmapData.width) || (this._height !== this._bitmapData.height))
|
|
{
|
|
this._bitmapData.destroy();
|
|
|
|
this._bitmapData = null;
|
|
|
|
if((this._width < 1) || (this._height < 1)) return true;
|
|
|
|
this._bitmapData = RoomTextureUtils.createAndFillRenderTexture(this._width, this._height);
|
|
}
|
|
else
|
|
{
|
|
if((this._width < 1) || (this._height < 1))
|
|
{
|
|
this._bitmapData.destroy();
|
|
|
|
this._bitmapData = null;
|
|
|
|
return true;
|
|
}
|
|
|
|
TextureUtils.clearAndFillRenderTexture(this._bitmapData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if((this._width < 1) || (this._height < 1)) return false;
|
|
|
|
this._bitmapData = RoomTextureUtils.createAndFillRenderTexture(this._width, this._height);
|
|
}
|
|
|
|
if(!this._bitmapData) return false;
|
|
}
|
|
else
|
|
{
|
|
TextureUtils.clearAndFillRenderTexture(this._bitmapData);
|
|
}
|
|
|
|
Randomizer.setSeed(this._randomSeed);
|
|
|
|
const texture = this.getTexture(geometry, timeSinceStartMs);
|
|
|
|
if(texture)
|
|
{
|
|
this.renderTexture(geometry, texture);
|
|
}
|
|
else
|
|
{
|
|
this.dispose();
|
|
|
|
return false;
|
|
}
|
|
|
|
return ((texture !== null) || geometryChanged);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private updateCorners(geometry: IRoomGeometry): void
|
|
{
|
|
this._cornerA.assign(geometry.getScreenPosition(this._location));
|
|
this._cornerB.assign(geometry.getScreenPosition(Vector3d.sum(this._location, this._rightSide)));
|
|
this._cornerC.assign(geometry.getScreenPosition(Vector3d.sum(Vector3d.sum(this._location, this._leftSide), this._rightSide)));
|
|
this._cornerD.assign(geometry.getScreenPosition(Vector3d.sum(this._location, this._leftSide)));
|
|
this._offset = geometry.getScreenPoint(this._origin);
|
|
this._cornerA.x = Math.round(this._cornerA.x);
|
|
this._cornerA.y = Math.round(this._cornerA.y);
|
|
this._cornerB.x = Math.round(this._cornerB.x);
|
|
this._cornerB.y = Math.round(this._cornerB.y);
|
|
this._cornerC.x = Math.round(this._cornerC.x);
|
|
this._cornerC.y = Math.round(this._cornerC.y);
|
|
this._cornerD.x = Math.round(this._cornerD.x);
|
|
this._cornerD.y = Math.round(this._cornerD.y);
|
|
this._offset.x = Math.round(this._offset.x);
|
|
this._offset.y = Math.round(this._offset.y);
|
|
|
|
const minX = Math.min(this._cornerA.x, this._cornerB.x, this._cornerC.x, this._cornerD.x);
|
|
const maxX = Math.max(this._cornerA.x, this._cornerB.x, this._cornerC.x, this._cornerD.x) - minX;
|
|
const minY = Math.min(this._cornerA.y, this._cornerB.y, this._cornerC.y, this._cornerD.y);
|
|
const maxY = Math.max(this._cornerA.y, this._cornerB.y, this._cornerC.y, this._cornerD.y) - minY;
|
|
|
|
this._offset.x = (this._offset.x - minX);
|
|
this._cornerA.x = (this._cornerA.x - minX);
|
|
this._cornerB.x = (this._cornerB.x - minX);
|
|
this._cornerC.x = (this._cornerC.x - minX);
|
|
this._cornerD.x = (this._cornerD.x - minX);
|
|
|
|
this._offset.y = (this._offset.y - minY);
|
|
this._cornerA.y = (this._cornerA.y - minY);
|
|
this._cornerB.y = (this._cornerB.y - minY);
|
|
this._cornerC.y = (this._cornerC.y - minY);
|
|
this._cornerD.y = (this._cornerD.y - minY);
|
|
|
|
this._width = maxX;
|
|
this._height = maxY;
|
|
}
|
|
|
|
private getMatrixForDimensions(width: number, height: number): Matrix
|
|
{
|
|
let _local_3: number = (this._cornerD.x - this._cornerC.x);
|
|
let _local_4: number = (this._cornerD.y - this._cornerC.y);
|
|
let _local_5: number = (this._cornerB.x - this._cornerC.x);
|
|
let _local_6: number = (this._cornerB.y - this._cornerC.y);
|
|
|
|
if((this._type === RoomPlane.TYPE_WALL) || (this._type === RoomPlane.TYPE_LANDSCAPE))
|
|
{
|
|
if(Math.abs((_local_5 - width)) <= 1) _local_5 = width;
|
|
|
|
if(Math.abs((_local_6 - width)) <= 1) _local_6 = width;
|
|
|
|
if(Math.abs((_local_3 - height)) <= 1) _local_3 = height;
|
|
|
|
if(Math.abs((_local_4 - height)) <= 1) _local_4 = height;
|
|
}
|
|
|
|
const xScale: number = (_local_5 / width);
|
|
const ySkew: number = (_local_6 / width);
|
|
const xSkew: number = (_local_3 / height);
|
|
const yScale: number = (_local_4 / height);
|
|
|
|
const matrix = new Matrix(xScale, ySkew, xSkew, yScale);
|
|
|
|
matrix.translate(this._cornerC.x, this._cornerC.y);
|
|
|
|
return matrix;
|
|
}
|
|
|
|
private renderTexture(geometry: IRoomGeometry, _arg_2: RenderTexture): void
|
|
{
|
|
if(((((((this._cornerA == null) || (this._cornerB == null)) || (this._cornerC == null)) || (this._cornerD == null)) || (_arg_2 == null)) || (this._bitmapData == null)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
this.draw(_arg_2, this.getMatrixForDimensions(_arg_2.width, _arg_2.height));
|
|
}
|
|
|
|
private draw(k: RenderTexture, matrix: Matrix): void
|
|
{
|
|
//k.baseTexture.mipmap = MIPMAP_MODES.OFF;
|
|
//k.baseTexture.scaleMode = SCALE_MODES.LINEAR;
|
|
|
|
TextureUtils.writeToRenderTexture(new Sprite(k), this._bitmapData, true, matrix);
|
|
}
|
|
|
|
public resetBitmapMasks(): void
|
|
{
|
|
if(this._disposed || !this._useMask || !this._bitmapMasks.length) return;
|
|
|
|
this._maskChanged = true;
|
|
this._bitmapMasks = [];
|
|
}
|
|
|
|
public addBitmapMask(maskType: string, leftSideLoc: number, rightSideLoc: number): boolean
|
|
{
|
|
if(!this._useMask) return false;
|
|
|
|
for(const mask of this._bitmapMasks)
|
|
{
|
|
if(!mask) continue;
|
|
|
|
if((((mask.type === maskType) && (mask.leftSideLoc === leftSideLoc)) && (mask.rightSideLoc === rightSideLoc))) return false;
|
|
}
|
|
|
|
const mask = new RoomPlaneBitmapMask(maskType, leftSideLoc, rightSideLoc);
|
|
|
|
this._bitmapMasks.push(mask);
|
|
this._maskChanged = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
public resetRectangleMasks(): void
|
|
{
|
|
if(!this._useMask || !this._rectangleMasks.length) return;
|
|
|
|
this._maskChanged = true;
|
|
this._rectangleMasks = [];
|
|
}
|
|
|
|
public addRectangleMask(k: number, _arg_2: number, _arg_3: number, _arg_4: number): boolean
|
|
{
|
|
if(this._useMask)
|
|
{
|
|
for(const mask of this._rectangleMasks)
|
|
{
|
|
if(!mask) continue;
|
|
|
|
if((((mask.leftSideLoc === k) && (mask.rightSideLoc === _arg_2)) && (mask.leftSideLength === _arg_3)) && (mask.rightSideLength === _arg_4)) return false;
|
|
}
|
|
|
|
const _local_5 = new RoomPlaneRectangleMask(k, _arg_2, _arg_3, _arg_4);
|
|
|
|
this._rectangleMasks.push(_local_5);
|
|
this._maskChanged = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private updateMaskChangeStatus(): void
|
|
{
|
|
if(!this._maskChanged) return;
|
|
|
|
let maskChanged = true;
|
|
|
|
if(this._bitmapMasks.length === this._bitmapMasksOld.length)
|
|
{
|
|
for(const mask of this._bitmapMasks)
|
|
{
|
|
if(!mask) continue;
|
|
|
|
let _local_6 = false;
|
|
|
|
for(const plane of this._bitmapMasksOld)
|
|
{
|
|
if(!plane) continue;
|
|
|
|
if(((plane.type === mask.type) && (plane.leftSideLoc === mask.leftSideLoc)) && (plane.rightSideLoc === mask.rightSideLoc))
|
|
{
|
|
_local_6 = true;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!_local_6)
|
|
{
|
|
maskChanged = false;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
maskChanged = false;
|
|
}
|
|
|
|
if(this._rectangleMasks.length > this._rectangleMasksOld.length) maskChanged = false;
|
|
|
|
if(maskChanged) this._maskChanged = false;
|
|
}
|
|
|
|
private updateMask(canvas: RenderTexture, geometry: IRoomGeometry): void
|
|
{
|
|
if(!canvas || !geometry) return;
|
|
|
|
if(((!this._useMask) || ((!this._bitmapMasks.length && !this._rectangleMasks.length) && !this._maskChanged)) || !this._maskManager) return;
|
|
|
|
const width = canvas.width;
|
|
const height = canvas.height;
|
|
|
|
this.updateMaskChangeStatus();
|
|
|
|
if(!this._maskBitmapData || (this._maskBitmapData.width !== width) || (this._maskBitmapData.height !== height))
|
|
{
|
|
if(this._maskBitmapData)
|
|
{
|
|
this._maskBitmapData.destroy(true);
|
|
this._maskBitmapData = null;
|
|
}
|
|
|
|
this._maskBitmapData = RoomTextureUtils.createAndFillRenderTexture(width, height);
|
|
this._maskChanged = true;
|
|
}
|
|
|
|
if(this._maskChanged)
|
|
{
|
|
this._bitmapMasksOld = [];
|
|
this._rectangleMasksOld = [];
|
|
|
|
if(this._maskBitmapData) TextureUtils.clearAndFillRenderTexture(this._maskBitmapData);
|
|
|
|
this.resetTextureCache(canvas);
|
|
|
|
const normal = geometry.getCoordinatePosition(this._normal);
|
|
|
|
let type: string = null;
|
|
let posX = 0;
|
|
let posY = 0;
|
|
let i = 0;
|
|
|
|
while(i < this._bitmapMasks.length)
|
|
{
|
|
const mask = this._bitmapMasks[i];
|
|
|
|
if(mask)
|
|
{
|
|
type = mask.type;
|
|
posX = (this._maskBitmapData.width - ((this._maskBitmapData.width * mask.leftSideLoc) / this._leftSide.length));
|
|
posY = (this._maskBitmapData.height - ((this._maskBitmapData.height * mask.rightSideLoc) / this._rightSide.length));
|
|
|
|
this._maskManager.updateMask(this._maskBitmapData, type, geometry.scale, normal, posX, posY);
|
|
this._bitmapMasksOld.push(new RoomPlaneBitmapMask(type, mask.leftSideLoc, mask.rightSideLoc));
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
i = 0;
|
|
|
|
while(i < this._rectangleMasks.length)
|
|
{
|
|
const rectMask = this._rectangleMasks[i];
|
|
|
|
if(rectMask)
|
|
{
|
|
posX = (this._maskBitmapData.width - ((this._maskBitmapData.width * rectMask.leftSideLoc) / this._leftSide.length));
|
|
posY = (this._maskBitmapData.height - ((this._maskBitmapData.height * rectMask.rightSideLoc) / this._rightSide.length));
|
|
|
|
const wd = ((this._maskBitmapData.width * rectMask.leftSideLength) / this._leftSide.length);
|
|
const ht = ((this._maskBitmapData.height * rectMask.rightSideLength) / this._rightSide.length);
|
|
|
|
/* this._maskBitmapData
|
|
.beginFill(0xFF0000)
|
|
.drawRect((posX - wd), (posY - ht), wd, ht)
|
|
.endFill(); */
|
|
|
|
this._rectangleMasksOld.push(new RoomPlaneRectangleMask(rectMask.leftSideLength, rectMask.rightSideLoc, rectMask.leftSideLength, rectMask.rightSideLength));
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
this._maskPixels = TextureUtils.getPixels(this._maskBitmapData);
|
|
|
|
this._maskChanged = false;
|
|
}
|
|
|
|
this.combineTextureMask(canvas, this._maskPixels);
|
|
}
|
|
|
|
private combineTextureMask(canvas: RenderTexture, maskPixels: Uint8Array): void
|
|
{
|
|
if(!canvas || !maskPixels) return;
|
|
|
|
const canvasPixels = TextureUtils.getPixels(canvas);
|
|
|
|
for(let i = 0; i < canvasPixels.length; i += 4)
|
|
{
|
|
const maskRed = maskPixels[i];
|
|
const maskGreen = maskPixels[i + 1];
|
|
const maskBlue = maskPixels[i + 2];
|
|
const maskAlpha = maskPixels[i + 3];
|
|
|
|
if(!maskRed && !maskGreen && !maskBlue) canvasPixels[i + 3] = 0;
|
|
}
|
|
|
|
const canvaGLTexture = canvas.baseTexture._glTextures['1']?.texture;
|
|
const gl = (PixiApplicationProxy.instance.renderer as Renderer)?.gl;
|
|
|
|
if(!canvaGLTexture || !gl) return;
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, canvaGLTexture);
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvasPixels);
|
|
}
|
|
}
|