From b2a391a21240f3d8491d130d2bb3c3a0dbea92cd Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sun, 12 Jan 2025 13:09:10 +0800 Subject: [PATCH] fix: icon --- src/core/render/cache.ts | 3 +++ src/core/render/index.tsx | 1 + src/core/render/preset/misc.ts | 45 ++++++++++++++++++++++++------- src/core/render/renderer/props.ts | 4 +-- src/data/logger.json | 1 + src/game/game.ts | 6 ++++- 6 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/core/render/cache.ts b/src/core/render/cache.ts index c1f9940..cb2165d 100644 --- a/src/core/render/cache.ts +++ b/src/core/render/cache.ts @@ -211,6 +211,7 @@ class TextureCache extends EventEmitter { // enemy48和npc48都应该视为大怪物 if (cls === 'enemy48' || cls === 'npc48') { const img = core.material.images[cls]; + if (!img) return null; // @ts-ignore const line = icons[cls][id]; const w = 32; @@ -234,6 +235,7 @@ class TextureCache extends EventEmitter { } // 自动元件 if (cls === 'autotile') { + if (!this.autotile) return null; const auto = this.autotile[num as AllNumbersOf<'autotile'>]; const cell = 32; const render: [number, number, number, number][] = []; @@ -264,6 +266,7 @@ class TextureCache extends EventEmitter { core.material.images[ cls as Exclude ]; + if (!image) return null; const frame = core.getAnimateFrames(cls); const cell = 32; // @ts-ignore diff --git a/src/core/render/index.tsx b/src/core/render/index.tsx index 5bbbb9f..c08f463 100644 --- a/src/core/render/index.tsx +++ b/src/core/render/index.tsx @@ -69,6 +69,7 @@ Mota.require('var', 'loading').once('coreInit', () => { + ); }); diff --git a/src/core/render/preset/misc.ts b/src/core/render/preset/misc.ts index 37d8126..7a94540 100644 --- a/src/core/render/preset/misc.ts +++ b/src/core/render/preset/misc.ts @@ -10,6 +10,8 @@ import { Transform } from '../transform'; import { ElementNamespace, ComponentInternalInstance } from 'vue'; import { AutotileRenderable, RenderableData } from '../cache'; import { texture } from '../cache'; +import { isNil } from 'lodash-es'; +import { logger } from '@/core/common/logger'; type CanvasStyle = string | CanvasGradient | CanvasPattern; @@ -223,6 +225,14 @@ export class Icon extends RenderItem implements IAnimateFrame { /** 图标的渲染信息 */ private renderable?: RenderableData | AutotileRenderable; + private pendingIcon?: AllNumbers; + + constructor(type: RenderItemPosition, cache?: boolean, fall?: boolean) { + super(type, cache, fall); + this.setAntiAliasing(false); + this.setHD(false); + } + protected render( canvas: MotaOffscreenCanvas2D, _transform: Transform @@ -236,6 +246,7 @@ export class Icon extends RenderItem implements IAnimateFrame { const frame = this.animate ? RenderItem.animatedFrame % renderable.frame : 0; + if (!this.animate) { if (renderable.autotile) { ctx.drawImage(renderable.image[0], x, y, w, h, 0, 0, cw, ch); @@ -250,8 +261,6 @@ export class Icon extends RenderItem implements IAnimateFrame { } else { ctx.drawImage(renderable.image, x1, y1, w1, h1, 0, 0, cw, ch); } - this.update(this); - renderEmits.addFramer(this); } } @@ -261,24 +270,35 @@ export class Icon extends RenderItem implements IAnimateFrame { */ setIcon(id: AllIds | AllNumbers) { const num = typeof id === 'number' ? id : texture.idNumberMap[id]; + + const loading = Mota.require('var', 'loading'); + if (loading.loaded) { + this.setIconRenderable(num); + } else { + if (isNil(this.pendingIcon)) { + loading.once('loaded', () => { + this.setIconRenderable(this.pendingIcon ?? 0); + this.pendingIcon = void 0; + }); + } + this.pendingIcon = num; + } + } + + private setIconRenderable(num: AllNumbers) { const renderable = texture.getRenderable(num); if (!renderable) { - //todo: logger.warn() + logger.warn(42, num.toString()); return; } else { this.icon = num; - + this.renderable = renderable; this.frame = renderable.frame; } this.update(); } - destroy(): void { - renderEmits.removeFramer(this); - super.destroy(); - } - /** * 更新动画帧 */ @@ -286,6 +306,11 @@ export class Icon extends RenderItem implements IAnimateFrame { this.update(this); } + destroy(): void { + renderEmits.removeFramer(this); + super.destroy(); + } + patchProp( key: string, prevValue: any, @@ -300,6 +325,8 @@ export class Icon extends RenderItem implements IAnimateFrame { case 'animate': if (!this.assertType(nextValue, 'boolean', key)) return; this.animate = nextValue; + if (nextValue) renderEmits.addFramer(this); + else renderEmits.removeFramer(this); this.update(); return; case 'frame': diff --git a/src/core/render/renderer/props.ts b/src/core/render/renderer/props.ts index 10bf408..e57777c 100644 --- a/src/core/render/renderer/props.ts +++ b/src/core/render/renderer/props.ts @@ -178,8 +178,8 @@ export interface RectRProps extends GraphicPropsBase { export interface IconProps extends BaseProps { icon: AllNumbers; - frame: number; - animate: boolean; + frame?: number; + animate?: boolean; } export interface WinskinProps extends BaseProps { diff --git a/src/data/logger.json b/src/data/logger.json index ae0a740..4561353 100644 --- a/src/data/logger.json +++ b/src/data/logger.json @@ -70,6 +70,7 @@ "40": "Cannot return canvas that is not provided by this pool.", "41": "Width of text content components must be positive. receive: $1", "42": "Repeated Textbox id: '$1'.", + "43": "Cannot set icon of '$1', since it does not exists. Please ensure you have delivered correct icon id or number.", "1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency.", "1101": "Cannot add new effect to point effect instance, for there's no more reserve space for it. Please increase the max count of the instance." } diff --git a/src/game/game.ts b/src/game/game.ts index 1973e9d..e4ee54d 100644 --- a/src/game/game.ts +++ b/src/game/game.ts @@ -13,12 +13,16 @@ class GameLoading extends EventEmitter { private autotileLoaded: number = 0; private autotileNum?: number; private autotileListened: boolean = false; + loaded: boolean = false; constructor() { super(); - this.on('coreInit', () => { + this.once('coreInit', () => { this.autotileNum = Object.keys(core.material.icons.autotile).length; }); + this.once('loaded', () => { + this.loaded = true; + }); } addAutotileLoaded() {