nitro-renderer/src/nitro/room/object/visualization/room/rasterizer/basic/PlaneMaterialCellMatrix.ts

706 lines
21 KiB
TypeScript

import { RenderTexture, Texture } from '@pixi/core';
import { Point, Rectangle } from '@pixi/math';
import { Sprite } from '@pixi/sprite';
import { IVector3D, NitroLogger, Vector3d } from '../../../../../../../api';
import { RoomTextureUtils, TextureUtils } from '../../../../../../../pixi-proxy';
import { Randomizer } from '../../utils';
import { PlaneMaterialCell } from './PlaneMaterialCell';
import { PlaneMaterialCellColumn } from './PlaneMaterialCellColumn';
export class PlaneMaterialCellMatrix
{
public static REPEAT_MODE_ALL: number = 1;
public static REPEAT_MODE_BORDERS: number = 2;
public static REPEAT_MODE_CENTER: number = 3;
public static REPEAT_MODE_FIRST: number = 4;
public static REPEAT_MODE_LAST: number = 5;
public static REPEAT_MODE_RANDOM: number = 6;
public static REPEAT_MODE_DEFAULT: number = PlaneMaterialCellMatrix.REPEAT_MODE_ALL;//1
public static MIN_NORMAL_COORDINATE_VALUE: number = -1;
public static MAX_NORMAL_COORDINATE_VALUE: number = 1;
public static ALIGN_TOP: number = 1;
public static ALIGN_BOTTOM: number = 2;
public static ALIGN_DEFAULT: number = PlaneMaterialCellMatrix.ALIGN_TOP;//1
private _columns: PlaneMaterialCellColumn[];
private _repeatMode: number = 1;
private _align: number = 1;
private _cachedBitmapData: RenderTexture;
private _cachedBitmapNormal: Vector3d = null;
private _cachedBitmapHeight: number = 0;
private _isCached: boolean = false;
private _isStatic: boolean = true;
private _normalMinX: number = -1;
private _normalMaxX: number = 1;
private _normalMinY: number = -1;
private _normalMaxY: number = 1;
private _texturePool: Map<string, RenderTexture>;
constructor(totalColumns: number, repeatMode: number = 1, align: number = 1, normalMinX: number = -1, normalMaxX: number = 1, normalMinY: number = -1, normalMaxY: number = 1)
{
this._columns = [];
if(totalColumns < 1) totalColumns = 1;
let _local_8 = 0;
while(_local_8 < totalColumns)
{
this._columns.push(null);
_local_8++;
}
this._repeatMode = repeatMode;
this._align = align;
this._normalMinX = normalMinX;
this._normalMaxX = normalMaxX;
this._normalMinY = normalMinY;
this._normalMaxY = normalMaxY;
this._texturePool = new Map();
if(this._repeatMode === PlaneMaterialCellMatrix.REPEAT_MODE_RANDOM) this._isStatic = false;
}
private static nextRandomColumnIndex(totalColumns: number): number
{
const _local_2 = Randomizer.getValues(1, 0, (totalColumns * 17631));
return _local_2[0] % totalColumns;
}
public get normalMinX(): number
{
return this._normalMinX;
}
public get normalMaxX(): number
{
return this._normalMaxX;
}
public get normalMinY(): number
{
return this._normalMinY;
}
public get normalMaxY(): number
{
return this._normalMaxY;
}
public isBottomAligned(): boolean
{
return this._align === PlaneMaterialCellMatrix.ALIGN_BOTTOM;
}
public get isStatic(): boolean
{
return this._isStatic;
}
public dispose(): void
{
if(this._cachedBitmapData)
{
this._cachedBitmapData.destroy(true);
this._cachedBitmapData = null;
}
if(this._cachedBitmapNormal) this._cachedBitmapNormal = null;
}
public clearCache(): void
{
if(!this._isCached) return;
if(this._cachedBitmapData)
{
this._cachedBitmapData.destroy();
this._cachedBitmapData = null;
}
if(this._cachedBitmapNormal)
{
this._cachedBitmapNormal.x = 0;
this._cachedBitmapNormal.y = 0;
this._cachedBitmapNormal.z = 0;
}
if(this._columns && this._columns.length)
{
for(const column of this._columns)
{
if(!column) continue;
column.clearCache();
}
}
if(this._texturePool && this._texturePool.size)
{
this._texturePool.forEach(texture => texture.destroy(true));
this._texturePool.clear();
}
this._isCached = false;
}
public createColumn(index: number, width: number, cells: PlaneMaterialCell[], repeatMode: number = 1): boolean
{
if((index < 0) || (index >= this._columns.length)) return false;
const newColumn = new PlaneMaterialCellColumn(width, cells, repeatMode);
const oldColumn = this._columns[index];
if(oldColumn) oldColumn.dispose();
this._columns[index] = newColumn;
if(newColumn && !newColumn.isStatic) this._isStatic = false;
return true;
}
public render(canvas: RenderTexture, width: number, height: number, normal: IVector3D, useTexture: boolean, offsetX: number, offsetY: number, topAlign: boolean): RenderTexture
{
if(width < 1) width = 1;
if(height < 1) height = 1;
if(!canvas || (canvas.width !== width) || (canvas.height !== height)) canvas = null;
if(!this._cachedBitmapNormal) this._cachedBitmapNormal = new Vector3d();
if(this.isStatic)
{
if(this._cachedBitmapData)
{
if((this._cachedBitmapData.width === width) && (this._cachedBitmapData.height === height) && Vector3d.isEqual(this._cachedBitmapNormal, normal))
{
if(canvas)
{
this.copyCachedBitmapOnCanvas(canvas, this._cachedBitmapHeight, offsetY, topAlign);
return canvas;
}
return this._cachedBitmapData;
}
this._cachedBitmapData = null;
}
}
else
{
this._cachedBitmapData = null;
}
this._isCached = true;
this._cachedBitmapNormal.assign(normal);
if(!useTexture)
{
this._cachedBitmapHeight = height;
if(!this._cachedBitmapData)
{
this._cachedBitmapData = this._texturePool.get(`${width}:${height}`);
if(!this._cachedBitmapData)
{
this._cachedBitmapData = RoomTextureUtils.createAndFillRenderTexture(width, height);
this._texturePool.set(`${width}:${height}`, this._cachedBitmapData);
}
else
{
TextureUtils.clearAndFillRenderTexture(this._cachedBitmapData);
}
}
else
{
TextureUtils.clearAndFillRenderTexture(this._cachedBitmapData);
}
if(canvas)
{
this.copyCachedBitmapOnCanvas(canvas, height, offsetY, topAlign);
return canvas;
}
return this._cachedBitmapData;
}
if(!this._cachedBitmapData)
{
this._cachedBitmapHeight = height;
this._cachedBitmapData = this._texturePool.get(`${width}:${height}`);
if(!this._cachedBitmapData)
{
this._cachedBitmapData = RoomTextureUtils.createRenderTexture(width, height);
this._texturePool.set(`${width}:${height}`, this._cachedBitmapData);
}
else
{
TextureUtils.clearRenderTexture(this._cachedBitmapData);
}
}
const columns: RenderTexture[] = [];
let columnIndex = 0;
while(columnIndex < this._columns.length)
{
const column = this._columns[columnIndex];
if(column)
{
const columnBitmapData = column.render(height, normal, offsetX, offsetY);
if(columnBitmapData) columns.push(columnBitmapData);
}
columnIndex++;
}
if(!columns.length)
{
if(canvas) return canvas;
return this._cachedBitmapData;
}
let maxColumnHeight = 0;
switch(this._repeatMode)
{
case PlaneMaterialCellMatrix.REPEAT_MODE_BORDERS:
NitroLogger.log('REPEAT_MODE_BORDERS');
// maxColumnHeight = this.renderRepeatBorders(this._cachedBitmapData, columns);
break;
case PlaneMaterialCellMatrix.REPEAT_MODE_CENTER:
NitroLogger.log('REPEAT_MODE_CENTER');
// maxColumnHeight = this.renderRepeatCenter(this._cachedBitmapData, columns);
break;
case PlaneMaterialCellMatrix.REPEAT_MODE_FIRST:
NitroLogger.log('REPEAT_MODE_FIRST');
// maxColumnHeight = this.renderRepeatFirst(this._cachedBitmapData, columns);
break;
case PlaneMaterialCellMatrix.REPEAT_MODE_LAST:
NitroLogger.log('REPEAT_MODE_LAST');
// maxColumnHeight = this.renderRepeatLast(this._cachedBitmapData, columns);
break;
case PlaneMaterialCellMatrix.REPEAT_MODE_RANDOM:
maxColumnHeight = this.renderRepeatRandom(this._cachedBitmapData, columns);
break;
default:
maxColumnHeight = this.renderRepeatAll(this._cachedBitmapData, columns);
break;
}
this._cachedBitmapHeight = maxColumnHeight;
if(canvas)
{
this.copyCachedBitmapOnCanvas(canvas, maxColumnHeight, offsetY, topAlign);
return canvas;
}
return this._cachedBitmapData;
}
private copyCachedBitmapOnCanvas(canvas: RenderTexture, height: number, offsetY: number, topAlign: boolean): void
{
if(!canvas || !this._cachedBitmapData || (canvas === this._cachedBitmapData)) return;
if(!topAlign) offsetY = ((canvas.height - height) - offsetY);
let bounds: Rectangle = null;
if(this._align === PlaneMaterialCellMatrix.ALIGN_TOP)
{
bounds = new Rectangle(0, 0, this._cachedBitmapData.width, this._cachedBitmapHeight);
}
else
{
bounds = new Rectangle(0, (this._cachedBitmapData.height - this._cachedBitmapHeight), this._cachedBitmapData.width, this._cachedBitmapHeight);
}
const texture = new Texture(this._cachedBitmapData.baseTexture, bounds);
const sprite = new Sprite(texture);
sprite.position.set(0, offsetY);
TextureUtils.writeToRenderTexture(sprite, canvas, false);
}
private getColumnsWidth(columns: RenderTexture[]): number
{
if(!columns || !columns.length) return 0;
let width = 0;
for(const texture of columns)
{
if(!texture) continue;
width += texture.width;
}
return width;
}
private renderColumns(canvas: RenderTexture, columns: RenderTexture[], x: number, flag: boolean): Point
{
if(!canvas || !columns || !columns.length) return new Point(x, 0);
let height = 0;
let i = 0;
while(i < columns.length)
{
const column = flag ? columns[i] : columns[((columns.length - 1) - i)];
if(column)
{
if(!flag) x = (x - column.width);
let y = 0;
if(this._align == PlaneMaterialCellMatrix.ALIGN_BOTTOM) y = (canvas.height - column.height);
const sprite = new Sprite(column);
sprite.position.set(x, y);
TextureUtils.writeToRenderTexture(sprite, canvas, false);
if(column.height > height) height = column.height;
if(flag) x = (x + column.width);
if((flag && (x >= canvas.width)) || (!flag && (x <= 0))) return new Point(x, height);
}
i++;
}
return new Point(x, height);
}
private renderRepeatAll(canvas: RenderTexture, columns: RenderTexture[]): number
{
if(!canvas || !columns || !columns.length) return 0;
const totalWidth: number = this.getColumnsWidth(columns);
let x = 0;
let y = 0;
while(x < canvas.width)
{
const point = this.renderColumns(canvas, columns, x, true);
x = point.x;
if(point.y > y) y = point.y;
if(!point.x) return y;
}
return y;
}
// private renderRepeatBorders(k:BitmapData, _arg_2:Array): number
// {
// if ((((_arg_2 == null) || (_arg_2.length == 0)) || (k == null)))
// {
// return 0;
// }
// var _local_3: number;
// var _local_4:BitmapData;
// var _local_5:Array = [];
// var _local_6: number;
// var _local_7: number;
// _local_7 = 1;
// while (_local_7 < (_arg_2.length - 1))
// {
// _local_4 = (_arg_2[_local_7] as BitmapData);
// if (_local_4 != null)
// {
// _local_6 = (_local_6 + _local_4.width);
// _local_5.push(_local_4);
// }
// _local_7++;
// }
// if (this._columns.length == 1)
// {
// _local_4 = (this._columns[0] as BitmapData);
// if (_local_4 != null)
// {
// _local_6 = _local_4.width;
// _local_5.push(_local_4);
// }
// }
// var _local_8:* = ((k.width - _local_6) >> 1);
// var _local_9:Point;
// _local_9 = this.renderColumns(k, _local_5, _local_8, true);
// var _local_10: number = _local_9.x;
// if (_local_9.y > _local_3)
// {
// _local_3 = _local_9.y;
// }
// _local_4 = (_arg_2[0] as BitmapData);
// if (_local_4 != null)
// {
// _local_5 = [_local_4];
// while (_local_8 >= 0)
// {
// _local_9 = this.renderColumns(k, _local_5, _local_8, false);
// _local_8 = _local_9.x;
// if (_local_9.y > _local_3)
// {
// _local_3 = _local_9.y;
// }
// }
// }
// _local_4 = (_arg_2[(_arg_2.length - 1)] as BitmapData);
// if (_local_4 != null)
// {
// _local_5 = [_local_4];
// while (_local_10 < k.height)
// {
// _local_9 = this.renderColumns(k, _local_5, _local_10, true);
// _local_10 = _local_9.x;
// if (_local_9.y > _local_3)
// {
// _local_3 = _local_9.y;
// }
// }
// }
// return _local_3;
// }
// private renderRepeatCenter(k:BitmapData, _arg_2:Array): number
// {
// var _local_14: number;
// var _local_15: number;
// var _local_16: number;
// var _local_17: number;
// var _local_18:Array;
// if ((((_arg_2 == null) || (_arg_2.length == 0)) || (k == null)))
// {
// return 0;
// }
// var _local_3: number;
// var _local_4:BitmapData;
// var _local_5:Array = [];
// var _local_6:Array = [];
// var _local_7: number;
// var _local_8: number;
// var _local_9: number;
// _local_9 = 0;
// while (_local_9 < (_arg_2.length >> 1))
// {
// _local_4 = (_arg_2[_local_9] as BitmapData);
// if (_local_4 != null)
// {
// _local_7 = (_local_7 + _local_4.width);
// _local_5.push(_local_4);
// }
// _local_9++;
// }
// _local_9 = ((_arg_2.length >> 1) + 1);
// while (_local_9 < _arg_2.length)
// {
// _local_4 = (_arg_2[_local_9] as BitmapData);
// if (_local_4 != null)
// {
// _local_8 = (_local_8 + _local_4.width);
// _local_6.push(_local_4);
// }
// _local_9++;
// }
// var _local_10:Point;
// var _local_11: number;
// var _local_12: number;
// var _local_13: number = k.width;
// if ((_local_7 + _local_8) > k.width)
// {
// _local_11 = ((_local_7 + _local_8) - k.width);
// _local_12 = (_local_12 - (_local_11 >> 1));
// _local_13 = (_local_13 + (_local_11 - (_local_11 >> 1)));
// }
// if (_local_11 == 0)
// {
// _local_4 = (_arg_2[(_arg_2.length >> 1)] as BitmapData);
// if (_local_4 != null)
// {
// _local_14 = _local_4.width;
// _local_15 = (k.width - (_local_7 + _local_8));
// _local_16 = (Math.ceil((_local_15 / _local_14)) * _local_14);
// _local_12 = (_local_7 - ((_local_16 - _local_15) >> 1));
// _local_17 = (_local_12 + _local_16);
// _local_18 = [_local_4];
// while (_local_12 < _local_17)
// {
// _local_10 = this.renderColumns(k, _local_18, _local_12, true);
// _local_12 = _local_10.x;
// if (_local_10.y > _local_3)
// {
// _local_3 = _local_10.y;
// }
// }
// }
// }
// _local_12 = 0;
// _local_10 = this.renderColumns(k, _local_5, _local_12, true);
// if (_local_10.y > _local_3)
// {
// _local_3 = _local_10.y;
// }
// _local_10 = this.renderColumns(k, _local_6, _local_13, false);
// if (_local_10.y > _local_3)
// {
// _local_3 = _local_10.y;
// }
// return _local_3;
// }
// private renderRepeatFirst(k:BitmapData, _arg_2:Array): number
// {
// var _local_7:Array;
// if ((((_arg_2 == null) || (_arg_2.length == 0)) || (k == null)))
// {
// return 0;
// }
// var _local_3: number;
// var _local_4:BitmapData;
// var _local_5: number = k.width;
// var _local_6:Point = this.renderColumns(k, _arg_2, _local_5, false);
// _local_5 = _local_6.x;
// if (_local_6.y > _local_3)
// {
// _local_3 = _local_6.y;
// }
// _local_4 = (_arg_2[0] as BitmapData);
// if (_local_4 != null)
// {
// _local_7 = [_local_4];
// while (_local_5 >= 0)
// {
// _local_6 = this.renderColumns(k, _local_7, _local_5, false);
// _local_5 = _local_6.x;
// if (_local_6.y > _local_3)
// {
// _local_3 = _local_6.y;
// }
// }
// }
// return _local_3;
// }
// private renderRepeatLast(k:BitmapData, _arg_2:Array): number
// {
// var _local_7:Array;
// if ((((_arg_2 == null) || (_arg_2.length == 0)) || (k == null)))
// {
// return 0;
// }
// var _local_3: number;
// var _local_4:BitmapData;
// var _local_5: number;
// var _local_6:Point = this.renderColumns(k, _arg_2, _local_5, true);
// _local_5 = _local_6.x;
// if (_local_6.y > _local_3)
// {
// _local_3 = _local_6.y;
// }
// _local_4 = (_arg_2[(_arg_2.length - 1)] as BitmapData);
// if (_local_4 != null)
// {
// _local_7 = [_local_4];
// while (_local_5 < k.width)
// {
// _local_6 = this.renderColumns(k, _local_7, _local_5, true);
// _local_5 = _local_6.x;
// if (_local_6.y > _local_3)
// {
// _local_3 = _local_6.y;
// }
// }
// }
// return _local_3;
// }
private renderRepeatRandom(canvas: RenderTexture, columns: RenderTexture[]): number
{
if(!canvas || !columns || !columns.length) return 0;
let height = 0;
let width = 0;
while(width < canvas.width)
{
const column = columns[PlaneMaterialCellMatrix.nextRandomColumnIndex(columns.length)];
if(column != null)
{
const point = this.renderColumns(canvas, [ column ], width, true);
width = point.x;
if(point.y > height)
{
height = point.y;
}
}
else
{
return height;
}
}
return height;
}
public getColumns(width: number): PlaneMaterialCellColumn[]
{
if(this._repeatMode === PlaneMaterialCellMatrix.REPEAT_MODE_RANDOM)
{
const columns: PlaneMaterialCellColumn[] = [];
let columnIndex = 0;
while(columnIndex < width)
{
const column = this._columns[PlaneMaterialCellMatrix.nextRandomColumnIndex(this._columns.length)];
if(column)
{
columns.push(column);
if(column.width > 1) columnIndex += column.width;
else break;
}
else break;
}
return columns;
}
return this._columns;
}
}