cyberia 3.2.5 → 3.2.9
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/.github/workflows/engine-cyberia.cd.yml +2 -2
- package/.github/workflows/release.cd.yml +1 -2
- package/CHANGELOG.md +351 -1
- package/CLI-HELP.md +40 -13
- package/Dockerfile +0 -4
- package/README.md +242 -497
- package/bin/build.js +19 -5
- package/bin/cyberia.js +1149 -240
- package/bin/deploy.js +570 -1
- package/bin/file.js +6 -0
- package/bin/index.js +1149 -240
- package/bin/vs.js +1 -1
- package/conf.js +67 -89
- package/deployment.yaml +4 -222
- package/hardhat/package-lock.json +32 -32
- package/hardhat/package.json +3 -3
- package/jsconfig.json +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +2 -2
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +4 -222
- package/manifests/deployment/dd-cyberia-development/proxy.yaml +10 -118
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -6
- package/manifests/deployment/dd-test-development/deployment.yaml +136 -66
- package/manifests/deployment/dd-test-development/proxy.yaml +41 -5
- package/package.json +23 -14
- package/proxy.yaml +10 -118
- package/scripts/k3s-node-setup.sh +2 -2
- package/scripts/nat-iptables.sh +103 -18
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +18 -18
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +7 -14
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +76 -21
- package/src/api/core/core.controller.js +10 -10
- package/src/api/core/core.service.js +10 -10
- package/src/api/crypto/crypto.controller.js +8 -8
- package/src/api/crypto/crypto.service.js +8 -8
- package/src/api/cyberia-action/cyberia-action.controller.js +74 -0
- package/src/api/cyberia-action/cyberia-action.model.js +87 -0
- package/src/api/cyberia-action/cyberia-action.router.js +27 -0
- package/src/api/cyberia-action/cyberia-action.service.js +42 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +13 -13
- package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +11 -11
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +2 -2
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +16 -16
- package/src/api/cyberia-entity/cyberia-entity.controller.js +10 -10
- package/src/api/cyberia-entity/cyberia-entity.service.js +10 -10
- package/src/api/cyberia-instance/cyberia-fallback-world.js +19 -209
- package/src/api/cyberia-instance/cyberia-instance.controller.js +14 -14
- package/src/api/cyberia-instance/cyberia-instance.model.js +3 -0
- package/src/api/cyberia-instance/cyberia-instance.service.js +22 -57
- package/src/api/cyberia-instance/cyberia-portal-connector.js +20 -246
- package/src/api/cyberia-instance/cyberia-world-generator.js +505 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +10 -10
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +216 -55
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +4 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +18 -14
- package/src/api/cyberia-map/cyberia-map.controller.js +10 -10
- package/src/api/cyberia-map/cyberia-map.service.js +10 -10
- package/src/api/cyberia-quest/cyberia-quest.controller.js +74 -0
- package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
- package/src/api/cyberia-quest/cyberia-quest.router.js +27 -0
- package/src/api/cyberia-quest/cyberia-quest.service.js +42 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +74 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +27 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
- package/src/api/default/default.controller.js +10 -10
- package/src/api/default/default.service.js +10 -10
- package/src/api/document/document.controller.js +12 -12
- package/src/api/document/document.model.js +10 -16
- package/src/api/file/file.controller.js +8 -8
- package/src/api/file/file.model.js +10 -10
- package/src/api/file/file.service.js +36 -36
- package/src/api/instance/instance.controller.js +10 -10
- package/src/api/instance/instance.model.js +4 -10
- package/src/api/instance/instance.service.js +10 -10
- package/src/api/ipfs/ipfs.controller.js +12 -12
- package/src/api/ipfs/ipfs.model.js +4 -13
- package/src/api/ipfs/ipfs.service.js +14 -28
- package/src/api/object-layer/object-layer.controller.js +12 -12
- package/src/api/object-layer/object-layer.model.js +4 -17
- package/src/api/object-layer/object-layer.service.js +12 -12
- package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +10 -10
- package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +6 -16
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +18 -14
- package/src/api/test/test.controller.js +8 -8
- package/src/api/test/test.service.js +8 -8
- package/src/api/user/guest.service.js +99 -0
- package/src/api/user/user.controller.js +6 -6
- package/src/api/user/user.model.js +8 -13
- package/src/api/user/user.service.js +3 -20
- package/src/cli/cluster.js +61 -14
- package/src/cli/db.js +47 -2
- package/src/cli/deploy.js +67 -35
- package/src/cli/fs.js +79 -8
- package/src/cli/image.js +43 -1
- package/src/cli/index.js +26 -1
- package/src/cli/release.js +57 -1
- package/src/cli/repository.js +69 -31
- package/src/cli/run.js +415 -36
- package/src/cli/ssh.js +1 -1
- package/src/cli/static.js +43 -115
- package/src/client/Cryptokoyn.index.js +18 -21
- package/src/client/CyberiaPortal.index.js +19 -23
- package/src/client/Default.index.js +21 -33
- package/src/client/Itemledger.index.js +20 -26
- package/src/client/Underpost.index.js +19 -23
- package/src/client/components/core/404.js +4 -4
- package/src/client/components/core/500.js +4 -4
- package/src/client/components/core/Account.js +73 -60
- package/src/client/components/core/AgGrid.js +23 -33
- package/src/client/components/core/Alert.js +12 -13
- package/src/client/components/core/AppStore.js +1 -1
- package/src/client/components/core/Auth.js +35 -37
- package/src/client/components/core/Badge.js +7 -13
- package/src/client/components/core/BtnIcon.js +15 -17
- package/src/client/components/core/CalendarCore.js +42 -63
- package/src/client/components/core/Chat.js +13 -15
- package/src/client/components/core/ClientEvents.js +87 -0
- package/src/client/components/core/ColorPaletteElement.js +309 -0
- package/src/client/components/core/Content.js +17 -14
- package/src/client/components/core/Css.js +15 -71
- package/src/client/components/core/CssCore.js +12 -16
- package/src/client/components/core/D3Chart.js +4 -4
- package/src/client/components/core/Docs.js +64 -91
- package/src/client/components/core/DropDown.js +69 -91
- package/src/client/components/core/EventBus.js +92 -0
- package/src/client/components/core/EventsUI.js +14 -17
- package/src/client/components/core/FileExplorer.js +96 -228
- package/src/client/components/core/FullScreen.js +47 -75
- package/src/client/components/core/Input.js +24 -69
- package/src/client/components/core/Keyboard.js +25 -18
- package/src/client/components/core/KeyboardAvoidance.js +145 -0
- package/src/client/components/core/LoadingAnimation.js +25 -31
- package/src/client/components/core/LogIn.js +41 -41
- package/src/client/components/core/LogOut.js +23 -14
- package/src/client/components/core/Modal.js +462 -178
- package/src/client/components/core/NotificationManager.js +14 -18
- package/src/client/components/core/Panel.js +54 -50
- package/src/client/components/core/PanelForm.js +25 -125
- package/src/client/components/core/Polyhedron.js +110 -214
- package/src/client/components/core/PublicProfile.js +39 -32
- package/src/client/components/core/Recover.js +48 -44
- package/src/client/components/core/Responsive.js +88 -32
- package/src/client/components/core/RichText.js +9 -18
- package/src/client/components/core/Router.js +24 -3
- package/src/client/components/core/SearchBox.js +37 -37
- package/src/client/components/core/SignUp.js +39 -30
- package/src/client/components/core/SocketIo.js +31 -2
- package/src/client/components/core/SocketIoHandler.js +6 -6
- package/src/client/components/core/ToggleSwitch.js +8 -20
- package/src/client/components/core/ToolTip.js +5 -17
- package/src/client/components/core/Translate.js +56 -59
- package/src/client/components/core/Validator.js +26 -16
- package/src/client/components/core/Wallet.js +15 -26
- package/src/client/components/core/Worker.js +163 -27
- package/src/client/components/core/windowGetDimensions.js +7 -7
- package/src/client/components/cryptokoyn/{MenuCryptokoyn.js → AppShellCryptokoyn.js} +57 -57
- package/src/client/components/cryptokoyn/CssCryptokoyn.js +15 -15
- package/src/client/components/cryptokoyn/LogInCryptokoyn.js +6 -4
- package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +6 -4
- package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
- package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +4 -4
- package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +6 -4
- package/src/client/components/cyberia/InstanceEngineCyberia.js +141 -60
- package/src/client/components/cyberia/MapEngineCyberia.js +691 -214
- package/src/client/components/cyberia/ObjectLayerEngine.js +19 -0
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +1204 -94
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +196 -298
- package/src/client/components/cyberia-portal/{MenuCyberiaPortal.js → AppShellCyberiaPortal.js} +102 -102
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +305 -61
- package/src/client/components/cyberia-portal/CssCyberiaPortal.js +15 -15
- package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +6 -4
- package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +6 -4
- package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +4 -4
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +60 -0
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +4 -4
- package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +6 -4
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -4
- package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +87 -87
- package/src/client/components/default/CssDefault.js +12 -12
- package/src/client/components/default/LogInDefault.js +6 -4
- package/src/client/components/default/LogOutDefault.js +6 -4
- package/src/client/components/default/RouterDefault.js +47 -0
- package/src/client/components/default/SettingsDefault.js +4 -4
- package/src/client/components/default/SignUpDefault.js +6 -4
- package/src/client/components/default/TranslateDefault.js +3 -3
- package/src/client/components/itemledger/{MenuItemledger.js → AppShellItemledger.js} +57 -57
- package/src/client/components/itemledger/CssItemledger.js +15 -15
- package/src/client/components/itemledger/LogInItemledger.js +6 -4
- package/src/client/components/itemledger/LogOutItemledger.js +6 -4
- package/src/client/components/itemledger/RouterItemledger.js +38 -0
- package/src/client/components/itemledger/SettingsItemledger.js +4 -4
- package/src/client/components/itemledger/SignUpItemledger.js +6 -4
- package/src/client/components/itemledger/TranslateItemledger.js +3 -3
- package/src/client/components/underpost/{MenuUnderpost.js → AppShellUnderpost.js} +88 -88
- package/src/client/components/underpost/CssUnderpost.js +14 -14
- package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +4 -4
- package/src/client/components/underpost/DocumentSearchProvider.js +1 -1
- package/src/client/components/underpost/LabGalleryUnderpost.js +12 -15
- package/src/client/components/underpost/LogInUnderpost.js +6 -4
- package/src/client/components/underpost/LogOutUnderpost.js +6 -4
- package/src/client/components/underpost/RouterUnderpost.js +45 -0
- package/src/client/components/underpost/SettingsUnderpost.js +4 -4
- package/src/client/components/underpost/SignUpUnderpost.js +6 -4
- package/src/client/components/underpost/TranslateUnderpost.js +4 -4
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +235 -0
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +443 -0
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +417 -0
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +313 -0
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +260 -0
- package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +241 -0
- package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
- package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +279 -0
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +206 -0
- package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +732 -0
- package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +14 -20
- package/src/client/services/core/core.service.js +17 -49
- package/src/client/services/crypto/crypto.service.js +8 -13
- package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
- package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +10 -16
- package/src/client/services/cyberia-entity/cyberia-entity.management.js +5 -5
- package/src/client/services/cyberia-entity/cyberia-entity.service.js +10 -16
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +6 -6
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +12 -18
- package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +10 -16
- package/src/client/services/cyberia-map/cyberia-map.management.js +6 -6
- package/src/client/services/cyberia-map/cyberia-map.service.js +12 -18
- package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
- package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
- package/src/client/services/default/default.management.js +159 -267
- package/src/client/services/default/default.service.js +10 -16
- package/src/client/services/document/document.service.js +14 -19
- package/src/client/services/file/file.service.js +8 -13
- package/src/client/services/instance/instance.management.js +5 -5
- package/src/client/services/instance/instance.service.js +10 -15
- package/src/client/services/ipfs/ipfs.service.js +12 -18
- package/src/client/services/object-layer/object-layer.management.js +12 -12
- package/src/client/services/object-layer/object-layer.service.js +20 -26
- package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +10 -16
- package/src/client/services/test/test.service.js +8 -13
- package/src/client/services/user/guest.service.js +86 -0
- package/src/client/services/user/user.management.js +5 -5
- package/src/client/services/user/user.service.js +14 -20
- package/src/client/ssr/body/404.js +3 -3
- package/src/client/ssr/body/500.js +3 -3
- package/src/client/ssr/body/CacheControl.js +5 -2
- package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
- package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +13 -6
- package/src/client/ssr/head/PwaItemledger.js +197 -60
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
- package/src/client/ssr/offline/Maintenance.js +12 -11
- package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
- package/src/client/ssr/pages/Test.js +2 -2
- package/src/client/sw/core.sw.js +212 -0
- package/src/grpc/cyberia/grpc-server.js +179 -67
- package/src/index.js +1 -1
- package/src/runtime/cyberia-client/Dockerfile +80 -0
- package/src/runtime/cyberia-server/Dockerfile +37 -0
- package/src/runtime/express/Dockerfile +4 -4
- package/src/runtime/lampp/Dockerfile +8 -7
- package/src/runtime/wp/Dockerfile +11 -17
- package/src/server/atlas-sprite-sheet-generator.js +4 -2
- package/src/server/client-build-docs.js +45 -46
- package/src/server/client-build.js +334 -60
- package/src/server/client-formatted.js +47 -16
- package/src/server/conf.js +5 -4
- package/src/server/data-query.js +32 -20
- package/src/server/dns.js +22 -0
- package/src/server/ipfs-client.js +232 -91
- package/src/server/object-layer.js +1 -6
- package/src/server/process.js +13 -27
- package/src/server/semantic-layer-generator-floor.js +11 -51
- package/src/server/semantic-layer-generator-resource.js +259 -0
- package/src/server/semantic-layer-generator-skin.js +41 -171
- package/src/server/semantic-layer-generator.js +122 -14
- package/src/server/shape-generator.js +108 -0
- package/src/server/start.js +17 -3
- package/src/server/valkey.js +141 -235
- package/tsconfig.docs.json +15 -0
- package/typedoc.dd-cyberia.json +29 -0
- package/typedoc.json +29 -0
- package/WHITE-PAPER.md +0 -1540
- package/hardhat/README.md +0 -531
- package/hardhat/WHITE-PAPER.md +0 -1540
- package/jsdoc.dd-cyberia.json +0 -68
- package/jsdoc.json +0 -68
- package/src/api/object-layer/README.md +0 -672
- package/src/client/components/core/ColorPalette.js +0 -5267
- package/src/client/components/core/JoyStick.js +0 -80
- package/src/client/components/cryptokoyn/RoutesCryptokoyn.js +0 -39
- package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +0 -62
- package/src/client/components/cyberia-portal/ServerCyberiaPortal.js +0 -136
- package/src/client/components/default/RoutesDefault.js +0 -49
- package/src/client/components/itemledger/RoutesItemledger.js +0 -40
- package/src/client/components/underpost/RoutesUnderpost.js +0 -47
- package/src/client/sw/default.sw.js +0 -127
- package/src/client/sw/template.sw.js +0 -84
- package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +0 -305
- package/src/grpc/cyberia/README.md +0 -326
|
@@ -11,7 +11,6 @@ import { ObjectLayerService } from '../../services/object-layer/object-layer.ser
|
|
|
11
11
|
import { AtlasSpriteSheetService } from '../../services/atlas-sprite-sheet/atlas-sprite-sheet.service.js';
|
|
12
12
|
import { NotificationManager } from '../core/NotificationManager.js';
|
|
13
13
|
import { append, htmls, s } from '../core/VanillaJs.js';
|
|
14
|
-
|
|
15
14
|
import { darkTheme, ThemeEvents, subThemeManager, lightenHex, darkenHex } from '../core/Css.js';
|
|
16
15
|
import { ObjectLayerManagement } from '../../services/object-layer/object-layer.management.js';
|
|
17
16
|
import { ObjectLayerEngineModal } from './ObjectLayerEngineModal.js';
|
|
@@ -20,11 +19,9 @@ import { DefaultManagement } from '../../services/default/default.management.js'
|
|
|
20
19
|
import { AgGrid } from '../core/AgGrid.js';
|
|
21
20
|
import { EventsUI } from '../core/EventsUI.js';
|
|
22
21
|
import { createJSONEditor } from 'vanilla-jsoneditor';
|
|
23
|
-
|
|
24
22
|
const logger = loggerFactory(import.meta);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Data: {
|
|
23
|
+
class ObjectLayerEngineViewer {
|
|
24
|
+
static Data = {
|
|
28
25
|
objectLayer: null,
|
|
29
26
|
frameCounts: null,
|
|
30
27
|
currentDirection: 'down',
|
|
@@ -36,10 +33,9 @@ const ObjectLayerEngineViewer = {
|
|
|
36
33
|
isGeneratingAtlas: false,
|
|
37
34
|
webpMetadata: null,
|
|
38
35
|
metadataJsonEditor: null,
|
|
39
|
-
}
|
|
40
|
-
|
|
36
|
+
};
|
|
41
37
|
// Map user-friendly direction/mode to numeric direction codes
|
|
42
|
-
getDirectionCode
|
|
38
|
+
static getDirectionCode(direction, mode) {
|
|
43
39
|
const key = `${direction}_${mode}`;
|
|
44
40
|
const directionCodeMap = {
|
|
45
41
|
down_idle: '08',
|
|
@@ -52,36 +48,29 @@ const ObjectLayerEngineViewer = {
|
|
|
52
48
|
right_walking: '16',
|
|
53
49
|
};
|
|
54
50
|
return directionCodeMap[key] || null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
Render: async function ({ appStore }) {
|
|
51
|
+
}
|
|
52
|
+
static async instance({ appStore }) {
|
|
58
53
|
const id = 'object-layer-engine-viewer';
|
|
59
|
-
|
|
60
54
|
// Reset currentObjectId when modal is rendered to ensure Reload triggers properly
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
ObjectLayerEngineViewer.Data.currentObjectId = undefined;
|
|
63
56
|
Modal.Data[`modal-${id}`].onReloadModalListener[id] = async () => {
|
|
64
57
|
ObjectLayerEngineViewer.Reload({ appStore });
|
|
65
58
|
};
|
|
66
|
-
|
|
67
59
|
// Listen for query parameter changes for smooth navigation
|
|
68
60
|
listenQueryParamsChange({
|
|
69
61
|
id: `${id}-query-listener`,
|
|
70
62
|
event: async (queryParams) => {
|
|
71
63
|
const objectId = queryParams.id || null;
|
|
72
|
-
|
|
73
64
|
if (!s(`.modal-${id}`) || !s(`#${id}`)) {
|
|
74
65
|
logger.warn('ObjectLayerEngineViewer DOM not ready for query param change');
|
|
75
66
|
return;
|
|
76
67
|
}
|
|
77
|
-
|
|
78
68
|
// Only reload if object id actually changed (normalize undefined to null for comparison)
|
|
79
|
-
if (objectId !==
|
|
80
|
-
await
|
|
69
|
+
if (objectId !== ObjectLayerEngineViewer.Data.currentObjectId) {
|
|
70
|
+
await ObjectLayerEngineViewer.Reload({ appStore });
|
|
81
71
|
}
|
|
82
72
|
},
|
|
83
73
|
});
|
|
84
|
-
|
|
85
74
|
return html`
|
|
86
75
|
<div class="fl">
|
|
87
76
|
<div class="in ${id}" id="${id}">
|
|
@@ -91,101 +80,83 @@ const ObjectLayerEngineViewer = {
|
|
|
91
80
|
</div>
|
|
92
81
|
</div>
|
|
93
82
|
`;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
renderEmpty: async function ({ appStore }) {
|
|
83
|
+
}
|
|
84
|
+
static async renderEmpty({ appStore }) {
|
|
97
85
|
const id = 'object-layer-engine-viewer';
|
|
98
86
|
const idModal = 'modal-object-layer-engine-viewer';
|
|
99
|
-
|
|
100
87
|
// Check if DOM element exists
|
|
101
88
|
if (!s(`#${id}`)) {
|
|
102
89
|
logger.warn('ObjectLayerEngineViewer DOM not ready for renderEmpty');
|
|
103
90
|
return;
|
|
104
91
|
}
|
|
105
|
-
|
|
106
92
|
// Clear current object id when rendering empty state
|
|
107
|
-
|
|
108
|
-
|
|
93
|
+
ObjectLayerEngineViewer.Data.currentObjectId = null;
|
|
109
94
|
// Check if the management table grid already exists AND its DOM is still present
|
|
110
95
|
// If it does, don't re-render (just let DefaultManagement's RouterEvents handle URL changes)
|
|
111
96
|
const gridId = `object-layer-engine-management-grid-${idModal}`;
|
|
112
97
|
const gridExists = AgGrid.grids[gridId];
|
|
113
98
|
const gridDomExists = s(`.${gridId}`);
|
|
114
|
-
|
|
115
99
|
if (gridExists && gridDomExists) {
|
|
116
100
|
// Grid already exists with DOM intact, no need to destroy and recreate it
|
|
117
101
|
// The DefaultManagement RouterEvents listener will handle pagination/filter updates
|
|
118
102
|
return;
|
|
119
103
|
}
|
|
120
|
-
|
|
121
104
|
// Grid doesn't exist or its DOM was destroyed, render/re-render it
|
|
122
105
|
if (gridExists && !gridDomExists) {
|
|
123
106
|
// Clean up orphaned grid reference
|
|
124
107
|
AgGrid.grids[gridId].destroy();
|
|
125
108
|
delete AgGrid.grids[gridId];
|
|
126
109
|
}
|
|
127
|
-
|
|
128
110
|
htmls(
|
|
129
111
|
`#${id}`,
|
|
130
|
-
await ObjectLayerManagement.
|
|
112
|
+
await ObjectLayerManagement.instance({
|
|
131
113
|
appStore,
|
|
132
114
|
idModal,
|
|
133
115
|
}),
|
|
134
116
|
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
loadObjectLayer: async function (objectLayerId, appStore, options = {}) {
|
|
117
|
+
}
|
|
118
|
+
static async loadObjectLayer(objectLayerId, appStore, options = {}) {
|
|
138
119
|
const { skipWebp = false } = options;
|
|
139
120
|
const id = 'object-layer-engine-viewer';
|
|
140
|
-
|
|
141
121
|
// Check if DOM element exists
|
|
142
122
|
if (!s(`#${id}`)) {
|
|
143
123
|
logger.warn('ObjectLayerEngineViewer DOM not ready for loadObjectLayer');
|
|
144
124
|
return;
|
|
145
125
|
}
|
|
146
|
-
|
|
147
126
|
try {
|
|
148
127
|
// Load metadata first
|
|
149
128
|
const { status: metaStatus, data: metadata } = await ObjectLayerService.getMetadata({ id: objectLayerId });
|
|
150
|
-
|
|
151
129
|
if (metaStatus !== 'success' || !metadata) {
|
|
152
130
|
throw new Error('Failed to load object layer metadata');
|
|
153
131
|
}
|
|
154
|
-
|
|
155
|
-
this.Data.objectLayer = metadata;
|
|
156
|
-
|
|
132
|
+
ObjectLayerEngineViewer.Data.objectLayer = metadata;
|
|
157
133
|
if (metadata.atlasSpriteSheetId) {
|
|
158
134
|
const { status: atlasStatus, data: atlasData } = await AtlasSpriteSheetService.get({
|
|
159
135
|
id: metadata.atlasSpriteSheetId,
|
|
160
136
|
});
|
|
161
137
|
if (atlasStatus === 'success') {
|
|
162
|
-
|
|
138
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet = atlasData;
|
|
163
139
|
}
|
|
164
140
|
} else {
|
|
165
|
-
|
|
141
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet = null;
|
|
166
142
|
}
|
|
167
|
-
|
|
168
143
|
// Load frame counts for all directions
|
|
169
144
|
const { status: frameStatus, data: frameData } = await ObjectLayerService.getFrameCounts({ id: objectLayerId });
|
|
170
|
-
|
|
171
145
|
if (frameStatus !== 'success' || !frameData) {
|
|
172
146
|
throw new Error('Failed to load frame counts');
|
|
173
147
|
}
|
|
174
|
-
|
|
175
|
-
this.Data.frameCounts = frameData.frameCounts;
|
|
148
|
+
ObjectLayerEngineViewer.Data.frameCounts = frameData.frameCounts;
|
|
176
149
|
// Priority order for directions
|
|
177
150
|
const directions = ['down', 'up', 'left', 'right'];
|
|
178
151
|
// Priority order for modes
|
|
179
152
|
const modes = ['idle', 'walking'];
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
await this.renderViewer({ appStore });
|
|
185
|
-
|
|
153
|
+
ObjectLayerEngineViewer.Data.currentDirection = 'down';
|
|
154
|
+
ObjectLayerEngineViewer.Data.currentMode = 'idle';
|
|
155
|
+
// instance the viewer UI
|
|
156
|
+
await ObjectLayerEngineViewer.renderViewer({ appStore });
|
|
186
157
|
// Generate WebP
|
|
187
158
|
if (!skipWebp) {
|
|
188
|
-
await
|
|
159
|
+
await ObjectLayerEngineViewer.generateWebp();
|
|
189
160
|
}
|
|
190
161
|
} catch (error) {
|
|
191
162
|
logger.error('Error loading object layer:', error);
|
|
@@ -193,7 +164,6 @@ const ObjectLayerEngineViewer = {
|
|
|
193
164
|
html: `Failed to load object layer: ${error.message}`,
|
|
194
165
|
status: 'error',
|
|
195
166
|
});
|
|
196
|
-
|
|
197
167
|
htmls(
|
|
198
168
|
`#${id}`,
|
|
199
169
|
html`
|
|
@@ -206,42 +176,34 @@ const ObjectLayerEngineViewer = {
|
|
|
206
176
|
`,
|
|
207
177
|
);
|
|
208
178
|
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
renderViewer: async function ({ appStore }) {
|
|
179
|
+
}
|
|
180
|
+
static async renderViewer({ appStore }) {
|
|
212
181
|
const id = 'object-layer-engine-viewer';
|
|
213
|
-
const { objectLayer, frameCounts } =
|
|
214
|
-
|
|
182
|
+
const { objectLayer, frameCounts } = ObjectLayerEngineViewer.Data;
|
|
215
183
|
if (!objectLayer || !frameCounts) return;
|
|
216
|
-
|
|
217
184
|
// Check if DOM element exists
|
|
218
185
|
if (!s(`#${id}`)) {
|
|
219
186
|
logger.warn('ObjectLayerEngineViewer DOM not ready for renderViewer');
|
|
220
187
|
return;
|
|
221
188
|
}
|
|
222
|
-
|
|
223
189
|
const itemType = objectLayer.data.item.type;
|
|
224
190
|
const itemId = objectLayer.data.item.id;
|
|
225
191
|
const itemDescription = objectLayer.data.item.description || '';
|
|
226
192
|
const itemActivable = objectLayer.data.item.activable || false;
|
|
227
|
-
|
|
228
193
|
// Get ledger data
|
|
229
194
|
const ledger = objectLayer.data.ledger || {};
|
|
230
195
|
const ledgerType = ledger.type || '';
|
|
231
196
|
const ledgerAddress = ledger.address || '';
|
|
232
|
-
|
|
233
197
|
// Get stats data
|
|
234
198
|
const stats = objectLayer.data.stats || {};
|
|
235
|
-
|
|
236
199
|
// Helper function to check if direction/mode has frames
|
|
237
200
|
const hasFrames = (direction, mode) => {
|
|
238
|
-
const numericCode =
|
|
201
|
+
const numericCode = ObjectLayerEngineViewer.getDirectionCode(direction, mode);
|
|
239
202
|
return numericCode && frameCounts[numericCode] && frameCounts[numericCode] > 0;
|
|
240
203
|
};
|
|
241
|
-
|
|
242
204
|
// Helper function to get frame count
|
|
243
205
|
const getFrameCount = (direction, mode) => {
|
|
244
|
-
const numericCode =
|
|
206
|
+
const numericCode = ObjectLayerEngineViewer.getDirectionCode(direction, mode);
|
|
245
207
|
return numericCode ? frameCounts[numericCode] || 0 : 0;
|
|
246
208
|
};
|
|
247
209
|
ThemeEvents[id] = () => {
|
|
@@ -662,7 +624,7 @@ const ObjectLayerEngineViewer = {
|
|
|
662
624
|
<div class="hide style-${id}"></div>
|
|
663
625
|
|
|
664
626
|
<div class="object-layer-viewer-container">
|
|
665
|
-
${
|
|
627
|
+
${ObjectLayerEngineViewer.Data.isGeneratingAtlas
|
|
666
628
|
? html`
|
|
667
629
|
<div
|
|
668
630
|
style="display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 500px; gap: 20px; text-align: center;"
|
|
@@ -789,7 +751,7 @@ const ObjectLayerEngineViewer = {
|
|
|
789
751
|
<span>WebP</span>
|
|
790
752
|
</button>
|
|
791
753
|
<div class="webp-canvas-container chess in" id="webp-canvas-container">
|
|
792
|
-
${!
|
|
754
|
+
${!ObjectLayerEngineViewer.Data.webp
|
|
793
755
|
? html`
|
|
794
756
|
<div class="webp-placeholder">
|
|
795
757
|
<i class="fa-solid fa-image"></i>
|
|
@@ -811,47 +773,55 @@ const ObjectLayerEngineViewer = {
|
|
|
811
773
|
<h4><i class="fa-solid fa-compass"></i> Direction</h4>
|
|
812
774
|
<div class="button-group">
|
|
813
775
|
<button
|
|
814
|
-
class="control-btn ${
|
|
776
|
+
class="control-btn ${ObjectLayerEngineViewer.Data.currentDirection === 'up' ? 'active' : ''}"
|
|
815
777
|
data-direction="up"
|
|
816
|
-
${!hasFrames('up',
|
|
778
|
+
${!hasFrames('up', ObjectLayerEngineViewer.Data.currentMode) ? 'disabled' : ''}
|
|
817
779
|
>
|
|
818
780
|
<i class="fa-solid fa-arrow-up"></i>
|
|
819
781
|
<span>Up</span>
|
|
820
|
-
${hasFrames('up',
|
|
821
|
-
? html`<span class="frame-count"
|
|
782
|
+
${hasFrames('up', ObjectLayerEngineViewer.Data.currentMode)
|
|
783
|
+
? html`<span class="frame-count"
|
|
784
|
+
>(${getFrameCount('up', ObjectLayerEngineViewer.Data.currentMode)})</span
|
|
785
|
+
>`
|
|
822
786
|
: ''}
|
|
823
787
|
</button>
|
|
824
788
|
<button
|
|
825
|
-
class="control-btn ${
|
|
789
|
+
class="control-btn ${ObjectLayerEngineViewer.Data.currentDirection === 'down' ? 'active' : ''}"
|
|
826
790
|
data-direction="down"
|
|
827
|
-
${!hasFrames('down',
|
|
791
|
+
${!hasFrames('down', ObjectLayerEngineViewer.Data.currentMode) ? 'disabled' : ''}
|
|
828
792
|
>
|
|
829
793
|
<i class="fa-solid fa-arrow-down"></i>
|
|
830
794
|
<span>Down</span>
|
|
831
|
-
${hasFrames('down',
|
|
832
|
-
? html`<span class="frame-count"
|
|
795
|
+
${hasFrames('down', ObjectLayerEngineViewer.Data.currentMode)
|
|
796
|
+
? html`<span class="frame-count"
|
|
797
|
+
>(${getFrameCount('down', ObjectLayerEngineViewer.Data.currentMode)})</span
|
|
798
|
+
>`
|
|
833
799
|
: ''}
|
|
834
800
|
</button>
|
|
835
801
|
<button
|
|
836
|
-
class="control-btn ${
|
|
802
|
+
class="control-btn ${ObjectLayerEngineViewer.Data.currentDirection === 'left' ? 'active' : ''}"
|
|
837
803
|
data-direction="left"
|
|
838
|
-
${!hasFrames('left',
|
|
804
|
+
${!hasFrames('left', ObjectLayerEngineViewer.Data.currentMode) ? 'disabled' : ''}
|
|
839
805
|
>
|
|
840
806
|
<i class="fa-solid fa-arrow-left"></i>
|
|
841
807
|
<span>Left</span>
|
|
842
|
-
${hasFrames('left',
|
|
843
|
-
? html`<span class="frame-count"
|
|
808
|
+
${hasFrames('left', ObjectLayerEngineViewer.Data.currentMode)
|
|
809
|
+
? html`<span class="frame-count"
|
|
810
|
+
>(${getFrameCount('left', ObjectLayerEngineViewer.Data.currentMode)})</span
|
|
811
|
+
>`
|
|
844
812
|
: ''}
|
|
845
813
|
</button>
|
|
846
814
|
<button
|
|
847
|
-
class="control-btn ${
|
|
815
|
+
class="control-btn ${ObjectLayerEngineViewer.Data.currentDirection === 'right' ? 'active' : ''}"
|
|
848
816
|
data-direction="right"
|
|
849
|
-
${!hasFrames('right',
|
|
817
|
+
${!hasFrames('right', ObjectLayerEngineViewer.Data.currentMode) ? 'disabled' : ''}
|
|
850
818
|
>
|
|
851
819
|
<i class="fa-solid fa-arrow-right"></i>
|
|
852
820
|
<span>Right</span>
|
|
853
|
-
${hasFrames('right',
|
|
854
|
-
? html`<span class="frame-count"
|
|
821
|
+
${hasFrames('right', ObjectLayerEngineViewer.Data.currentMode)
|
|
822
|
+
? html`<span class="frame-count"
|
|
823
|
+
>(${getFrameCount('right', ObjectLayerEngineViewer.Data.currentMode)})</span
|
|
824
|
+
>`
|
|
855
825
|
: ''}
|
|
856
826
|
</button>
|
|
857
827
|
</div>
|
|
@@ -861,28 +831,28 @@ const ObjectLayerEngineViewer = {
|
|
|
861
831
|
<h4><i class="fa-solid fa-person-running"></i> Mode</h4>
|
|
862
832
|
<div class="button-group">
|
|
863
833
|
<button
|
|
864
|
-
class="control-btn ${
|
|
834
|
+
class="control-btn ${ObjectLayerEngineViewer.Data.currentMode === 'idle' ? 'active' : ''}"
|
|
865
835
|
data-mode="idle"
|
|
866
|
-
${!hasFrames(
|
|
836
|
+
${!hasFrames(ObjectLayerEngineViewer.Data.currentDirection, 'idle') ? 'disabled' : ''}
|
|
867
837
|
>
|
|
868
838
|
<i class="fa-solid fa-user"></i>
|
|
869
839
|
<span>Idle</span>
|
|
870
|
-
${hasFrames(
|
|
840
|
+
${hasFrames(ObjectLayerEngineViewer.Data.currentDirection, 'idle')
|
|
871
841
|
? html`<span class="frame-count"
|
|
872
|
-
>(${getFrameCount(
|
|
842
|
+
>(${getFrameCount(ObjectLayerEngineViewer.Data.currentDirection, 'idle')})</span
|
|
873
843
|
>`
|
|
874
844
|
: ''}
|
|
875
845
|
</button>
|
|
876
846
|
<button
|
|
877
|
-
class="control-btn ${
|
|
847
|
+
class="control-btn ${ObjectLayerEngineViewer.Data.currentMode === 'walking' ? 'active' : ''}"
|
|
878
848
|
data-mode="walking"
|
|
879
|
-
${!hasFrames(
|
|
849
|
+
${!hasFrames(ObjectLayerEngineViewer.Data.currentDirection, 'walking') ? 'disabled' : ''}
|
|
880
850
|
>
|
|
881
851
|
<i class="fa-solid fa-person-walking"></i>
|
|
882
852
|
<span>Walking</span>
|
|
883
|
-
${hasFrames(
|
|
853
|
+
${hasFrames(ObjectLayerEngineViewer.Data.currentDirection, 'walking')
|
|
884
854
|
? html`<span class="frame-count"
|
|
885
|
-
>(${getFrameCount(
|
|
855
|
+
>(${getFrameCount(ObjectLayerEngineViewer.Data.currentDirection, 'walking')})</span
|
|
886
856
|
>`
|
|
887
857
|
: ''}
|
|
888
858
|
</button>
|
|
@@ -892,16 +862,17 @@ const ObjectLayerEngineViewer = {
|
|
|
892
862
|
<div class="control-group">
|
|
893
863
|
<h4><i class="fa-solid fa-file-image"></i> Atlas Sprite Sheet</h4>
|
|
894
864
|
<div class="button-group" style="flex-direction: column; align-items: flex-start;">
|
|
895
|
-
${
|
|
865
|
+
${ObjectLayerEngineViewer.Data.atlasSpriteSheet
|
|
896
866
|
? html`
|
|
897
867
|
<div class="atlas-preview-container">
|
|
898
868
|
${
|
|
899
|
-
|
|
869
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet.fileId
|
|
900
870
|
? html`
|
|
901
871
|
<div class="atlas-img-wrapper">
|
|
902
872
|
<img
|
|
903
|
-
src="${getProxyPath()}api/file/blob/${
|
|
904
|
-
|
|
873
|
+
src="${getProxyPath()}api/file/blob/${ObjectLayerEngineViewer.Data
|
|
874
|
+
.atlasSpriteSheet.fileId._id ||
|
|
875
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet.fileId}"
|
|
905
876
|
class="in atlas-img-preview"
|
|
906
877
|
/>
|
|
907
878
|
</div>
|
|
@@ -915,14 +886,14 @@ const ObjectLayerEngineViewer = {
|
|
|
915
886
|
<div class="atlas-metadata-grid">
|
|
916
887
|
<div>
|
|
917
888
|
<p style="padding: 2px"><strong class="item-data-key-label">ID:</strong></p>
|
|
918
|
-
<p style="padding: 2px" font-size: 12px;">${
|
|
889
|
+
<p style="padding: 2px" font-size: 12px;">${ObjectLayerEngineViewer.Data.atlasSpriteSheet._id}</p>
|
|
919
890
|
</div>
|
|
920
891
|
${
|
|
921
|
-
|
|
892
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet.cid
|
|
922
893
|
? html`<div style="grid-column: 1 / -1;">
|
|
923
894
|
<p style="padding: 2px"><strong class="item-data-key-label">IPFS CID:</strong></p>
|
|
924
895
|
<p class="ipfs-cid-value" style="padding: 2px;">
|
|
925
|
-
${
|
|
896
|
+
${ObjectLayerEngineViewer.Data.atlasSpriteSheet.cid}
|
|
926
897
|
</p>
|
|
927
898
|
</div>`
|
|
928
899
|
: ''
|
|
@@ -930,18 +901,16 @@ const ObjectLayerEngineViewer = {
|
|
|
930
901
|
<div>
|
|
931
902
|
<p style="padding: 2px"><strong class="item-data-key-label">Dimensions:</strong></p>
|
|
932
903
|
<p style="padding: 2px">
|
|
933
|
-
${
|
|
934
|
-
this.Data.atlasSpriteSheet.metadata.atlasHeight
|
|
935
|
-
}
|
|
904
|
+
${ObjectLayerEngineViewer.Data.atlasSpriteSheet.metadata.atlasWidth}x${ObjectLayerEngineViewer.Data.atlasSpriteSheet.metadata.atlasHeight}
|
|
936
905
|
</p>
|
|
937
906
|
</div>
|
|
938
907
|
<div>
|
|
939
908
|
<p style="padding: 2px"><strong class="item-data-key-label">Cell Dim:</strong></p>
|
|
940
|
-
<p style="padding: 2px">${
|
|
909
|
+
<p style="padding: 2px">${ObjectLayerEngineViewer.Data.atlasSpriteSheet.metadata.cellPixelDim}px</p>
|
|
941
910
|
</div>
|
|
942
911
|
<div>
|
|
943
912
|
<p style="padding: 2px"><strong class="item-data-key-label">Item Key:</strong></p>
|
|
944
|
-
<p style="padding: 2px">${
|
|
913
|
+
<p style="padding: 2px">${ObjectLayerEngineViewer.Data.atlasSpriteSheet.metadata.itemKey}</p>
|
|
945
914
|
</div>
|
|
946
915
|
</div>
|
|
947
916
|
</div>
|
|
@@ -994,31 +963,24 @@ const ObjectLayerEngineViewer = {
|
|
|
994
963
|
);
|
|
995
964
|
ThemeEvents[id]();
|
|
996
965
|
// Attach event listeners
|
|
997
|
-
|
|
998
|
-
|
|
966
|
+
ObjectLayerEngineViewer.attachEventListeners({ appStore });
|
|
999
967
|
// If we already have a webp loaded, display it without re-generating
|
|
1000
|
-
if (
|
|
1001
|
-
|
|
968
|
+
if (ObjectLayerEngineViewer.Data.webp) {
|
|
969
|
+
ObjectLayerEngineViewer.displayWebp();
|
|
1002
970
|
}
|
|
1003
|
-
|
|
1004
971
|
// Initialize metadata JSON editor
|
|
1005
|
-
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
const { webp, webpMetadata } = this.Data;
|
|
972
|
+
ObjectLayerEngineViewer.initMetadataJsonEditor();
|
|
973
|
+
}
|
|
974
|
+
static async displayWebp() {
|
|
975
|
+
const { webp, webpMetadata } = ObjectLayerEngineViewer.Data;
|
|
1010
976
|
if (!webp || !webpMetadata) return;
|
|
1011
|
-
|
|
1012
977
|
const { frameCount, frameDuration, currentDirection, currentMode, numericCode } = webpMetadata;
|
|
1013
|
-
|
|
1014
978
|
const container = s('#webp-canvas-container');
|
|
1015
979
|
if (!container) return;
|
|
1016
|
-
|
|
1017
980
|
// Remove one-time placeholder without destroying the rest of the container
|
|
1018
981
|
// (clearing innerHTML would also destroy #webp-loading-overlay, breaking showLoading)
|
|
1019
982
|
const placeholder = container.querySelector('.webp-placeholder');
|
|
1020
983
|
if (placeholder) placeholder.remove();
|
|
1021
|
-
|
|
1022
984
|
// Reuse the existing <img> element or create one — never nuke the container
|
|
1023
985
|
let img = container.querySelector('img');
|
|
1024
986
|
if (!img) {
|
|
@@ -1029,7 +991,6 @@ const ObjectLayerEngineViewer = {
|
|
|
1029
991
|
container.insertBefore(img, overlay || null);
|
|
1030
992
|
}
|
|
1031
993
|
img.src = webp;
|
|
1032
|
-
|
|
1033
994
|
// Update info badge in-place or create it once
|
|
1034
995
|
const displayArea = s('.webp-display-area');
|
|
1035
996
|
if (displayArea) {
|
|
@@ -1052,12 +1013,10 @@ const ObjectLayerEngineViewer = {
|
|
|
1052
1013
|
<span>${numericCode}</span>
|
|
1053
1014
|
`;
|
|
1054
1015
|
}
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
initMetadataJsonEditor: async function () {
|
|
1016
|
+
}
|
|
1017
|
+
static async initMetadataJsonEditor() {
|
|
1058
1018
|
const container = s('#metadata-json-editor-container');
|
|
1059
1019
|
if (!container) return;
|
|
1060
|
-
|
|
1061
1020
|
// Ensure vanilla-jsoneditor dark theme CSS is loaded
|
|
1062
1021
|
if (!s('.jse-dark-theme-link')) {
|
|
1063
1022
|
append(
|
|
@@ -1070,21 +1029,17 @@ const ObjectLayerEngineViewer = {
|
|
|
1070
1029
|
/>`,
|
|
1071
1030
|
);
|
|
1072
1031
|
}
|
|
1073
|
-
|
|
1074
1032
|
// Destroy previous instance if any
|
|
1075
|
-
if (
|
|
1076
|
-
|
|
1077
|
-
|
|
1033
|
+
if (ObjectLayerEngineViewer.Data.metadataJsonEditor) {
|
|
1034
|
+
ObjectLayerEngineViewer.Data.metadataJsonEditor.destroy();
|
|
1035
|
+
ObjectLayerEngineViewer.Data.metadataJsonEditor = null;
|
|
1078
1036
|
}
|
|
1079
|
-
|
|
1080
|
-
const objectLayerId = this.Data.objectLayer?._id;
|
|
1037
|
+
const objectLayerId = ObjectLayerEngineViewer.Data.objectLayer?._id;
|
|
1081
1038
|
if (!objectLayerId) return;
|
|
1082
|
-
|
|
1083
1039
|
try {
|
|
1084
1040
|
const response = await ObjectLayerService.getMetadata({ id: objectLayerId });
|
|
1085
1041
|
const metadataContent = response.status === 'success' && response.data ? response.data : response;
|
|
1086
|
-
|
|
1087
|
-
this.Data.metadataJsonEditor = createJSONEditor({
|
|
1042
|
+
ObjectLayerEngineViewer.Data.metadataJsonEditor = createJSONEditor({
|
|
1088
1043
|
target: container,
|
|
1089
1044
|
props: {
|
|
1090
1045
|
content: { json: metadataContent },
|
|
@@ -1095,13 +1050,11 @@ const ObjectLayerEngineViewer = {
|
|
|
1095
1050
|
mode: 'tree',
|
|
1096
1051
|
},
|
|
1097
1052
|
});
|
|
1098
|
-
|
|
1099
1053
|
// Apply dark theme class based on current theme
|
|
1100
|
-
|
|
1101
|
-
|
|
1054
|
+
ObjectLayerEngineViewer._applyJsonEditorTheme();
|
|
1102
1055
|
// Register theme event to toggle dark/light on the JSON editor
|
|
1103
1056
|
ThemeEvents['metadata-json-editor-theme'] = () => {
|
|
1104
|
-
|
|
1057
|
+
ObjectLayerEngineViewer._applyJsonEditorTheme();
|
|
1105
1058
|
};
|
|
1106
1059
|
} catch (err) {
|
|
1107
1060
|
logger.warn('Failed to initialize metadata JSON editor:', err);
|
|
@@ -1109,9 +1062,8 @@ const ObjectLayerEngineViewer = {
|
|
|
1109
1062
|
Failed to load metadata JSON
|
|
1110
1063
|
</div>`;
|
|
1111
1064
|
}
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
_applyJsonEditorTheme: function () {
|
|
1065
|
+
}
|
|
1066
|
+
static _applyJsonEditorTheme() {
|
|
1115
1067
|
const container = s('#metadata-json-editor-container');
|
|
1116
1068
|
if (!container) return;
|
|
1117
1069
|
if (darkTheme) {
|
|
@@ -1119,14 +1071,11 @@ const ObjectLayerEngineViewer = {
|
|
|
1119
1071
|
} else {
|
|
1120
1072
|
container.classList.remove('jse-theme-dark');
|
|
1121
1073
|
}
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
const objectLayerId = this.Data.objectLayer?._id;
|
|
1074
|
+
}
|
|
1075
|
+
static async deleteObjectLayer({ appStore } = {}) {
|
|
1076
|
+
const objectLayerId = ObjectLayerEngineViewer.Data.objectLayer?._id;
|
|
1126
1077
|
if (!objectLayerId) return;
|
|
1127
|
-
|
|
1128
|
-
const itemId = this.Data.objectLayer?.data?.item?.id || objectLayerId;
|
|
1129
|
-
|
|
1078
|
+
const itemId = ObjectLayerEngineViewer.Data.objectLayer?.data?.item?.id || objectLayerId;
|
|
1130
1079
|
const confirmResult = await Modal.RenderConfirm({
|
|
1131
1080
|
id: 'delete-object-layer-confirm',
|
|
1132
1081
|
html: async () => html`
|
|
@@ -1139,9 +1088,7 @@ const ObjectLayerEngineViewer = {
|
|
|
1139
1088
|
</div>
|
|
1140
1089
|
`,
|
|
1141
1090
|
});
|
|
1142
|
-
|
|
1143
1091
|
if (confirmResult.status !== 'confirm') return;
|
|
1144
|
-
|
|
1145
1092
|
try {
|
|
1146
1093
|
const result = await ObjectLayerService.delete({ id: objectLayerId });
|
|
1147
1094
|
if (result.status === 'success') {
|
|
@@ -1149,20 +1096,18 @@ const ObjectLayerEngineViewer = {
|
|
|
1149
1096
|
html: `Object layer "${itemId}" deleted successfully`,
|
|
1150
1097
|
status: 'success',
|
|
1151
1098
|
});
|
|
1152
|
-
|
|
1153
1099
|
// Clean up JSON editor and its theme event
|
|
1154
|
-
if (
|
|
1155
|
-
|
|
1156
|
-
|
|
1100
|
+
if (ObjectLayerEngineViewer.Data.metadataJsonEditor) {
|
|
1101
|
+
ObjectLayerEngineViewer.Data.metadataJsonEditor.destroy();
|
|
1102
|
+
ObjectLayerEngineViewer.Data.metadataJsonEditor = null;
|
|
1157
1103
|
}
|
|
1158
1104
|
delete ThemeEvents['metadata-json-editor-theme'];
|
|
1159
|
-
|
|
1160
1105
|
// Navigate back to list
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1106
|
+
ObjectLayerEngineViewer.Data.currentObjectId = undefined;
|
|
1107
|
+
ObjectLayerEngineViewer.Data.objectLayer = null;
|
|
1108
|
+
ObjectLayerEngineViewer.Data.webp = null;
|
|
1109
|
+
ObjectLayerEngineViewer.Data.webpMetadata = null;
|
|
1110
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet = null;
|
|
1166
1111
|
setQueryParams({ id: null }, { replace: false });
|
|
1167
1112
|
} else {
|
|
1168
1113
|
throw new Error(result.message || 'Failed to delete object layer');
|
|
@@ -1174,109 +1119,100 @@ const ObjectLayerEngineViewer = {
|
|
|
1174
1119
|
status: 'error',
|
|
1175
1120
|
});
|
|
1176
1121
|
}
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
attachEventListeners: function ({ appStore }) {
|
|
1122
|
+
}
|
|
1123
|
+
static attachEventListeners({ appStore }) {
|
|
1180
1124
|
// Direction buttons
|
|
1181
1125
|
const directionButtons = document.querySelectorAll('[data-direction]');
|
|
1182
1126
|
directionButtons.forEach((btn) => {
|
|
1183
1127
|
btn.addEventListener('click', async (e) => {
|
|
1184
1128
|
if (e.currentTarget.disabled) return;
|
|
1185
1129
|
const direction = e.currentTarget.getAttribute('data-direction');
|
|
1186
|
-
if (direction !==
|
|
1187
|
-
|
|
1130
|
+
if (direction !== ObjectLayerEngineViewer.Data.currentDirection) {
|
|
1131
|
+
ObjectLayerEngineViewer.Data.currentDirection = direction;
|
|
1188
1132
|
// Update button active states without re-rendering the full viewer (prevents flicker)
|
|
1189
|
-
|
|
1190
|
-
await
|
|
1133
|
+
ObjectLayerEngineViewer._updateControlsState();
|
|
1134
|
+
await ObjectLayerEngineViewer.generateWebp();
|
|
1191
1135
|
}
|
|
1192
1136
|
});
|
|
1193
1137
|
});
|
|
1194
|
-
|
|
1195
1138
|
// Mode buttons
|
|
1196
1139
|
const modeButtons = document.querySelectorAll('[data-mode]');
|
|
1197
1140
|
modeButtons.forEach((btn) => {
|
|
1198
1141
|
btn.addEventListener('click', async (e) => {
|
|
1199
1142
|
if (e.currentTarget.disabled) return;
|
|
1200
1143
|
const mode = e.currentTarget.getAttribute('data-mode');
|
|
1201
|
-
if (mode !==
|
|
1202
|
-
|
|
1144
|
+
if (mode !== ObjectLayerEngineViewer.Data.currentMode) {
|
|
1145
|
+
ObjectLayerEngineViewer.Data.currentMode = mode;
|
|
1203
1146
|
// Update button active states without re-rendering the full viewer (prevents flicker)
|
|
1204
|
-
|
|
1205
|
-
await
|
|
1147
|
+
ObjectLayerEngineViewer._updateControlsState();
|
|
1148
|
+
await ObjectLayerEngineViewer.generateWebp();
|
|
1206
1149
|
}
|
|
1207
1150
|
});
|
|
1208
1151
|
});
|
|
1209
|
-
|
|
1210
1152
|
// Download button
|
|
1211
1153
|
const downloadBtn = s('#download-webp-btn');
|
|
1212
1154
|
if (downloadBtn) {
|
|
1213
1155
|
downloadBtn.addEventListener('click', () => {
|
|
1214
|
-
|
|
1156
|
+
ObjectLayerEngineViewer.downloadWebp();
|
|
1215
1157
|
});
|
|
1216
1158
|
}
|
|
1217
|
-
|
|
1218
1159
|
// Return to list button
|
|
1219
1160
|
const listBtn = s('#return-to-list-btn');
|
|
1220
1161
|
if (listBtn) {
|
|
1221
1162
|
listBtn.addEventListener('click', async () => {
|
|
1222
1163
|
// Clear object data and reset state
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1164
|
+
ObjectLayerEngineViewer.Data.webp = null;
|
|
1165
|
+
ObjectLayerEngineViewer.Data.webpMetadata = null;
|
|
1166
|
+
ObjectLayerEngineViewer.Data.objectLayer = null;
|
|
1167
|
+
ObjectLayerEngineViewer.Data.frameCounts = null;
|
|
1228
1168
|
// Set currentObjectId to null BEFORE setQueryParams so the
|
|
1229
1169
|
// listenQueryParamsChange listener sees the id already matches
|
|
1230
1170
|
// and skips calling Reload (avoids double-render race condition)
|
|
1231
|
-
|
|
1232
|
-
|
|
1171
|
+
ObjectLayerEngineViewer.Data.currentObjectId = null;
|
|
1233
1172
|
// Update the URL to remove the id parameter
|
|
1234
1173
|
setQueryParams({ id: null }, { replace: false });
|
|
1235
|
-
|
|
1236
1174
|
// Directly render the list view instead of relying on the
|
|
1237
1175
|
// listener → Reload → renderEmpty chain which can silently
|
|
1238
1176
|
// fail when the URL was already clean or currentObjectId
|
|
1239
1177
|
// was already null
|
|
1240
|
-
await
|
|
1178
|
+
await ObjectLayerEngineViewer.renderEmpty({ appStore });
|
|
1241
1179
|
});
|
|
1242
1180
|
}
|
|
1243
|
-
|
|
1244
1181
|
// Edit button
|
|
1245
1182
|
const editBtn = s('#edit-object-layer-btn');
|
|
1246
1183
|
if (editBtn) {
|
|
1247
1184
|
editBtn.addEventListener('click', () => {
|
|
1248
|
-
|
|
1185
|
+
ObjectLayerEngineViewer.toEngine();
|
|
1249
1186
|
});
|
|
1250
1187
|
}
|
|
1251
|
-
|
|
1252
1188
|
// Delete button
|
|
1253
1189
|
const deleteBtn = s('#delete-object-layer-btn');
|
|
1254
1190
|
if (deleteBtn) {
|
|
1255
1191
|
deleteBtn.addEventListener('click', async () => {
|
|
1256
|
-
await
|
|
1192
|
+
await ObjectLayerEngineViewer.deleteObjectLayer({ appStore });
|
|
1257
1193
|
});
|
|
1258
1194
|
}
|
|
1259
|
-
|
|
1260
1195
|
// Atlas buttons
|
|
1261
1196
|
if (s('#generate-atlas-btn')) {
|
|
1262
1197
|
EventsUI.onClick('#generate-atlas-btn', async () => {
|
|
1263
|
-
await
|
|
1198
|
+
await ObjectLayerEngineViewer.generateAtlas({ appStore });
|
|
1264
1199
|
});
|
|
1265
1200
|
}
|
|
1266
|
-
|
|
1267
1201
|
const removeAtlasBtn = s('#remove-atlas-btn');
|
|
1268
1202
|
if (removeAtlasBtn) {
|
|
1269
1203
|
removeAtlasBtn.addEventListener('click', async () => {
|
|
1270
|
-
await
|
|
1204
|
+
await ObjectLayerEngineViewer.removeAtlas({ appStore });
|
|
1271
1205
|
});
|
|
1272
1206
|
}
|
|
1273
|
-
|
|
1274
1207
|
const downloadAtlasPngBtn = s('#download-atlas-png-btn');
|
|
1275
1208
|
if (downloadAtlasPngBtn) {
|
|
1276
1209
|
downloadAtlasPngBtn.addEventListener('click', () => {
|
|
1277
1210
|
const fileId =
|
|
1278
|
-
|
|
1279
|
-
|
|
1211
|
+
ObjectLayerEngineViewer.Data &&
|
|
1212
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet &&
|
|
1213
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet.fileId
|
|
1214
|
+
? ObjectLayerEngineViewer.Data.atlasSpriteSheet.fileId._id ||
|
|
1215
|
+
ObjectLayerEngineViewer.Data.atlasSpriteSheet.fileId
|
|
1280
1216
|
: null;
|
|
1281
1217
|
if (!fileId) {
|
|
1282
1218
|
NotificationManager.Push({
|
|
@@ -1288,47 +1224,43 @@ const ObjectLayerEngineViewer = {
|
|
|
1288
1224
|
const url = `${getProxyPath()}api/file/blob/${fileId}`;
|
|
1289
1225
|
const a = document.createElement('a');
|
|
1290
1226
|
a.href = url;
|
|
1291
|
-
a.download = `${
|
|
1227
|
+
a.download = `${ObjectLayerEngineViewer.Data.atlasSpriteSheet.metadata.itemKey}-atlas.png`;
|
|
1292
1228
|
document.body.appendChild(a);
|
|
1293
1229
|
a.click();
|
|
1294
1230
|
document.body.removeChild(a);
|
|
1295
1231
|
});
|
|
1296
1232
|
}
|
|
1297
|
-
|
|
1298
1233
|
const downloadAtlasJsonBtn = s('#download-atlas-json-btn');
|
|
1299
1234
|
if (downloadAtlasJsonBtn) {
|
|
1300
1235
|
downloadAtlasJsonBtn.addEventListener('click', () => {
|
|
1301
|
-
const blob = new Blob([JSON.stringify(
|
|
1236
|
+
const blob = new Blob([JSON.stringify(ObjectLayerEngineViewer.Data.atlasSpriteSheet.metadata, null, 2)], {
|
|
1302
1237
|
type: 'application/json',
|
|
1303
1238
|
});
|
|
1304
1239
|
const url = URL.createObjectURL(blob);
|
|
1305
1240
|
const a = document.createElement('a');
|
|
1306
1241
|
a.href = url;
|
|
1307
|
-
a.download = `${
|
|
1242
|
+
a.download = `${ObjectLayerEngineViewer.Data.atlasSpriteSheet.metadata.itemKey}-atlas-metadata.json`;
|
|
1308
1243
|
document.body.appendChild(a);
|
|
1309
1244
|
a.click();
|
|
1310
1245
|
document.body.removeChild(a);
|
|
1311
1246
|
URL.revokeObjectURL(url);
|
|
1312
1247
|
});
|
|
1313
1248
|
}
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
await this.renderViewer({ appStore });
|
|
1320
|
-
|
|
1249
|
+
}
|
|
1250
|
+
static async generateAtlas({ appStore } = {}) {
|
|
1251
|
+
const objectLayerId = ObjectLayerEngineViewer.Data.objectLayer._id;
|
|
1252
|
+
ObjectLayerEngineViewer.Data.isGeneratingAtlas = true;
|
|
1253
|
+
await ObjectLayerEngineViewer.renderViewer({ appStore });
|
|
1321
1254
|
try {
|
|
1322
1255
|
const { status, data, message } = await AtlasSpriteSheetService.generateAtlas({ id: objectLayerId });
|
|
1323
|
-
|
|
1324
1256
|
if (status === 'success') {
|
|
1325
1257
|
NotificationManager.Push({
|
|
1326
1258
|
html: 'Atlas sprite sheet generated successfully',
|
|
1327
1259
|
status: 'success',
|
|
1328
1260
|
});
|
|
1329
1261
|
// Reset generating flag before reload so renderViewer shows updated content
|
|
1330
|
-
|
|
1331
|
-
await
|
|
1262
|
+
ObjectLayerEngineViewer.Data.isGeneratingAtlas = false;
|
|
1263
|
+
await ObjectLayerEngineViewer.Reload({ appStore, force: true, skipWebp: true });
|
|
1332
1264
|
return;
|
|
1333
1265
|
} else {
|
|
1334
1266
|
throw new Error(message || 'Failed to generate atlas');
|
|
@@ -1340,14 +1272,13 @@ const ObjectLayerEngineViewer = {
|
|
|
1340
1272
|
status: 'error',
|
|
1341
1273
|
});
|
|
1342
1274
|
} finally {
|
|
1343
|
-
if (
|
|
1344
|
-
|
|
1345
|
-
await
|
|
1275
|
+
if (ObjectLayerEngineViewer.Data.isGeneratingAtlas) {
|
|
1276
|
+
ObjectLayerEngineViewer.Data.isGeneratingAtlas = false;
|
|
1277
|
+
await ObjectLayerEngineViewer.renderViewer({ appStore });
|
|
1346
1278
|
}
|
|
1347
1279
|
}
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
removeAtlas: async function ({ appStore } = {}) {
|
|
1280
|
+
}
|
|
1281
|
+
static async removeAtlas({ appStore } = {}) {
|
|
1351
1282
|
const confirmResult = await Modal.RenderConfirm({
|
|
1352
1283
|
id: 'remove-atlas-confirm',
|
|
1353
1284
|
html: async () => html`
|
|
@@ -1356,26 +1287,22 @@ const ObjectLayerEngineViewer = {
|
|
|
1356
1287
|
</div>
|
|
1357
1288
|
`,
|
|
1358
1289
|
});
|
|
1359
|
-
|
|
1360
1290
|
if (confirmResult.status !== 'confirm') {
|
|
1361
1291
|
return;
|
|
1362
1292
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
await this.renderViewer({ appStore });
|
|
1367
|
-
|
|
1293
|
+
const objectLayerId = ObjectLayerEngineViewer.Data.objectLayer._id;
|
|
1294
|
+
ObjectLayerEngineViewer.Data.isGeneratingAtlas = true;
|
|
1295
|
+
await ObjectLayerEngineViewer.renderViewer({ appStore });
|
|
1368
1296
|
try {
|
|
1369
1297
|
const { status, message } = await AtlasSpriteSheetService.deleteByObjectLayerId({ id: objectLayerId });
|
|
1370
|
-
|
|
1371
1298
|
if (status === 'success') {
|
|
1372
1299
|
NotificationManager.Push({
|
|
1373
1300
|
html: 'Atlas sprite sheet removed successfully',
|
|
1374
1301
|
status: 'success',
|
|
1375
1302
|
});
|
|
1376
1303
|
// Reset generating flag before reload so renderViewer shows updated content
|
|
1377
|
-
|
|
1378
|
-
await
|
|
1304
|
+
ObjectLayerEngineViewer.Data.isGeneratingAtlas = false;
|
|
1305
|
+
await ObjectLayerEngineViewer.Reload({ appStore, force: true, skipWebp: true });
|
|
1379
1306
|
return;
|
|
1380
1307
|
} else {
|
|
1381
1308
|
throw new Error(message || 'Failed to remove atlas');
|
|
@@ -1387,21 +1314,18 @@ const ObjectLayerEngineViewer = {
|
|
|
1387
1314
|
status: 'error',
|
|
1388
1315
|
});
|
|
1389
1316
|
} finally {
|
|
1390
|
-
if (
|
|
1391
|
-
|
|
1392
|
-
await
|
|
1317
|
+
if (ObjectLayerEngineViewer.Data.isGeneratingAtlas) {
|
|
1318
|
+
ObjectLayerEngineViewer.Data.isGeneratingAtlas = false;
|
|
1319
|
+
await ObjectLayerEngineViewer.renderViewer({ appStore });
|
|
1393
1320
|
}
|
|
1394
1321
|
}
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
const { objectLayer, frameCounts, currentDirection, currentMode } = this.Data;
|
|
1322
|
+
}
|
|
1323
|
+
static async generateWebp() {
|
|
1324
|
+
if (ObjectLayerEngineViewer.Data.isGenerating) return;
|
|
1325
|
+
const { objectLayer, frameCounts, currentDirection, currentMode } = ObjectLayerEngineViewer.Data;
|
|
1401
1326
|
if (!objectLayer || !frameCounts) return;
|
|
1402
|
-
|
|
1403
1327
|
// Get numeric direction code
|
|
1404
|
-
const numericCode =
|
|
1328
|
+
const numericCode = ObjectLayerEngineViewer.getDirectionCode(currentDirection, currentMode);
|
|
1405
1329
|
if (!numericCode) {
|
|
1406
1330
|
NotificationManager.Push({
|
|
1407
1331
|
html: `Invalid direction/mode combination: ${currentDirection} ${currentMode}`,
|
|
@@ -1409,9 +1333,7 @@ const ObjectLayerEngineViewer = {
|
|
|
1409
1333
|
});
|
|
1410
1334
|
return;
|
|
1411
1335
|
}
|
|
1412
|
-
|
|
1413
1336
|
const frameCount = frameCounts[numericCode];
|
|
1414
|
-
|
|
1415
1337
|
if (!frameCount || frameCount === 0) {
|
|
1416
1338
|
NotificationManager.Push({
|
|
1417
1339
|
html: `No frames available for ${currentDirection} ${currentMode}`,
|
|
@@ -1419,13 +1341,11 @@ const ObjectLayerEngineViewer = {
|
|
|
1419
1341
|
});
|
|
1420
1342
|
return;
|
|
1421
1343
|
}
|
|
1422
|
-
|
|
1423
1344
|
const itemType = objectLayer.data.item.type;
|
|
1424
1345
|
const itemId = objectLayer.data.item.id;
|
|
1425
1346
|
const frameDuration = objectLayer.objectLayerRenderFramesId?.frame_duration || 100;
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
this.showLoading(true, 'Generating WebP...');
|
|
1347
|
+
ObjectLayerEngineViewer.Data.isGenerating = true;
|
|
1348
|
+
ObjectLayerEngineViewer.showLoading(true, 'Generating WebP...');
|
|
1429
1349
|
try {
|
|
1430
1350
|
// Call the WebP generation API endpoint
|
|
1431
1351
|
const { status, data } = await ObjectLayerService.generateWebp({
|
|
@@ -1433,21 +1353,18 @@ const ObjectLayerEngineViewer = {
|
|
|
1433
1353
|
itemId,
|
|
1434
1354
|
directionCode: numericCode,
|
|
1435
1355
|
});
|
|
1436
|
-
|
|
1437
1356
|
if (status === 'success' && data) {
|
|
1438
1357
|
// Store the blob URL and metadata
|
|
1439
|
-
|
|
1440
|
-
|
|
1358
|
+
ObjectLayerEngineViewer.Data.webp = data;
|
|
1359
|
+
ObjectLayerEngineViewer.Data.webpMetadata = {
|
|
1441
1360
|
frameCount,
|
|
1442
1361
|
frameDuration,
|
|
1443
1362
|
currentDirection,
|
|
1444
1363
|
currentMode,
|
|
1445
1364
|
numericCode,
|
|
1446
1365
|
};
|
|
1447
|
-
|
|
1448
1366
|
// Display the WebP in the viewer
|
|
1449
|
-
await
|
|
1450
|
-
|
|
1367
|
+
await ObjectLayerEngineViewer.displayWebp();
|
|
1451
1368
|
// NotificationManager.Push({
|
|
1452
1369
|
// html: `WebP generated successfully (${frameCount} frames, ${frameDuration}ms duration)`,
|
|
1453
1370
|
// status: 'success',
|
|
@@ -1455,36 +1372,33 @@ const ObjectLayerEngineViewer = {
|
|
|
1455
1372
|
} else {
|
|
1456
1373
|
throw new Error('Failed to generate WebP');
|
|
1457
1374
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
this.showLoading(false);
|
|
1375
|
+
ObjectLayerEngineViewer.Data.isGenerating = false;
|
|
1376
|
+
ObjectLayerEngineViewer.showLoading(false);
|
|
1461
1377
|
} catch (error) {
|
|
1462
1378
|
logger.error('Error generating WebP:', error);
|
|
1463
1379
|
NotificationManager.Push({
|
|
1464
1380
|
html: `Failed to generate WebP: ${error.message}`,
|
|
1465
1381
|
status: 'error',
|
|
1466
1382
|
});
|
|
1467
|
-
|
|
1468
|
-
|
|
1383
|
+
ObjectLayerEngineViewer.Data.isGenerating = false;
|
|
1384
|
+
ObjectLayerEngineViewer.showLoading(false);
|
|
1469
1385
|
}
|
|
1470
|
-
}
|
|
1471
|
-
|
|
1386
|
+
}
|
|
1472
1387
|
/**
|
|
1473
1388
|
* Updates direction/mode button active states and disabled flags in-place,
|
|
1474
1389
|
* without re-rendering the viewer. Prevents layout flicker when switching
|
|
1475
1390
|
* direction or mode while the WebP canvas and surrounding structure stay intact.
|
|
1476
1391
|
*/
|
|
1477
|
-
_updateControlsState
|
|
1478
|
-
const { currentDirection, currentMode, frameCounts } =
|
|
1392
|
+
static _updateControlsState() {
|
|
1393
|
+
const { currentDirection, currentMode, frameCounts } = ObjectLayerEngineViewer.Data;
|
|
1479
1394
|
const hasFrames = (direction, mode) => {
|
|
1480
|
-
const code =
|
|
1395
|
+
const code = ObjectLayerEngineViewer.getDirectionCode(direction, mode);
|
|
1481
1396
|
return !!(code && frameCounts && frameCounts[code] && frameCounts[code] > 0);
|
|
1482
1397
|
};
|
|
1483
1398
|
const getFrameCount = (direction, mode) => {
|
|
1484
|
-
const code =
|
|
1399
|
+
const code = ObjectLayerEngineViewer.getDirectionCode(direction, mode);
|
|
1485
1400
|
return code ? (frameCounts && frameCounts[code]) || 0 : 0;
|
|
1486
1401
|
};
|
|
1487
|
-
|
|
1488
1402
|
document.querySelectorAll('[data-direction]').forEach((btn) => {
|
|
1489
1403
|
const d = btn.getAttribute('data-direction');
|
|
1490
1404
|
btn.classList.toggle('active', d === currentDirection);
|
|
@@ -1493,7 +1407,6 @@ const ObjectLayerEngineViewer = {
|
|
|
1493
1407
|
const countEl = btn.querySelector('.frame-count');
|
|
1494
1408
|
if (countEl) countEl.textContent = hasFr ? `(${getFrameCount(d, currentMode)})` : '';
|
|
1495
1409
|
});
|
|
1496
|
-
|
|
1497
1410
|
document.querySelectorAll('[data-mode]').forEach((btn) => {
|
|
1498
1411
|
const m = btn.getAttribute('data-mode');
|
|
1499
1412
|
btn.classList.toggle('active', m === currentMode);
|
|
@@ -1502,9 +1415,8 @@ const ObjectLayerEngineViewer = {
|
|
|
1502
1415
|
const countEl = btn.querySelector('.frame-count');
|
|
1503
1416
|
if (countEl) countEl.textContent = hasFr ? `(${getFrameCount(currentDirection, m)})` : '';
|
|
1504
1417
|
});
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
showLoading: function (show, message = 'Generating WebP...') {
|
|
1418
|
+
}
|
|
1419
|
+
static showLoading(show, message = 'Generating WebP...') {
|
|
1508
1420
|
const overlay = s('#webp-loading-overlay');
|
|
1509
1421
|
if (overlay) {
|
|
1510
1422
|
overlay.style.display = show ? 'flex' : 'none';
|
|
@@ -1513,90 +1425,76 @@ const ObjectLayerEngineViewer = {
|
|
|
1513
1425
|
loadingText.textContent = message;
|
|
1514
1426
|
}
|
|
1515
1427
|
}
|
|
1516
|
-
|
|
1517
1428
|
const downloadBtn = s('#download-webp-btn');
|
|
1518
1429
|
if (downloadBtn) {
|
|
1519
1430
|
downloadBtn.disabled = show;
|
|
1520
1431
|
}
|
|
1521
|
-
|
|
1522
1432
|
// Keep existing info badge visible during loading (removes the layout-shift flicker)
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
if (!this.Data.webp) {
|
|
1433
|
+
}
|
|
1434
|
+
static downloadWebp() {
|
|
1435
|
+
if (!ObjectLayerEngineViewer.Data.webp) {
|
|
1527
1436
|
NotificationManager.Push({
|
|
1528
1437
|
html: 'No WebP available to download',
|
|
1529
1438
|
status: 'warning',
|
|
1530
1439
|
});
|
|
1531
1440
|
return;
|
|
1532
1441
|
}
|
|
1533
|
-
|
|
1534
|
-
const
|
|
1535
|
-
const numericCode = this.getDirectionCode(currentDirection, currentMode);
|
|
1442
|
+
const { objectLayer, currentDirection, currentMode } = ObjectLayerEngineViewer.Data;
|
|
1443
|
+
const numericCode = ObjectLayerEngineViewer.getDirectionCode(currentDirection, currentMode);
|
|
1536
1444
|
const filename = `${objectLayer.data.item.id}_${currentDirection}_${currentMode}_${numericCode}.webp`;
|
|
1537
|
-
|
|
1538
1445
|
// Create a temporary anchor element to trigger download
|
|
1539
1446
|
const a = document.createElement('a');
|
|
1540
|
-
a.href =
|
|
1447
|
+
a.href = ObjectLayerEngineViewer.Data.webp;
|
|
1541
1448
|
a.download = filename;
|
|
1542
1449
|
document.body.appendChild(a);
|
|
1543
1450
|
a.click();
|
|
1544
1451
|
document.body.removeChild(a);
|
|
1545
|
-
|
|
1546
1452
|
NotificationManager.Push({
|
|
1547
1453
|
html: `WebP downloaded: ${filename}`,
|
|
1548
1454
|
status: 'success',
|
|
1549
1455
|
});
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
const { objectLayer } = this.Data;
|
|
1456
|
+
}
|
|
1457
|
+
static toEngine() {
|
|
1458
|
+
const { objectLayer } = ObjectLayerEngineViewer.Data;
|
|
1554
1459
|
if (!objectLayer || !objectLayer._id) return;
|
|
1555
|
-
|
|
1556
1460
|
// Navigate to editor route first
|
|
1557
1461
|
setPath(`${getProxyPath()}object-layer-engine`);
|
|
1558
1462
|
// Then add query param without replacing history
|
|
1559
1463
|
setQueryParams({ id: objectLayer._id }, { replace: true });
|
|
1560
|
-
|
|
1561
1464
|
if (s(`.modal-object-layer-engine`)) {
|
|
1562
1465
|
ObjectLayerEngineModal.Reload();
|
|
1563
1466
|
} else {
|
|
1564
1467
|
s(`.main-btn-object-layer-engine`)?.click();
|
|
1565
1468
|
}
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
Reload: async function (options = {}) {
|
|
1469
|
+
}
|
|
1470
|
+
static async Reload(options = {}) {
|
|
1569
1471
|
const { appStore, force = false, skipWebp = false } = options;
|
|
1570
1472
|
const queryParams = getQueryParams();
|
|
1571
1473
|
const objectId = queryParams.id || null;
|
|
1572
|
-
|
|
1573
1474
|
// Only reload if object id actually changed (same logic as listener) or forced
|
|
1574
|
-
if (objectId !==
|
|
1575
|
-
if (objectId !==
|
|
1576
|
-
|
|
1577
|
-
|
|
1475
|
+
if (objectId !== ObjectLayerEngineViewer.Data.currentObjectId || force) {
|
|
1476
|
+
if (objectId !== ObjectLayerEngineViewer.Data.currentObjectId && !skipWebp) {
|
|
1477
|
+
ObjectLayerEngineViewer.Data.webp = null;
|
|
1478
|
+
ObjectLayerEngineViewer.Data.webpMetadata = null;
|
|
1578
1479
|
}
|
|
1579
|
-
|
|
1580
|
-
|
|
1480
|
+
ObjectLayerEngineViewer.Data.currentObjectId = objectId;
|
|
1581
1481
|
if (objectId) {
|
|
1582
|
-
await
|
|
1482
|
+
await ObjectLayerEngineViewer.loadObjectLayer(objectId, appStore, { skipWebp });
|
|
1583
1483
|
} else {
|
|
1584
|
-
await
|
|
1484
|
+
await ObjectLayerEngineViewer.renderEmpty({ appStore });
|
|
1585
1485
|
}
|
|
1586
|
-
} else if (!objectId && (
|
|
1486
|
+
} else if (!objectId && (ObjectLayerEngineViewer.Data.currentObjectId === null || force)) {
|
|
1587
1487
|
// Special case: if we're already in empty state but DOM might have been reset
|
|
1588
1488
|
// (e.g., modal reopened), force render the table if DOM is missing
|
|
1589
1489
|
const id = 'object-layer-engine-viewer';
|
|
1590
1490
|
const idModal = 'modal-object-layer-engine-viewer';
|
|
1591
1491
|
const gridId = `object-layer-engine-management-grid-${idModal}`;
|
|
1592
1492
|
const gridDomExists = s(`.${gridId}`);
|
|
1593
|
-
|
|
1594
1493
|
if (!gridDomExists) {
|
|
1595
1494
|
// DOM was reset (e.g., modal HTML reloaded), re-render the table
|
|
1596
|
-
await
|
|
1495
|
+
await ObjectLayerEngineViewer.renderEmpty({ appStore });
|
|
1597
1496
|
}
|
|
1598
1497
|
}
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1602
1500
|
export { ObjectLayerEngineViewer };
|