refactor: 组合器固定输出结果大小而非可变

This commit is contained in:
unanmed 2025-10-20 18:27:10 +08:00
parent 66e60f5f15
commit 146866d51f
2 changed files with 39 additions and 69 deletions

View File

@ -21,7 +21,7 @@ import { isNil } from 'lodash-es';
interface IndexMarkedComposedData {
/** 组合数据 */
readonly data: ITextureComposedData;
readonly asset: ITextureComposedData;
/** 组合时最后一个用到的贴图的索引 */
readonly index: number;
}
@ -33,75 +33,37 @@ type TranslatedComposer<D, T> = ITextureComposer<
>;
export interface IGridComposerData {
/** 单张图集的最大宽度 */
readonly maxWidth: number;
/** 单张图集的最大高度 */
readonly maxHeight: number;
/** 单个贴图的宽度,与之不同的贴图将会被剔除并警告 */
readonly width: number;
/** 单个贴图的宽度,与之不同的贴图将会被剔除并警告 */
readonly height: number;
}
interface GridNeededSize {
/** 图集宽度 */
readonly width: number;
/** 图集高度 */
readonly height: number;
/** 一共有多少行 */
readonly rows: number;
/** 一共有多少列 */
readonly cols: number;
}
/**
*
*
*/
export class TextureGridComposer<T>
implements TranslatedComposer<IGridComposerData, T>
{
private getNeededSize(
tex: ITexture[],
start: number,
data: IGridComposerData
): GridNeededSize {
const maxRows = Math.floor(data.maxWidth / data.width);
const maxCols = Math.floor(data.maxHeight / data.height);
const rest = tex.length - start;
if (rest >= maxRows * maxCols) {
const size: GridNeededSize = {
width: data.maxWidth,
height: data.maxHeight,
rows: maxRows,
cols: maxCols
};
return size;
} else {
const aspect = data.height / data.width;
const cols = Math.ceil(Math.sqrt(rest * aspect));
const rows = Math.ceil(rest / cols);
const size: GridNeededSize = {
width: cols * data.width,
height: rows * data.height,
rows,
cols
};
return size;
}
}
/**
*
*
* @param maxWidth
* @param maxHeight
*/
constructor(
readonly maxWidth: number,
readonly maxHeight: number
) {}
private nextAsset(
tex: ITexture[],
start: number,
data: IGridComposerData
data: IGridComposerData,
rows: number,
cols: number
): IndexMarkedComposedData {
const size = this.getNeededSize(tex, start, data);
const { width, height, rows, cols } = size;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d')!;
canvas.width = width;
canvas.height = height;
canvas.width = this.maxWidth;
canvas.height = this.maxHeight;
const count = Math.min(rows * cols, tex.length - start);
const map = new Map<ITexture, IRect>();
@ -131,7 +93,7 @@ export class TextureGridComposer<T>
assetMap: map
};
return { data: composed, index: start + count };
return { asset: composed, index: start + count };
}
*compose(
@ -140,10 +102,13 @@ export class TextureGridComposer<T>
): Generator<ITextureComposedData> {
const arr = [...input];
const rows = Math.floor(this.maxWidth / data.width);
const cols = Math.floor(this.maxHeight / data.height);
let i = 0;
while (i < arr.length) {
const { data: asset, index } = this.nextAsset(arr, i, data);
const { asset, index } = this.nextAsset(arr, i, data, rows, cols);
i = index + 1;
yield asset;
}
@ -160,13 +125,15 @@ interface MaxRectsRectangle extends IRectangle {
readonly data: ITexture;
}
/**
* 使 Max Rects {@link IMaxRectsComposerData}
* {@link TextureMaxRectsWebGL2Composer}
*/
export class TextureMaxRectsComposer<T>
implements TranslatedComposer<IMaxRectsComposerData, T>
{
/**
* 使 Max Rects {@link IMaxRectsComposerData}
* {@link TextureMaxRectsWebGL2Composer}
* @param maxWidth
* @param maxHeight
*/
constructor(
public readonly maxWidth: number,
public readonly maxHeight: number
@ -195,8 +162,8 @@ export class TextureMaxRectsComposer<T>
const map = new Map<ITexture, IRect>();
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d')!;
canvas.width = bin.width;
canvas.height = bin.height;
canvas.width = this.maxWidth;
canvas.height = this.maxHeight;
ctx.imageSmoothingEnabled = false;
bin.rects.forEach(v => {
const rect: IRect = { x: v.x, y: v.y, w: v.width, h: v.height };
@ -226,12 +193,6 @@ interface RectProcessed {
readonly attrib: Float32Array;
}
/**
* 使 Max Rects {@link IMaxRectsComposerData}
*
* `compose`
* 使 `toBitmap`
*/
export class TextureMaxRectsWebGL2Composer<T>
implements TranslatedComposer<IMaxRectsComposerData, T>
{
@ -257,6 +218,15 @@ export class TextureMaxRectsWebGL2Composer<T>
/** 本次处理的贴图高度 */
private opHeight: number = 0;
/**
* 使 Max Rects 使 WebGL2
* {@link IMaxRectsComposerData}
* `compose`
* 使 `toBitmap`,
* `next`
* @param maxWidth
* @param maxHeight
*/
constructor(
public readonly maxWidth: number,
public readonly maxHeight: number

View File

@ -50,7 +50,7 @@ export class Texture<T = unknown, A = unknown> implements ITexture<T, A> {
async toBitmap(): Promise<void> {
if (this.source instanceof ImageBitmap) return;
this.source = await createImageBitmap(this.source as any);
this.source = await createImageBitmap(this.source);
}
split<U>(splitter: ITextureSplitter<U>, data: U): Generator<ITexture> {