2024-05-09 23:49:53 +08:00
|
|
|
|
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
|
|
|
|
import { Camera } from './camera';
|
|
|
|
|
import {
|
|
|
|
|
ICanvasCachedRenderItem,
|
2024-05-23 23:55:08 +08:00
|
|
|
|
IRenderChildable,
|
2024-05-09 23:49:53 +08:00
|
|
|
|
RenderItem,
|
|
|
|
|
RenderItemPosition,
|
|
|
|
|
withCacheRender
|
|
|
|
|
} from './item';
|
|
|
|
|
|
2024-05-23 23:55:08 +08:00
|
|
|
|
export class Container
|
|
|
|
|
extends RenderItem
|
|
|
|
|
implements ICanvasCachedRenderItem, IRenderChildable
|
|
|
|
|
{
|
2024-05-09 23:49:53 +08:00
|
|
|
|
children: RenderItem[] = [];
|
|
|
|
|
sortedChildren: RenderItem[] = [];
|
|
|
|
|
|
|
|
|
|
canvas: MotaOffscreenCanvas2D;
|
|
|
|
|
|
2024-08-17 23:11:20 +08:00
|
|
|
|
/** 是否启用缓存机制,对于特殊场景,内部已经包含了缓存机制,这时就不需要启用了 */
|
|
|
|
|
private readonly enableCache: boolean;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建一个容器,容器中可以包含其他渲染对象
|
|
|
|
|
* @param type 渲染模式,absolute表示绝对位置,static表示跟随摄像机移动,只对顶层元素有效
|
|
|
|
|
* @param cache 是否启用缓存机制
|
|
|
|
|
*/
|
|
|
|
|
constructor(type: RenderItemPosition = 'static', cache: boolean = true) {
|
2024-05-09 23:49:53 +08:00
|
|
|
|
super();
|
|
|
|
|
this.canvas = new MotaOffscreenCanvas2D();
|
|
|
|
|
this.type = type;
|
|
|
|
|
this.canvas.withGameScale(true);
|
2024-08-17 23:11:20 +08:00
|
|
|
|
this.enableCache = cache;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private renderTo(canvas: MotaOffscreenCanvas2D, camera: Camera) {
|
|
|
|
|
const { ctx } = canvas;
|
|
|
|
|
this.sortedChildren.forEach(v => {
|
|
|
|
|
if (v.hidden) return;
|
|
|
|
|
ctx.save();
|
|
|
|
|
if (!v.antiAliasing) {
|
|
|
|
|
ctx.imageSmoothingEnabled = false;
|
|
|
|
|
} else {
|
|
|
|
|
ctx.imageSmoothingEnabled = true;
|
|
|
|
|
}
|
|
|
|
|
v.render(canvas, camera);
|
|
|
|
|
ctx.restore();
|
|
|
|
|
});
|
2024-05-09 23:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-17 23:11:20 +08:00
|
|
|
|
render(canvas: MotaOffscreenCanvas2D, camera: Camera): void {
|
2024-05-16 22:43:24 +08:00
|
|
|
|
this.emit('beforeRender');
|
2024-05-18 17:05:01 +08:00
|
|
|
|
if (this.needUpdate) {
|
2024-05-23 23:55:08 +08:00
|
|
|
|
this.cache(this.using);
|
2024-05-18 17:05:01 +08:00
|
|
|
|
this.needUpdate = false;
|
|
|
|
|
}
|
2024-08-17 23:11:20 +08:00
|
|
|
|
if (this.enableCache) {
|
|
|
|
|
withCacheRender(this, canvas.canvas, canvas.ctx, camera, c => {
|
|
|
|
|
this.renderTo(c, camera);
|
2024-05-09 23:49:53 +08:00
|
|
|
|
});
|
2024-08-17 23:11:20 +08:00
|
|
|
|
} else {
|
|
|
|
|
this.renderTo(canvas, camera);
|
|
|
|
|
}
|
2024-05-10 17:33:27 +08:00
|
|
|
|
this.writing = void 0;
|
2024-05-16 22:43:24 +08:00
|
|
|
|
this.emit('afterRender');
|
2024-05-09 23:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size(width: number, height: number) {
|
|
|
|
|
this.width = width;
|
|
|
|
|
this.height = height;
|
|
|
|
|
this.canvas.size(width, height);
|
|
|
|
|
this.writing = this.using;
|
|
|
|
|
this.update(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos(x: number, y: number) {
|
|
|
|
|
this.x = x;
|
|
|
|
|
this.y = y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 添加子元素到这个容器上,然后在下一个tick执行更新
|
|
|
|
|
* @param children 要添加的子元素
|
|
|
|
|
*/
|
2024-05-23 23:55:08 +08:00
|
|
|
|
appendChild(...children: RenderItem[]) {
|
2024-05-09 23:49:53 +08:00
|
|
|
|
children.forEach(v => (v.parent = this));
|
|
|
|
|
this.children.push(...children);
|
2024-05-16 22:43:24 +08:00
|
|
|
|
this.sortChildren();
|
2024-05-23 23:55:08 +08:00
|
|
|
|
this.update(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
removeChild(...child: RenderItem[]): void {
|
|
|
|
|
child.forEach(v => {
|
|
|
|
|
const index = this.children.indexOf(v);
|
|
|
|
|
if (index === -1) return;
|
|
|
|
|
this.children.splice(index, 1);
|
|
|
|
|
});
|
|
|
|
|
this.sortChildren();
|
|
|
|
|
this.update(this);
|
2024-05-16 22:43:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sortChildren() {
|
2024-05-09 23:49:53 +08:00
|
|
|
|
this.sortedChildren = this.children
|
|
|
|
|
.slice()
|
|
|
|
|
.sort((a, b) => a.zIndex - b.zIndex);
|
|
|
|
|
}
|
2024-05-16 22:43:24 +08:00
|
|
|
|
|
|
|
|
|
setHD(hd: boolean): void {
|
|
|
|
|
this.highResolution = hd;
|
|
|
|
|
this.canvas.setHD(hd);
|
|
|
|
|
this.update(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setAntiAliasing(anti: boolean): void {
|
|
|
|
|
this.antiAliasing = anti;
|
|
|
|
|
this.canvas.setAntiAliasing(anti);
|
|
|
|
|
this.update(this);
|
|
|
|
|
}
|
2024-05-23 23:55:08 +08:00
|
|
|
|
|
|
|
|
|
destroy(): void {
|
|
|
|
|
super.destroy();
|
|
|
|
|
this.children.forEach(v => {
|
|
|
|
|
v.destroy();
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-05-09 23:49:53 +08:00
|
|
|
|
}
|