@rpgjs/client 5.0.0-beta.1 → 5.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/LICENSE +19 -0
- package/dist/Game/AnimationManager.d.ts +1 -1
- package/dist/Game/AnimationManager.js +18 -9
- package/dist/Game/AnimationManager.js.map +1 -1
- package/dist/Game/AnimationManager.spec.d.ts +1 -0
- package/dist/Game/Event.js.map +1 -1
- package/dist/Game/Map.d.ts +9 -1
- package/dist/Game/Map.js +63 -5
- package/dist/Game/Map.js.map +1 -1
- package/dist/Game/Object.d.ts +47 -15
- package/dist/Game/Object.js +82 -38
- package/dist/Game/Object.js.map +1 -1
- package/dist/Game/Player.js.map +1 -1
- package/dist/Game/ProjectileManager.d.ts +89 -0
- package/dist/Game/ProjectileManager.js +179 -0
- package/dist/Game/ProjectileManager.js.map +1 -0
- package/dist/Game/ProjectileManager.spec.d.ts +1 -0
- package/dist/Gui/Gui.d.ts +17 -4
- package/dist/Gui/Gui.js +78 -48
- package/dist/Gui/Gui.js.map +1 -1
- package/dist/Gui/Gui.spec.d.ts +1 -0
- package/dist/Gui/NotificationManager.js.map +1 -1
- package/dist/Resource.js +1 -1
- package/dist/Resource.js.map +1 -1
- package/dist/RpgClient.d.ts +110 -15
- package/dist/RpgClientEngine.d.ts +86 -10
- package/dist/RpgClientEngine.js +306 -49
- package/dist/RpgClientEngine.js.map +1 -1
- package/dist/Sound.js.map +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.130.0}/helpers/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.130.0}/helpers/decorateMetadata.js +1 -1
- package/dist/components/animations/animation.ce.js +4 -5
- package/dist/components/animations/animation.ce.js.map +1 -1
- package/dist/components/animations/hit.ce.js +19 -25
- package/dist/components/animations/hit.ce.js.map +1 -1
- package/dist/components/animations/index.js +4 -4
- package/dist/components/animations/index.js.map +1 -1
- package/dist/components/character.ce.js +422 -240
- package/dist/components/character.ce.js.map +1 -1
- package/dist/components/dynamics/bar.ce.js +97 -0
- package/dist/components/dynamics/bar.ce.js.map +1 -0
- package/dist/components/dynamics/image.ce.js +24 -0
- package/dist/components/dynamics/image.ce.js.map +1 -0
- package/dist/components/dynamics/parse-value.d.ts +3 -0
- package/dist/components/dynamics/parse-value.js +54 -35
- package/dist/components/dynamics/parse-value.js.map +1 -1
- package/dist/components/dynamics/parse-value.spec.d.ts +1 -0
- package/dist/components/dynamics/shape-utils.d.ts +16 -0
- package/dist/components/dynamics/shape-utils.js +73 -0
- package/dist/components/dynamics/shape-utils.js.map +1 -0
- package/dist/components/dynamics/shape-utils.spec.d.ts +1 -0
- package/dist/components/dynamics/shape.ce.js +84 -0
- package/dist/components/dynamics/shape.ce.js.map +1 -0
- package/dist/components/dynamics/text.ce.js +34 -56
- package/dist/components/dynamics/text.ce.js.map +1 -1
- package/dist/components/gui/box.ce.js +6 -8
- package/dist/components/gui/box.ce.js.map +1 -1
- package/dist/components/gui/dialogbox/index.ce.js +56 -62
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
- package/dist/components/gui/gameover.ce.js +42 -65
- package/dist/components/gui/gameover.ce.js.map +1 -1
- package/dist/components/gui/hud/hud.ce.js +21 -30
- package/dist/components/gui/hud/hud.ce.js.map +1 -1
- package/dist/components/gui/menu/equip-menu.ce.js +112 -165
- package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/exit-menu.ce.js +8 -6
- package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/items-menu.ce.js +52 -69
- package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/main-menu.ce.js +75 -92
- package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/options-menu.ce.js +5 -4
- package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/skills-menu.ce.js +12 -17
- package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
- package/dist/components/gui/mobile/index.js +2 -2
- package/dist/components/gui/mobile/index.js.map +1 -1
- package/dist/components/gui/mobile/mobile.ce.js +5 -4
- package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
- package/dist/components/gui/notification/notification.ce.js +22 -24
- package/dist/components/gui/notification/notification.ce.js.map +1 -1
- package/dist/components/gui/save-load.ce.js +72 -249
- package/dist/components/gui/save-load.ce.js.map +1 -1
- package/dist/components/gui/shop/shop.ce.js +90 -127
- package/dist/components/gui/shop/shop.ce.js.map +1 -1
- package/dist/components/gui/title-screen.ce.js +45 -70
- package/dist/components/gui/title-screen.ce.js.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.js +1 -0
- package/dist/components/player-components-utils.d.ts +67 -0
- package/dist/components/player-components-utils.js +162 -0
- package/dist/components/player-components-utils.js.map +1 -0
- package/dist/components/player-components-utils.spec.d.ts +1 -0
- package/dist/components/player-components.ce.js +189 -0
- package/dist/components/player-components.ce.js.map +1 -0
- package/dist/components/prebuilt/hp-bar.ce.js +42 -44
- package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
- package/dist/components/prebuilt/light-halo.ce.js +36 -59
- package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
- package/dist/components/scenes/canvas.ce.js +165 -21
- package/dist/components/scenes/canvas.ce.js.map +1 -1
- package/dist/components/scenes/draw-map.ce.js +25 -32
- package/dist/components/scenes/draw-map.ce.js.map +1 -1
- package/dist/components/scenes/event-layer.ce.js +9 -8
- package/dist/components/scenes/event-layer.ce.js.map +1 -1
- package/dist/core/inject.js +1 -1
- package/dist/core/inject.js.map +1 -1
- package/dist/core/setup.js +1 -1
- package/dist/core/setup.js.map +1 -1
- package/dist/decorators/spritesheet.d.ts +1 -0
- package/dist/decorators/spritesheet.js +11 -0
- package/dist/decorators/spritesheet.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +26 -21
- package/dist/module.js +15 -1
- package/dist/module.js.map +1 -1
- package/dist/node_modules/.pnpm/{@signe_di@2.9.0 → @signe_di@3.0.1}/node_modules/@signe/di/dist/index.js +7 -117
- package/dist/node_modules/.pnpm/@signe_di@3.0.1/node_modules/@signe/di/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_reactive@3.0.1/node_modules/@signe/reactive/dist/index.js +239 -0
- package/dist/node_modules/.pnpm/@signe_reactive@3.0.1/node_modules/@signe/reactive/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/chunk-EUXUH3YW.js +13 -0
- package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/chunk-EUXUH3YW.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/index.js +696 -0
- package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/client/index.js +44 -0
- package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/client/index.js.map +1 -0
- package/dist/node_modules/.pnpm/{@signe_sync@2.9.0 → @signe_sync@3.0.1}/node_modules/@signe/sync/dist/index.js +57 -141
- package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -1
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -1
- package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js +27 -27
- package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -1
- package/dist/presets/animation.js.map +1 -1
- package/dist/presets/faceset.js.map +1 -1
- package/dist/presets/icon.js.map +1 -1
- package/dist/presets/index.js.map +1 -1
- package/dist/presets/lpc.js.map +1 -1
- package/dist/presets/rmspritesheet.js.map +1 -1
- package/dist/services/AbstractSocket.js.map +1 -1
- package/dist/services/actionInput.d.ts +12 -0
- package/dist/services/actionInput.js +27 -0
- package/dist/services/actionInput.js.map +1 -0
- package/dist/services/actionInput.spec.d.ts +1 -0
- package/dist/services/keyboardControls.js.map +1 -1
- package/dist/services/loadMap.d.ts +6 -0
- package/dist/services/loadMap.js +1 -1
- package/dist/services/loadMap.js.map +1 -1
- package/dist/services/mmorpg-connection.d.ts +5 -0
- package/dist/services/mmorpg-connection.js +50 -0
- package/dist/services/mmorpg-connection.js.map +1 -0
- package/dist/services/mmorpg-connection.spec.d.ts +1 -0
- package/dist/services/mmorpg.d.ts +10 -4
- package/dist/services/mmorpg.js +56 -33
- package/dist/services/mmorpg.js.map +1 -1
- package/dist/services/pointerContext.d.ts +11 -0
- package/dist/services/pointerContext.js +48 -0
- package/dist/services/pointerContext.js.map +1 -0
- package/dist/services/pointerContext.spec.d.ts +1 -0
- package/dist/services/save.js.map +1 -1
- package/dist/services/save.spec.d.ts +1 -0
- package/dist/services/standalone-message.d.ts +1 -0
- package/dist/services/standalone-message.js +9 -0
- package/dist/services/standalone-message.js.map +1 -0
- package/dist/services/standalone.js +4 -3
- package/dist/services/standalone.js.map +1 -1
- package/dist/services/standalone.spec.d.ts +1 -0
- package/dist/utils/getEntityProp.js +4 -3
- package/dist/utils/getEntityProp.js.map +1 -1
- package/dist/utils/getEntityProp.spec.d.ts +1 -0
- package/dist/utils/readPropValue.d.ts +2 -0
- package/dist/utils/readPropValue.js +13 -0
- package/dist/utils/readPropValue.js.map +1 -0
- package/package.json +13 -14
- package/src/Game/AnimationManager.spec.ts +30 -0
- package/src/Game/AnimationManager.ts +22 -10
- package/src/Game/Map.ts +91 -2
- package/src/Game/Object.ts +148 -69
- package/src/Game/ProjectileManager.spec.ts +338 -0
- package/src/Game/ProjectileManager.ts +324 -0
- package/src/Gui/Gui.spec.ts +273 -0
- package/src/Gui/Gui.ts +105 -50
- package/src/Resource.ts +1 -2
- package/src/RpgClient.ts +125 -17
- package/src/RpgClientEngine.ts +457 -87
- package/src/components/character.ce +441 -32
- package/src/components/dynamics/bar.ce +88 -0
- package/src/components/dynamics/image.ce +21 -0
- package/src/components/dynamics/parse-value.spec.ts +83 -0
- package/src/components/dynamics/parse-value.ts +111 -37
- package/src/components/dynamics/shape-utils.spec.ts +46 -0
- package/src/components/dynamics/shape-utils.ts +61 -0
- package/src/components/dynamics/shape.ce +90 -0
- package/src/components/dynamics/text.ce +35 -149
- package/src/components/gui/dialogbox/index.ce +18 -8
- package/src/components/gui/gameover.ce +2 -1
- package/src/components/gui/menu/equip-menu.ce +2 -1
- package/src/components/gui/menu/exit-menu.ce +2 -1
- package/src/components/gui/menu/items-menu.ce +3 -2
- package/src/components/gui/menu/main-menu.ce +2 -1
- package/src/components/gui/save-load.ce +2 -1
- package/src/components/gui/shop/shop.ce +3 -2
- package/src/components/gui/title-screen.ce +2 -1
- package/src/components/index.ts +2 -1
- package/src/components/player-components-utils.spec.ts +109 -0
- package/src/components/player-components-utils.ts +205 -0
- package/src/components/player-components.ce +222 -0
- package/src/components/prebuilt/hp-bar.ce +4 -3
- package/src/components/prebuilt/light-halo.ce +2 -2
- package/src/components/scenes/canvas.ce +175 -8
- package/src/components/scenes/draw-map.ce +18 -17
- package/src/components/scenes/event-layer.ce +1 -2
- package/src/core/setup.ts +2 -2
- package/src/decorators/spritesheet.ts +8 -0
- package/src/index.ts +4 -0
- package/src/module.ts +18 -1
- package/src/services/actionInput.spec.ts +101 -0
- package/src/services/actionInput.ts +53 -0
- package/src/services/loadMap.ts +2 -0
- package/src/services/mmorpg-connection.spec.ts +99 -0
- package/src/services/mmorpg-connection.ts +69 -0
- package/src/services/mmorpg.ts +68 -36
- package/src/services/pointerContext.spec.ts +36 -0
- package/src/services/pointerContext.ts +84 -0
- package/src/services/save.spec.ts +127 -0
- package/src/services/standalone-message.ts +7 -0
- package/src/services/standalone.spec.ts +34 -0
- package/src/services/standalone.ts +3 -2
- package/src/utils/getEntityProp.spec.ts +96 -0
- package/src/utils/getEntityProp.ts +4 -3
- package/src/utils/readPropValue.ts +16 -0
- package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js +0 -457
- package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +0 -463
- package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +0 -2191
- package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +0 -10
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +0 -91
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +0 -14
- package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<Sprite sheet={sheet} />
|
|
2
|
+
|
|
3
|
+
<script>
|
|
4
|
+
import { computed } from "canvasengine";
|
|
5
|
+
import { RpgClientEngine } from "../../RpgClientEngine";
|
|
6
|
+
import { inject } from "../../core/inject";
|
|
7
|
+
import { resolveDynamicValue } from "./parse-value";
|
|
8
|
+
|
|
9
|
+
const { object, value } = defineProps();
|
|
10
|
+
const sprite = object();
|
|
11
|
+
const client = inject(RpgClientEngine);
|
|
12
|
+
|
|
13
|
+
const sheet = computed(() => {
|
|
14
|
+
const id = resolveDynamicValue(value?.(), sprite);
|
|
15
|
+
if (!id) return null;
|
|
16
|
+
return {
|
|
17
|
+
definition: client.getSpriteSheet(id),
|
|
18
|
+
playing: 'default'
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
</script>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { signal } from "canvasengine";
|
|
3
|
+
import { resolveDynamicProps, resolveDynamicValue } from "./parse-value";
|
|
4
|
+
|
|
5
|
+
describe("dynamic component values", () => {
|
|
6
|
+
test("resolves player properties and keeps bar placeholders for the bar renderer", () => {
|
|
7
|
+
const object = {
|
|
8
|
+
_name: signal("Alex"),
|
|
9
|
+
_speed: signal(4),
|
|
10
|
+
_canMove: signal(true),
|
|
11
|
+
hpSignal: signal(100),
|
|
12
|
+
_param: signal({ maxHp: 120 }),
|
|
13
|
+
get name() {
|
|
14
|
+
return this._name();
|
|
15
|
+
},
|
|
16
|
+
set name(value: string) {
|
|
17
|
+
this._name.set(value);
|
|
18
|
+
},
|
|
19
|
+
get speed() {
|
|
20
|
+
return this._speed();
|
|
21
|
+
},
|
|
22
|
+
set speed(value: number) {
|
|
23
|
+
this._speed.set(value);
|
|
24
|
+
},
|
|
25
|
+
get canMove() {
|
|
26
|
+
return this._canMove();
|
|
27
|
+
},
|
|
28
|
+
set canMove(value: boolean) {
|
|
29
|
+
this._canMove.set(value);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
expect(resolveDynamicValue("HP: {hp}/{param.maxHp} {name} {speed} {canMove} {$current}", object)).toBe("HP: 100/120 Alex 4 true {$current}");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("keeps resolved props reactive", () => {
|
|
37
|
+
const object = {
|
|
38
|
+
_name: signal("Alex"),
|
|
39
|
+
_speed: signal(4),
|
|
40
|
+
_canMove: signal(true),
|
|
41
|
+
hpSignal: signal(100),
|
|
42
|
+
_param: signal({ maxHp: 120 }),
|
|
43
|
+
get name() {
|
|
44
|
+
return this._name();
|
|
45
|
+
},
|
|
46
|
+
set name(value: string) {
|
|
47
|
+
this._name.set(value);
|
|
48
|
+
},
|
|
49
|
+
get speed() {
|
|
50
|
+
return this._speed();
|
|
51
|
+
},
|
|
52
|
+
set speed(value: number) {
|
|
53
|
+
this._speed.set(value);
|
|
54
|
+
},
|
|
55
|
+
get canMove() {
|
|
56
|
+
return this._canMove();
|
|
57
|
+
},
|
|
58
|
+
set canMove(value: boolean) {
|
|
59
|
+
this._canMove.set(value);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const props: any = resolveDynamicProps({
|
|
63
|
+
value: "HP: {hp} {name} {speed} {canMove}",
|
|
64
|
+
text: "{$current}/{$max} {name}",
|
|
65
|
+
style: {
|
|
66
|
+
width: "{hp}"
|
|
67
|
+
}
|
|
68
|
+
}, object);
|
|
69
|
+
|
|
70
|
+
expect(props.value()).toBe("HP: 100 Alex 4 true");
|
|
71
|
+
expect(props.text()).toBe("{$current}/{$max} Alex");
|
|
72
|
+
expect(props.style()).toEqual({ width: "100" });
|
|
73
|
+
|
|
74
|
+
object.hpSignal.set(10);
|
|
75
|
+
object.name = "Sam";
|
|
76
|
+
object.speed = 6;
|
|
77
|
+
object.canMove = false;
|
|
78
|
+
|
|
79
|
+
expect(props.value()).toBe("HP: 10 Sam 6 false");
|
|
80
|
+
expect(props.text()).toBe("{$current}/{$max} Sam");
|
|
81
|
+
expect(props.style()).toEqual({ width: "10" });
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -6,17 +6,123 @@ interface MatchResult {
|
|
|
6
6
|
index: number;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
const readSignal = (value: any) => typeof value === 'function' ? value() : value;
|
|
10
|
+
const DYNAMIC_VALUE_PATTERN = /\{([^}]+)\}/g;
|
|
11
|
+
|
|
12
|
+
const hasDynamicValue = (value: any) => {
|
|
13
|
+
value = readSignal(value);
|
|
14
|
+
if (typeof value !== 'string') return false;
|
|
15
|
+
DYNAMIC_VALUE_PATTERN.lastIndex = 0;
|
|
16
|
+
return DYNAMIC_VALUE_PATTERN.test(value);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const resolveDynamicSnapshot = (value: any, object?: any): any => {
|
|
20
|
+
value = readSignal(value);
|
|
21
|
+
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
return value.map((entry) => resolveDynamicSnapshot(entry, object));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (value && typeof value === 'object') {
|
|
27
|
+
return Object.fromEntries(
|
|
28
|
+
Object.entries(value).map(([key, entry]) => [key, resolveDynamicSnapshot(entry, object)])
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return resolveDynamicValue(value, object);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const getDynamicValue = (property: string, object?: any) => {
|
|
36
|
+
try {
|
|
37
|
+
const propertyPath = property.split('.');
|
|
38
|
+
let currentValue = object;
|
|
39
|
+
|
|
40
|
+
for (let j = 0; j < propertyPath.length; j++) {
|
|
41
|
+
let prop = propertyPath[j];
|
|
42
|
+
|
|
43
|
+
currentValue = readSignal(currentValue);
|
|
44
|
+
|
|
45
|
+
if (j === 0) {
|
|
46
|
+
if (prop === 'hp') prop = 'hpSignal';
|
|
47
|
+
if (prop === 'sp') prop = 'spSignal';
|
|
48
|
+
if (prop === 'param') prop = '_param';
|
|
49
|
+
if (prop === 'name' && currentValue && typeof currentValue === 'object' && '_name' in currentValue) {
|
|
50
|
+
prop = '_name';
|
|
51
|
+
}
|
|
52
|
+
if (prop === 'speed' && currentValue && typeof currentValue === 'object' && '_speed' in currentValue) {
|
|
53
|
+
prop = '_speed';
|
|
54
|
+
}
|
|
55
|
+
if (prop === 'canMove' && currentValue && typeof currentValue === 'object' && '_canMove' in currentValue) {
|
|
56
|
+
prop = '_canMove';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (currentValue && typeof currentValue === 'object' && prop in currentValue) {
|
|
61
|
+
currentValue = currentValue[prop];
|
|
62
|
+
} else {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return readSignal(currentValue);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const resolveDynamicValue = (value: any, object?: any): any => {
|
|
74
|
+
value = readSignal(value);
|
|
75
|
+
|
|
76
|
+
if (typeof value !== 'string') {
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return value.replace(DYNAMIC_VALUE_PATTERN, (fullMatch, property) => {
|
|
81
|
+
const propertyValue = getDynamicValue(property, object);
|
|
82
|
+
if (propertyValue == null && property.startsWith('$')) return fullMatch;
|
|
83
|
+
return propertyValue != null ? String(propertyValue) : '';
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const resolveDynamicProp = (value: any, object?: any): any => {
|
|
88
|
+
if (Array.isArray(value) || (value && typeof value === 'object' && typeof value !== 'function')) {
|
|
89
|
+
return computed(() => resolveDynamicSnapshot(value, object));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (typeof value === 'function' || hasDynamicValue(value)) {
|
|
93
|
+
return computed(() => resolveDynamicValue(value, object));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return value;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const resolveDynamicProps = (props: any, object?: any): any => {
|
|
100
|
+
props = readSignal(props);
|
|
101
|
+
|
|
102
|
+
if (Array.isArray(props)) {
|
|
103
|
+
return computed(() => resolveDynamicSnapshot(props, object));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (props && typeof props === 'object') {
|
|
107
|
+
return Object.fromEntries(
|
|
108
|
+
Object.entries(props).map(([key, value]) => [key, resolveDynamicProp(value, object)])
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return resolveDynamicProp(props, object);
|
|
113
|
+
};
|
|
114
|
+
|
|
9
115
|
export const parseDynamicValue = (value: any, object?: any) => {
|
|
10
116
|
if (typeof value !== 'string') {
|
|
11
117
|
return computed(() => String(value ?? ''));
|
|
12
118
|
}
|
|
13
119
|
|
|
14
120
|
// Find all dynamic references like {propertyName}
|
|
15
|
-
const pattern = /\{([^}]+)\}/g;
|
|
16
121
|
const matches: MatchResult[] = [];
|
|
17
122
|
let match;
|
|
18
|
-
|
|
19
|
-
|
|
123
|
+
|
|
124
|
+
DYNAMIC_VALUE_PATTERN.lastIndex = 0;
|
|
125
|
+
while ((match = DYNAMIC_VALUE_PATTERN.exec(value)) !== null) {
|
|
20
126
|
matches.push({
|
|
21
127
|
property: match[1],
|
|
22
128
|
fullMatch: match[0],
|
|
@@ -37,40 +143,8 @@ export const parseDynamicValue = (value: any, object?: any) => {
|
|
|
37
143
|
for (let i = matches.length - 1; i >= 0; i--) {
|
|
38
144
|
const { property, fullMatch } = matches[i];
|
|
39
145
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
let propertyValue = '';
|
|
43
|
-
try {
|
|
44
|
-
const propertyPath = property.split('.');
|
|
45
|
-
let currentValue = object;
|
|
46
|
-
|
|
47
|
-
for (let j = 0; j < propertyPath.length; j++) {
|
|
48
|
-
const prop = propertyPath[j];
|
|
49
|
-
|
|
50
|
-
// Check if currentValue is a signal (function) and call it
|
|
51
|
-
if (typeof currentValue === 'function') {
|
|
52
|
-
currentValue = currentValue();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Access the property
|
|
56
|
-
if (currentValue && typeof currentValue === 'object' && prop in currentValue) {
|
|
57
|
-
currentValue = currentValue[prop];
|
|
58
|
-
} else {
|
|
59
|
-
currentValue = undefined;
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// If the final value is a signal, call it
|
|
65
|
-
if (typeof currentValue === 'function') {
|
|
66
|
-
currentValue = currentValue();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
propertyValue = currentValue != null ? String(currentValue) : '';
|
|
70
|
-
} catch (error) {
|
|
71
|
-
// If property doesn't exist or can't be accessed, use empty string
|
|
72
|
-
propertyValue = '';
|
|
73
|
-
}
|
|
146
|
+
const currentValue = getDynamicValue(property, object);
|
|
147
|
+
const propertyValue = currentValue != null ? String(currentValue) : property.startsWith('$') ? fullMatch : '';
|
|
74
148
|
|
|
75
149
|
result = result.replace(fullMatch, propertyValue);
|
|
76
150
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { getShapeBox, getShapePointBounds, translatePolygonPoints } from "./shape-utils";
|
|
3
|
+
|
|
4
|
+
describe("shape utilities", () => {
|
|
5
|
+
test("normalizes rectangles and circles around their rendered bounds", () => {
|
|
6
|
+
expect(getShapeBox({ type: "rect", width: 32, height: 32 })).toEqual({
|
|
7
|
+
width: 32,
|
|
8
|
+
height: 32,
|
|
9
|
+
offsetX: 0,
|
|
10
|
+
offsetY: 0
|
|
11
|
+
});
|
|
12
|
+
expect(getShapeBox({ type: "circle", radius: 8 })).toEqual({
|
|
13
|
+
width: 16,
|
|
14
|
+
height: 16,
|
|
15
|
+
offsetX: 0,
|
|
16
|
+
offsetY: 0
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("normalizes line bounds with negative coordinates", () => {
|
|
21
|
+
expect(getShapeBox({ type: "line", x1: -4, y1: 6, x2: 12, y2: -2 })).toEqual({
|
|
22
|
+
width: 16,
|
|
23
|
+
height: 8,
|
|
24
|
+
offsetX: 4,
|
|
25
|
+
offsetY: 2
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("normalizes polygon bounds and translated points", () => {
|
|
30
|
+
const box = getShapeBox({ type: "polygon", points: [-5, 2, 15, 2, 5, 12] });
|
|
31
|
+
|
|
32
|
+
expect(getShapePointBounds([-5, 2, 15, 2, 5, 12])).toEqual({
|
|
33
|
+
minX: -5,
|
|
34
|
+
minY: 2,
|
|
35
|
+
maxX: 15,
|
|
36
|
+
maxY: 12
|
|
37
|
+
});
|
|
38
|
+
expect(box).toEqual({
|
|
39
|
+
width: 20,
|
|
40
|
+
height: 10,
|
|
41
|
+
offsetX: 5,
|
|
42
|
+
offsetY: -2
|
|
43
|
+
});
|
|
44
|
+
expect(translatePolygonPoints([-5, 2, 15, 2, 5, 12], box)).toEqual([0, 0, 20, 0, 10, 10]);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const defaultToNumber = (value: any, fallback = 0) => {
|
|
2
|
+
const num = typeof value === 'number' ? value : parseFloat(value);
|
|
3
|
+
return Number.isFinite(num) ? num : fallback;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export function getShapePointBounds(points: any[] = [], toNumber = defaultToNumber) {
|
|
7
|
+
if (!Array.isArray(points) || points.length < 2) {
|
|
8
|
+
return { minX: 0, minY: 0, maxX: 1, maxY: 1 };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let minX = Infinity;
|
|
12
|
+
let minY = Infinity;
|
|
13
|
+
let maxX = -Infinity;
|
|
14
|
+
let maxY = -Infinity;
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < points.length; i += 2) {
|
|
17
|
+
const x = toNumber(points[i], 0);
|
|
18
|
+
const y = toNumber(points[i + 1], 0);
|
|
19
|
+
minX = Math.min(minX, x);
|
|
20
|
+
minY = Math.min(minY, y);
|
|
21
|
+
maxX = Math.max(maxX, x);
|
|
22
|
+
maxY = Math.max(maxY, y);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { minX, minY, maxX, maxY };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getShapeBox(cfg: any, toNumber = defaultToNumber) {
|
|
29
|
+
if (cfg.type === 'circle') {
|
|
30
|
+
return { width: cfg.radius * 2, height: cfg.radius * 2, offsetX: 0, offsetY: 0 };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (cfg.type === 'line') {
|
|
34
|
+
const minX = Math.min(cfg.x1, cfg.x2);
|
|
35
|
+
const minY = Math.min(cfg.y1, cfg.y2);
|
|
36
|
+
const maxX = Math.max(cfg.x1, cfg.x2);
|
|
37
|
+
const maxY = Math.max(cfg.y1, cfg.y2);
|
|
38
|
+
return {
|
|
39
|
+
width: Math.max(1, maxX - minX),
|
|
40
|
+
height: Math.max(1, maxY - minY),
|
|
41
|
+
offsetX: -minX,
|
|
42
|
+
offsetY: -minY
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (cfg.type === 'polygon') {
|
|
47
|
+
const bounds = getShapePointBounds(cfg.points, toNumber);
|
|
48
|
+
return {
|
|
49
|
+
width: Math.max(1, bounds.maxX - bounds.minX),
|
|
50
|
+
height: Math.max(1, bounds.maxY - bounds.minY),
|
|
51
|
+
offsetX: -bounds.minX,
|
|
52
|
+
offsetY: -bounds.minY
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { width: cfg.width, height: cfg.height, offsetX: 0, offsetY: 0 };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function translatePolygonPoints(points: any[] = [], box: { offsetX: number; offsetY: number }, toNumber = defaultToNumber) {
|
|
60
|
+
return points.map((point, index) => toNumber(point, 0) + (index % 2 === 0 ? box.offsetX : box.offsetY));
|
|
61
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<Container width={shapeWidth} height={shapeHeight} minWidth={shapeWidth} minHeight={shapeHeight}>
|
|
2
|
+
<Graphics width={shapeWidth} height={shapeHeight} draw={drawShape} />
|
|
3
|
+
</Container>
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
import { computed } from "canvasengine";
|
|
7
|
+
import { resolveDynamicValue } from "./parse-value";
|
|
8
|
+
import { getShapeBox, translatePolygonPoints } from "./shape-utils";
|
|
9
|
+
|
|
10
|
+
const props = defineProps();
|
|
11
|
+
const { object } = props;
|
|
12
|
+
const sprite = object();
|
|
13
|
+
|
|
14
|
+
const read = (prop, fallback) => prop ? prop() : fallback;
|
|
15
|
+
|
|
16
|
+
const toNumber = (value, fallback = 0) => {
|
|
17
|
+
const resolved = resolveDynamicValue(value, sprite);
|
|
18
|
+
const num = typeof resolved === 'number' ? resolved : parseFloat(resolved);
|
|
19
|
+
return Number.isFinite(num) ? num : fallback;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const toColor = (value, fallback) => {
|
|
23
|
+
const resolved = resolveDynamicValue(value, sprite);
|
|
24
|
+
if (typeof resolved === 'number') return resolved;
|
|
25
|
+
if (typeof resolved === 'string' && resolved.startsWith('#')) {
|
|
26
|
+
return parseInt(resolved.slice(1), 16);
|
|
27
|
+
}
|
|
28
|
+
return resolved ?? fallback;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const config = computed(() => ({
|
|
32
|
+
type: read(props.type, 'rectangle'),
|
|
33
|
+
fill: toColor(read(props.fill, '#ffffff'), 0xffffff),
|
|
34
|
+
radius: toNumber(read(props.radius, 8), 8),
|
|
35
|
+
width: toNumber(read(props.width, 16), 16),
|
|
36
|
+
height: toNumber(read(props.height, 16), 16),
|
|
37
|
+
x1: toNumber(read(props.x1, 0), 0),
|
|
38
|
+
y1: toNumber(read(props.y1, 0), 0),
|
|
39
|
+
x2: toNumber(read(props.x2, 16), 16),
|
|
40
|
+
y2: toNumber(read(props.y2, 0), 0),
|
|
41
|
+
opacity: Math.max(0, Math.min(1, toNumber(read(props.opacity, 1), 1))),
|
|
42
|
+
points: read(props.points, []),
|
|
43
|
+
line: read(props.line, null)
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
const shapeBox = computed(() => getShapeBox(config(), toNumber));
|
|
47
|
+
|
|
48
|
+
const shapeWidth = computed(() => shapeBox().width);
|
|
49
|
+
const shapeHeight = computed(() => shapeBox().height);
|
|
50
|
+
|
|
51
|
+
const drawShape = (g) => {
|
|
52
|
+
const cfg = config();
|
|
53
|
+
const box = shapeBox();
|
|
54
|
+
|
|
55
|
+
if (cfg.type === 'circle') {
|
|
56
|
+
g.circle(cfg.radius, cfg.radius, cfg.radius);
|
|
57
|
+
} else if (cfg.type === 'ellipse') {
|
|
58
|
+
g.ellipse(box.width / 2, box.height / 2, box.width / 2, box.height / 2);
|
|
59
|
+
} else if (cfg.type === 'line') {
|
|
60
|
+
g.moveTo(cfg.x1 + box.offsetX, cfg.y1 + box.offsetY);
|
|
61
|
+
g.lineTo(cfg.x2 + box.offsetX, cfg.y2 + box.offsetY);
|
|
62
|
+
} else if (cfg.type === 'polygon' && Array.isArray(cfg.points)) {
|
|
63
|
+
g.poly(translatePolygonPoints(cfg.points, box, toNumber));
|
|
64
|
+
} else if (cfg.type === 'rounded-rectangle') {
|
|
65
|
+
g.roundRect(0, 0, box.width, box.height, toNumber(read(props.radius, 4), 4));
|
|
66
|
+
} else {
|
|
67
|
+
g.rect(0, 0, box.width, box.height);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (cfg.type === 'line') {
|
|
71
|
+
const line = cfg.line ?? {};
|
|
72
|
+
g.stroke({
|
|
73
|
+
color: toColor(line.color, cfg.fill),
|
|
74
|
+
width: toNumber(line.width, 1),
|
|
75
|
+
alpha: toNumber(line.alpha, cfg.opacity)
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
g.fill({ color: cfg.fill, alpha: cfg.opacity });
|
|
81
|
+
|
|
82
|
+
if (cfg.line) {
|
|
83
|
+
g.stroke({
|
|
84
|
+
color: toColor(cfg.line.color, cfg.fill),
|
|
85
|
+
width: toNumber(cfg.line.width, 1),
|
|
86
|
+
alpha: toNumber(cfg.line.alpha, cfg.opacity)
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
</script>
|
|
@@ -1,157 +1,39 @@
|
|
|
1
|
-
<Text text={
|
|
1
|
+
<Text text={textValue} color={textColor} size={textSize} fontFamily={textFontFamily} style={textStyle} />
|
|
2
2
|
|
|
3
3
|
<script>
|
|
4
4
|
import { computed } from "canvasengine";
|
|
5
|
-
import {
|
|
5
|
+
import { resolveDynamicValue } from "./parse-value";
|
|
6
6
|
|
|
7
|
-
const { object } = defineProps();
|
|
8
|
-
const
|
|
7
|
+
const { object, value, style } = defineProps();
|
|
8
|
+
const sprite = object();
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
* Parses a numeric style value that can be a number or a string
|
|
12
|
-
*
|
|
13
|
-
* If the value is a string, it may contain dynamic references like {hp}
|
|
14
|
-
* which need to be parsed using parseDynamicValue. If it's a number,
|
|
15
|
-
* it's returned as-is wrapped in a computed.
|
|
16
|
-
*
|
|
17
|
-
* @param value - Numeric value (number or string)
|
|
18
|
-
* @param object - Object to resolve dynamic references from
|
|
19
|
-
* @returns Computed signal with the numeric value
|
|
20
|
-
*/
|
|
21
|
-
const parseNumericStyleValue = (value, object) => {
|
|
22
|
-
if (value === undefined || value === null) {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (typeof value === 'number') {
|
|
27
|
-
return value;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (typeof value === 'string') {
|
|
31
|
-
// Check if it contains dynamic references
|
|
32
|
-
if (value.includes('{')) {
|
|
33
|
-
// Parse dynamic value and convert to number
|
|
34
|
-
const parsed = parseDynamicValue(value, object);
|
|
35
|
-
return computed(() => {
|
|
36
|
-
const str = parsed();
|
|
37
|
-
const num = parseFloat(str);
|
|
38
|
-
return isNaN(num) ? 0 : num;
|
|
39
|
-
});
|
|
40
|
-
} else {
|
|
41
|
-
// Simple string number, convert directly
|
|
42
|
-
const num = parseFloat(value);
|
|
43
|
-
return isNaN(num) ? undefined : num;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return value;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Maps component style properties to Canvas Engine Text component props
|
|
52
|
-
*
|
|
53
|
-
* Converts TextComponentOptions from the server to the format expected
|
|
54
|
-
* by the Canvas Engine Text component. Supports all text styling properties
|
|
55
|
-
* including fill, fontSize, fontFamily, fontStyle, fontWeight, stroke,
|
|
56
|
-
* opacity, wordWrap, and align. Also supports dynamic values (number | string)
|
|
57
|
-
* for numeric properties like fontSize and opacity.
|
|
58
|
-
*
|
|
59
|
-
* @param component - Component definition with style property
|
|
60
|
-
* @returns Object with Text component props
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```ts
|
|
64
|
-
* // Component with style
|
|
65
|
-
* const component = {
|
|
66
|
-
* style: {
|
|
67
|
-
* fill: '#000000',
|
|
68
|
-
* fontSize: 20,
|
|
69
|
-
* fontFamily: 'Arial',
|
|
70
|
-
* fontWeight: 'bold'
|
|
71
|
-
* }
|
|
72
|
-
* };
|
|
73
|
-
*
|
|
74
|
-
* const props = getComponentStyle(component);
|
|
75
|
-
* // Returns: { color: '#000000', size: 20, fontFamily: 'Arial', style: { fontWeight: 'bold' } }
|
|
76
|
-
*
|
|
77
|
-
* // Component with dynamic fontSize
|
|
78
|
-
* const component2 = {
|
|
79
|
-
* style: {
|
|
80
|
-
* fill: '#000000',
|
|
81
|
-
* fontSize: '{hp}', // Will be resolved from object.hp
|
|
82
|
-
* opacity: '0.8'
|
|
83
|
-
* }
|
|
84
|
-
* };
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
const getComponentStyle = (component) => {
|
|
88
|
-
if (!component.style) {
|
|
89
|
-
return {};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const style = component.style;
|
|
93
|
-
const result = {};
|
|
94
|
-
|
|
95
|
-
// Map fill to color (shortcut property)
|
|
96
|
-
// fill can be a string (hex color) or a dynamic string
|
|
97
|
-
if (style.fill !== undefined) {
|
|
98
|
-
if (typeof style.fill === 'string' && style.fill.includes('{')) {
|
|
99
|
-
result.color = parseDynamicValue(style.fill, object);
|
|
100
|
-
} else {
|
|
101
|
-
result.color = style.fill;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
10
|
+
const read = (prop, fallback) => prop ? prop() : fallback;
|
|
104
11
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
if (fontSizeValue !== undefined) {
|
|
110
|
-
result.size = fontSizeValue;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
12
|
+
const parseNumericStyleValue = (value, object) => {
|
|
13
|
+
value = resolveDynamicValue(value, sprite);
|
|
14
|
+
if (value === undefined || value === null) return undefined;
|
|
15
|
+
if (typeof value === 'number') return value;
|
|
113
16
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
result.fontFamily = parseDynamicValue(style.fontFamily, object);
|
|
118
|
-
} else {
|
|
119
|
-
result.fontFamily = style.fontFamily;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
17
|
+
const num = parseFloat(value);
|
|
18
|
+
return isNaN(num) ? undefined : num;
|
|
19
|
+
};
|
|
122
20
|
|
|
123
|
-
|
|
21
|
+
const getTextStyle = (style) => {
|
|
22
|
+
if (!style) return {};
|
|
124
23
|
const textStyle = {};
|
|
125
24
|
|
|
126
|
-
// Font style properties
|
|
127
25
|
if (style.fontStyle !== undefined) {
|
|
128
|
-
|
|
129
|
-
textStyle.fontStyle = parseDynamicValue(style.fontStyle, object);
|
|
130
|
-
} else {
|
|
131
|
-
textStyle.fontStyle = style.fontStyle;
|
|
132
|
-
}
|
|
26
|
+
textStyle.fontStyle = resolveDynamicValue(style.fontStyle, sprite);
|
|
133
27
|
}
|
|
134
28
|
|
|
135
29
|
if (style.fontWeight !== undefined) {
|
|
136
|
-
|
|
137
|
-
textStyle.fontWeight = parseDynamicValue(style.fontWeight, object);
|
|
138
|
-
} else if (typeof style.fontWeight === 'number') {
|
|
139
|
-
textStyle.fontWeight = style.fontWeight;
|
|
140
|
-
} else {
|
|
141
|
-
textStyle.fontWeight = style.fontWeight;
|
|
142
|
-
}
|
|
30
|
+
textStyle.fontWeight = resolveDynamicValue(style.fontWeight, sprite);
|
|
143
31
|
}
|
|
144
32
|
|
|
145
|
-
// Stroke properties
|
|
146
33
|
if (style.stroke !== undefined) {
|
|
147
|
-
|
|
148
|
-
textStyle.stroke = parseDynamicValue(style.stroke, object);
|
|
149
|
-
} else {
|
|
150
|
-
textStyle.stroke = style.stroke;
|
|
151
|
-
}
|
|
34
|
+
textStyle.stroke = resolveDynamicValue(style.stroke, sprite);
|
|
152
35
|
}
|
|
153
36
|
|
|
154
|
-
// Opacity (can be number or string)
|
|
155
37
|
if (style.opacity !== undefined) {
|
|
156
38
|
const opacityValue = parseNumericStyleValue(style.opacity, object);
|
|
157
39
|
if (opacityValue !== undefined) {
|
|
@@ -159,25 +41,29 @@ const getComponentStyle = (component) => {
|
|
|
159
41
|
}
|
|
160
42
|
}
|
|
161
43
|
|
|
162
|
-
// Word wrap
|
|
163
44
|
if (style.wordWrap !== undefined) {
|
|
164
45
|
textStyle.wordWrap = style.wordWrap;
|
|
165
46
|
}
|
|
166
47
|
|
|
167
|
-
// Text alignment
|
|
168
48
|
if (style.align !== undefined) {
|
|
169
|
-
|
|
170
|
-
textStyle.align = parseDynamicValue(style.align, object);
|
|
171
|
-
} else {
|
|
172
|
-
textStyle.align = style.align;
|
|
173
|
-
}
|
|
49
|
+
textStyle.align = resolveDynamicValue(style.align, sprite);
|
|
174
50
|
}
|
|
175
51
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
result.style = textStyle;
|
|
179
|
-
}
|
|
52
|
+
return textStyle;
|
|
53
|
+
};
|
|
180
54
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
55
|
+
const textValue = computed(() => String(resolveDynamicValue(read(value, ''), sprite) ?? ''));
|
|
56
|
+
const textColor = computed(() => {
|
|
57
|
+
const currentStyle = read(style, {});
|
|
58
|
+
return currentStyle.fill !== undefined ? resolveDynamicValue(currentStyle.fill, sprite) : undefined;
|
|
59
|
+
});
|
|
60
|
+
const textSize = computed(() => {
|
|
61
|
+
const currentStyle = read(style, {});
|
|
62
|
+
return currentStyle.fontSize !== undefined ? parseNumericStyleValue(currentStyle.fontSize, object) : undefined;
|
|
63
|
+
});
|
|
64
|
+
const textFontFamily = computed(() => {
|
|
65
|
+
const currentStyle = read(style, {});
|
|
66
|
+
return currentStyle.fontFamily !== undefined ? resolveDynamicValue(currentStyle.fontFamily, sprite) : undefined;
|
|
67
|
+
});
|
|
68
|
+
const textStyle = computed(() => getTextStyle(read(style, {})));
|
|
69
|
+
</script>
|