@rpgjs/client 5.0.0-beta.2 → 5.0.0-beta.22
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 +130 -0
- package/dist/Game/AnimationManager.d.ts +2 -1
- package/dist/Game/AnimationManager.js +21 -9
- package/dist/Game/AnimationManager.js.map +1 -1
- package/dist/Game/AnimationManager.spec.d.ts +1 -0
- package/dist/Game/ClientVisuals.d.ts +61 -0
- package/dist/Game/ClientVisuals.js +96 -0
- package/dist/Game/ClientVisuals.js.map +1 -0
- package/dist/Game/ClientVisuals.spec.d.ts +1 -0
- package/dist/Game/Event.js.map +1 -1
- package/dist/Game/EventComponentResolver.d.ts +16 -0
- package/dist/Game/EventComponentResolver.js +52 -0
- package/dist/Game/EventComponentResolver.js.map +1 -0
- package/dist/Game/EventComponentResolver.spec.d.ts +1 -0
- package/dist/Game/Map.d.ts +9 -1
- package/dist/Game/Map.js +83 -5
- package/dist/Game/Map.js.map +1 -1
- package/dist/Game/Object.d.ts +49 -15
- package/dist/Game/Object.js +101 -42
- package/dist/Game/Object.js.map +1 -1
- package/dist/Game/Object.spec.d.ts +1 -0
- package/dist/Game/Player.js.map +1 -1
- package/dist/Game/ProjectileManager.d.ts +98 -0
- package/dist/Game/ProjectileManager.js +196 -0
- package/dist/Game/ProjectileManager.js.map +1 -0
- package/dist/Game/ProjectileManager.spec.d.ts +1 -0
- package/dist/Gui/Gui.d.ts +20 -6
- package/dist/Gui/Gui.js +132 -57
- 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 +194 -15
- package/dist/RpgClientEngine.d.ts +191 -19
- package/dist/RpgClientEngine.js +693 -74
- package/dist/RpgClientEngine.js.map +1 -1
- package/dist/Sound.js.map +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0/helpers → _@oxc-project_runtime@0.133.0/helpers/esm}/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0/helpers → _@oxc-project_runtime@0.133.0/helpers/esm}/decorateMetadata.js +1 -1
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/components/animations/animation.ce.js +6 -5
- package/dist/components/animations/animation.ce.js.map +1 -1
- package/dist/components/animations/fx.ce.js +60 -0
- package/dist/components/animations/fx.ce.js.map +1 -0
- package/dist/components/animations/hit.ce.js +24 -28
- package/dist/components/animations/hit.ce.js.map +1 -1
- package/dist/components/animations/index.d.ts +1 -0
- package/dist/components/animations/index.js +6 -4
- package/dist/components/animations/index.js.map +1 -1
- package/dist/components/character.ce.js +748 -249
- package/dist/components/character.ce.js.map +1 -1
- package/dist/components/dynamics/bar.ce.js +99 -0
- package/dist/components/dynamics/bar.ce.js.map +1 -0
- package/dist/components/dynamics/image.ce.js +26 -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 +86 -0
- package/dist/components/dynamics/shape.ce.js.map +1 -0
- package/dist/components/dynamics/text.ce.js +36 -56
- package/dist/components/dynamics/text.ce.js.map +1 -1
- package/dist/components/gui/box.ce.js +9 -9
- package/dist/components/gui/box.ce.js.map +1 -1
- package/dist/components/gui/dialogbox/index.ce.js +75 -65
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
- package/dist/components/gui/gameover.ce.js +47 -68
- package/dist/components/gui/gameover.ce.js.map +1 -1
- package/dist/components/gui/hud/hud.ce.js +23 -31
- package/dist/components/gui/hud/hud.ce.js.map +1 -1
- package/dist/components/gui/menu/equip-menu.ce.js +121 -172
- package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/exit-menu.ce.js +15 -10
- package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/items-menu.ce.js +62 -77
- package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/main-menu.ce.js +89 -104
- package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/options-menu.ce.js +12 -8
- package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/skills-menu.ce.js +17 -19
- package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
- package/dist/components/gui/mobile/index.d.ts +51 -2
- package/dist/components/gui/mobile/index.js +14 -6
- package/dist/components/gui/mobile/index.js.map +1 -1
- package/dist/components/gui/mobile/index.spec.d.ts +1 -0
- package/dist/components/gui/mobile/mobile.ce.js +309 -59
- package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
- package/dist/components/gui/notification/notification.ce.js +28 -26
- package/dist/components/gui/notification/notification.ce.js.map +1 -1
- package/dist/components/gui/save-load.ce.js +81 -256
- package/dist/components/gui/save-load.ce.js.map +1 -1
- package/dist/components/gui/shop/shop.ce.js +107 -142
- package/dist/components/gui/shop/shop.ce.js.map +1 -1
- package/dist/components/gui/title-screen.ce.js +50 -73
- 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/interaction-components.ce.js +22 -0
- package/dist/components/interaction-components.ce.js.map +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 +191 -0
- package/dist/components/player-components.ce.js.map +1 -0
- package/dist/components/prebuilt/hp-bar.ce.js +45 -45
- package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
- package/dist/components/prebuilt/light-halo.ce.js +39 -60
- package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
- package/dist/components/scenes/canvas.ce.js +205 -27
- package/dist/components/scenes/canvas.ce.js.map +1 -1
- package/dist/components/scenes/draw-map.ce.js +39 -39
- package/dist/components/scenes/draw-map.ce.js.map +1 -1
- package/dist/components/scenes/event-layer.ce.js +51 -10
- 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/i18n.d.ts +55 -0
- package/dist/i18n.js +60 -0
- package/dist/i18n.js.map +1 -0
- package/dist/i18n.spec.d.ts +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +29 -21
- package/dist/module.js +45 -4
- package/dist/module.js.map +1 -1
- package/dist/node_modules/.pnpm/{@signe_di@2.9.0 → @signe_di@3.1.0}/node_modules/@signe/di/dist/index.js +7 -117
- package/dist/node_modules/.pnpm/@signe_di@3.1.0/node_modules/@signe/di/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_reactive@3.1.0/node_modules/@signe/reactive/dist/index.js +239 -0
- package/dist/node_modules/.pnpm/@signe_reactive@3.1.0/node_modules/@signe/reactive/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/chunk-EUXUH3YW.js +13 -0
- package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/chunk-EUXUH3YW.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/index.js +698 -0
- package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/node_modules/@signe/sync/dist/client/index.js +43 -0
- package/dist/node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/node_modules/@signe/sync/dist/client/index.js.map +1 -0
- package/dist/node_modules/.pnpm/{@signe_sync@2.9.0 → @signe_sync@3.1.0_react@19.2.7}/node_modules/@signe/sync/dist/index.js +57 -141
- package/dist/node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/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 → partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/index.js} +30 -17
- package/dist/node_modules/.pnpm/partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/{partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js → partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/ws.js} +65 -34
- package/dist/node_modules/.pnpm/partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/ws.js.map +1 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js +13 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js.map +1 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js +106 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js.map +1 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js +13 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js.map +1 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js +121 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js.map +1 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js +10 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js.map +1 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js +110 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js.map +1 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js +99 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js.map +1 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js +82 -0
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js.map +1 -0
- package/dist/node_modules/.pnpm/{zod@3.24.2/node_modules/zod/lib/index.js → zod@3.25.76/node_modules/zod/v3/types.js} +74 -611
- package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js.map +1 -0
- 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.d.ts +2 -0
- package/dist/services/AbstractSocket.js.map +1 -1
- package/dist/services/actionInput.d.ts +14 -0
- package/dist/services/actionInput.js +59 -0
- package/dist/services/actionInput.js.map +1 -0
- package/dist/services/actionInput.spec.d.ts +1 -0
- package/dist/services/cameraFollow.d.ts +51 -0
- package/dist/services/cameraFollow.js +134 -0
- package/dist/services/cameraFollow.js.map +1 -0
- package/dist/services/cameraFollow.spec.d.ts +1 -0
- package/dist/services/interactions.d.ts +159 -0
- package/dist/services/interactions.js +460 -0
- package/dist/services/interactions.js.map +1 -0
- package/dist/services/interactions.spec.d.ts +1 -0
- package/dist/services/keyboardControls.d.ts +1 -0
- package/dist/services/keyboardControls.js +1 -0
- package/dist/services/keyboardControls.js.map +1 -1
- package/dist/services/loadMap.d.ts +9 -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 +11 -4
- package/dist/services/mmorpg.js +57 -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.d.ts +4 -1
- package/dist/services/standalone.js +36 -16
- 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/mapId.d.ts +1 -0
- package/dist/utils/mapId.js +6 -0
- package/dist/utils/mapId.js.map +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 -13
- package/src/Game/AnimationManager.spec.ts +30 -0
- package/src/Game/AnimationManager.ts +26 -10
- package/src/Game/ClientVisuals.spec.ts +56 -0
- package/src/Game/ClientVisuals.ts +184 -0
- package/src/Game/EventComponentResolver.spec.ts +84 -0
- package/src/Game/EventComponentResolver.ts +74 -0
- package/src/Game/Map.ts +134 -2
- package/src/Game/Object.spec.ts +59 -0
- package/src/Game/Object.ts +181 -77
- package/src/Game/ProjectileManager.spec.ts +449 -0
- package/src/Game/ProjectileManager.ts +346 -0
- package/src/Gui/Gui.spec.ts +359 -0
- package/src/Gui/Gui.ts +178 -67
- package/src/Resource.ts +1 -2
- package/src/RpgClient.ts +220 -17
- package/src/RpgClientEngine.ts +995 -133
- package/src/components/animations/fx.ce +101 -0
- package/src/components/animations/index.ts +4 -2
- package/src/components/character.ce +839 -45
- 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 +52 -21
- package/src/components/gui/gameover.ce +6 -4
- package/src/components/gui/menu/equip-menu.ce +11 -9
- package/src/components/gui/menu/exit-menu.ce +6 -4
- package/src/components/gui/menu/items-menu.ce +11 -9
- package/src/components/gui/menu/main-menu.ce +14 -12
- package/src/components/gui/menu/options-menu.ce +4 -3
- package/src/components/gui/menu/skills-menu.ce +2 -1
- package/src/components/gui/mobile/index.spec.ts +94 -0
- package/src/components/gui/mobile/index.ts +74 -6
- package/src/components/gui/mobile/mobile.ce +347 -65
- package/src/components/gui/notification/notification.ce +7 -1
- package/src/components/gui/save-load.ce +13 -11
- package/src/components/gui/shop/shop.ce +20 -18
- package/src/components/gui/title-screen.ce +6 -4
- package/src/components/index.ts +2 -1
- package/src/components/interaction-components.ce +23 -0
- 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 +219 -15
- package/src/components/scenes/draw-map.ce +34 -22
- package/src/components/scenes/event-layer.ce +55 -4
- package/src/core/setup.ts +2 -2
- package/src/decorators/spritesheet.ts +8 -0
- package/src/i18n.spec.ts +39 -0
- package/src/i18n.ts +59 -0
- package/src/index.ts +19 -0
- package/src/module.ts +61 -11
- package/src/services/AbstractSocket.ts +3 -0
- package/src/services/actionInput.spec.ts +155 -0
- package/src/services/actionInput.ts +120 -0
- package/src/services/cameraFollow.spec.ts +220 -0
- package/src/services/cameraFollow.ts +222 -0
- package/src/services/interactions.spec.ts +175 -0
- package/src/services/interactions.ts +722 -0
- package/src/services/keyboardControls.ts +2 -1
- package/src/services/loadMap.ts +5 -1
- package/src/services/mmorpg-connection.spec.ts +99 -0
- package/src/services/mmorpg-connection.ts +69 -0
- package/src/services/mmorpg.ts +70 -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 +54 -0
- package/src/services/standalone.ts +44 -12
- package/src/utils/getEntityProp.spec.ts +96 -0
- package/src/utils/getEntityProp.ts +4 -3
- package/src/utils/mapId.ts +2 -0
- 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
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +0 -1
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +0 -1
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/index.js +0 -2
- package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +0 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<Container width={width} height={containerHeight} minWidth={width} minHeight={containerHeight}>
|
|
2
|
+
<Graphics width={width} height={containerHeight} draw={drawBar} />
|
|
3
|
+
@if (hasLabel) {
|
|
4
|
+
<Text text={labelText} x={labelPosition.x} y={labelPosition.y} size={labelSize} color={labelColor} />
|
|
5
|
+
}
|
|
6
|
+
</Container>
|
|
7
|
+
|
|
8
|
+
<script>
|
|
9
|
+
import { computed } from "canvasengine";
|
|
10
|
+
import { resolveDynamicValue } from "./parse-value";
|
|
11
|
+
|
|
12
|
+
const { object, current, max, style, text } = defineProps();
|
|
13
|
+
const sprite = object();
|
|
14
|
+
|
|
15
|
+
const read = (prop, fallback) => prop ? prop() : fallback;
|
|
16
|
+
|
|
17
|
+
const toNumber = (value, fallback = 0) => {
|
|
18
|
+
const resolved = resolveDynamicValue(value, sprite);
|
|
19
|
+
const num = typeof resolved === 'number' ? resolved : parseFloat(resolved);
|
|
20
|
+
return Number.isFinite(num) ? num : fallback;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const toColor = (value, fallback) => {
|
|
24
|
+
const resolved = resolveDynamicValue(value, sprite);
|
|
25
|
+
if (typeof resolved === 'number') return resolved;
|
|
26
|
+
if (typeof resolved === 'string' && resolved.startsWith('#')) {
|
|
27
|
+
return parseInt(resolved.slice(1), 16);
|
|
28
|
+
}
|
|
29
|
+
return resolved ?? fallback;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const config = computed(() => read(style, {}) ?? {});
|
|
33
|
+
const width = computed(() => toNumber(config().width, 50));
|
|
34
|
+
const height = computed(() => toNumber(config().height, 8));
|
|
35
|
+
const borderRadius = computed(() => toNumber(config().borderRadius, 3));
|
|
36
|
+
const borderWidth = computed(() => toNumber(config().borderWidth, 1));
|
|
37
|
+
const backgroundColor = computed(() => toColor(config().bgColor, 0x16213e));
|
|
38
|
+
const fillColor = computed(() => toColor(config().fillColor, 0x4ade80));
|
|
39
|
+
const borderColor = computed(() => toColor(config().borderColor, 0x4a5568));
|
|
40
|
+
const opacity = computed(() => Math.max(0, Math.min(1, toNumber(config().opacity, 1))));
|
|
41
|
+
|
|
42
|
+
const currentValue = computed(() => toNumber(read(current, 0), 0));
|
|
43
|
+
const maxValue = computed(() => Math.max(0, toNumber(read(max, 0), 0)));
|
|
44
|
+
const percent = computed(() => {
|
|
45
|
+
const max = maxValue();
|
|
46
|
+
if (max <= 0) return 0;
|
|
47
|
+
return Math.max(0, Math.min(1, currentValue() / max));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const fillWidth = computed(() => Math.max(0, width() * percent()));
|
|
51
|
+
const labelTemplate = computed(() => read(text, null));
|
|
52
|
+
const labelText = computed(() => {
|
|
53
|
+
const template = labelTemplate();
|
|
54
|
+
if (template == null || template === '') return '';
|
|
55
|
+
|
|
56
|
+
const value = String(template)
|
|
57
|
+
.replace(/\{\$current\}/g, String(currentValue()))
|
|
58
|
+
.replace(/\{\$max\}/g, String(maxValue()))
|
|
59
|
+
.replace(/\{\$percent\}/g, String(Math.round(percent() * 100)));
|
|
60
|
+
|
|
61
|
+
return String(resolveDynamicValue(value, sprite) ?? '');
|
|
62
|
+
});
|
|
63
|
+
const labelSize = computed(() => toNumber(config().fontSize, 10));
|
|
64
|
+
const hasLabel = computed(() => labelText().length > 0);
|
|
65
|
+
const labelOffset = computed(() => hasLabel() ? labelSize() + 2 : 0);
|
|
66
|
+
const containerHeight = computed(() => labelOffset() + height());
|
|
67
|
+
const labelColor = computed(() => toColor(config().textColor, 0xffffff));
|
|
68
|
+
const labelPosition = computed(() => ({
|
|
69
|
+
x: 0,
|
|
70
|
+
y: 0
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
const drawBar = (g) => {
|
|
74
|
+
g.roundRect(0, labelOffset(), width(), height(), borderRadius());
|
|
75
|
+
g.fill({ color: backgroundColor(), alpha: opacity() });
|
|
76
|
+
|
|
77
|
+
const currentWidth = fillWidth();
|
|
78
|
+
if (currentWidth > 0) {
|
|
79
|
+
g.roundRect(0, labelOffset(), currentWidth, height(), borderRadius());
|
|
80
|
+
g.fill({ color: fillColor(), alpha: opacity() });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const strokeWidth = borderWidth();
|
|
84
|
+
if (strokeWidth <= 0) return;
|
|
85
|
+
g.roundRect(0, labelOffset(), width(), height(), borderRadius());
|
|
86
|
+
g.stroke({ color: borderColor(), width: strokeWidth, alpha: opacity() });
|
|
87
|
+
};
|
|
88
|
+
</script>
|
|
@@ -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>
|