auvrynt 1.0.2 → 1.0.5
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/LICENSE +21 -21
- package/README.md +366 -233
- package/addons/auvrynt_bridge/auvrynt_bridge.gd +500 -0
- package/addons/auvrynt_bridge/plugin.cfg +7 -0
- package/bin/auvrynt-launcher.cjs +77 -0
- package/dist/artifact-registry.js +1 -0
- package/dist/aseprite-tools.js +1 -0
- package/dist/auth/connection-registry.js +145 -0
- package/dist/auth/connection-status.js +176 -0
- package/dist/auth/oauth-provider.js +617 -0
- package/dist/auth/room-registry.js +131 -0
- package/dist/auth/session-registry.js +531 -0
- package/dist/background-lifecycle.js +1 -0
- package/dist/blender-client.js +1 -109
- package/dist/blender-tools.js +1 -930
- package/dist/browser-stability.js +1 -0
- package/dist/cli/commands/help-command.js +10 -0
- package/dist/cli/commands/init-command.js +190 -0
- package/dist/cli/commands/integration-commands.js +88 -0
- package/dist/cli/commands/serve-command.js +83 -0
- package/dist/cli/commands/setup-command.js +81 -0
- package/dist/cli/commands/status-commands.js +166 -0
- package/dist/cli/commands/tunnel-command.js +127 -0
- package/dist/cli/commands/user-config-commands.js +105 -0
- package/dist/cli/dashboard-actions.js +516 -0
- package/dist/cli/dashboard-native-actions.js +282 -0
- package/dist/cli/foreground-server.js +270 -0
- package/dist/cli/instance-control.js +21 -0
- package/dist/cli/instance-lock.js +123 -0
- package/dist/cli/integration-bootstrap.js +206 -0
- package/dist/cli/lifecycle-manager.js +493 -0
- package/dist/cli/runtime-support.js +74 -0
- package/dist/cli/serena-detected-default.js +27 -0
- package/dist/cli/tunnel-health-monitor.js +182 -0
- package/dist/cli.js +82 -739
- package/dist/config.js +1 -243
- package/dist/connection-registry.js +1 -73
- package/dist/connection-status.js +1 -139
- package/dist/control-retry.js +1 -0
- package/dist/crash-recovery.js +1 -0
- package/dist/db/client.js +16 -3
- package/dist/db/schema.js +30 -0
- package/dist/dotnet-tools.js +1 -223
- package/dist/git-worktrees.js +1 -134
- package/dist/git.js +1 -41
- package/dist/godot-animation-tilemap.js +1 -82
- package/dist/godot-csharp-build.js +1 -93
- package/dist/godot-csharp-project.js +1 -157
- package/dist/godot-csharp-runner.js +1 -146
- package/dist/godot-csharp-semantic.js +1 -161
- package/dist/godot-csharp-validate.js +1 -71
- package/dist/godot-dotnet-env.js +1 -169
- package/dist/godot-editor-bridge.js +1 -140
- package/dist/godot-gdscript.js +1 -824
- package/dist/godot-project-settings.js +1 -223
- package/dist/godot-runtime-testing.js +1 -249
- package/dist/godot-tools.js +1 -183
- package/dist/http-rate-limit.js +1 -0
- package/dist/http-server-hardening.js +1 -0
- package/dist/image-tools.js +1 -157
- package/dist/infrastructure/command-reference.js +32 -0
- package/dist/infrastructure/config.js +424 -0
- package/dist/infrastructure/context7-auth.js +55 -0
- package/dist/infrastructure/http-rate-limit.js +42 -0
- package/dist/infrastructure/http-server-hardening.js +23 -0
- package/dist/infrastructure/integration-queue.js +46 -0
- package/dist/infrastructure/logger.js +129 -0
- package/dist/infrastructure/mcp-event-store.js +103 -0
- package/dist/infrastructure/ngrok-auth-pool.js +208 -0
- package/dist/infrastructure/request-context.js +14 -0
- package/dist/infrastructure/shutdown.js +37 -0
- package/dist/infrastructure/sse-heartbeat.js +47 -0
- package/dist/infrastructure/tool-capabilities.js +67 -0
- package/dist/infrastructure/tool-result-budget.js +175 -0
- package/dist/infrastructure/user-config.js +167 -0
- package/dist/integration-discovery.js +1 -98
- package/dist/integration-queue.js +1 -0
- package/dist/integrations/agent-reach/agent-reach-tools.js +196 -0
- package/dist/integrations/agent-reach/native-channels.js +468 -0
- package/dist/integrations/aseprite/aseprite-analysis-tools.js +368 -0
- package/dist/integrations/aseprite/aseprite-editing-tools.js +647 -0
- package/dist/integrations/aseprite/aseprite-live-tools.js +297 -0
- package/dist/integrations/aseprite/aseprite-safety-tools.js +594 -0
- package/dist/integrations/aseprite/aseprite-specialized-tools.js +289 -0
- package/dist/integrations/aseprite/aseprite-tools.js +837 -0
- package/dist/integrations/blender/blender-catalog-mesh.js +593 -0
- package/dist/integrations/blender/blender-catalog-object.js +906 -0
- package/dist/integrations/blender/blender-catalog-scene.js +266 -0
- package/dist/integrations/blender/blender-catalog-select.js +581 -0
- package/dist/integrations/blender/blender-catalog-stubs.js +7512 -0
- package/dist/integrations/blender/blender-catalog.js +165 -0
- package/dist/integrations/blender/blender-client.js +105 -0
- package/dist/integrations/blender/blender-tools.js +2243 -0
- package/dist/integrations/context7/context7-tools.js +106 -0
- package/dist/integrations/dotnet/dotnet-tools.js +195 -0
- package/dist/integrations/godot/godot-animation-tilemap.js +74 -0
- package/dist/integrations/godot/godot-csharp-build.js +91 -0
- package/dist/integrations/godot/godot-csharp-project.js +155 -0
- package/dist/integrations/godot/godot-csharp-runner.js +118 -0
- package/dist/integrations/godot/godot-csharp-semantic.js +146 -0
- package/dist/integrations/godot/godot-csharp-validate.js +71 -0
- package/dist/integrations/godot/godot-dotnet-env.js +134 -0
- package/dist/integrations/godot/godot-editor-bridge.js +328 -0
- package/dist/integrations/godot/godot-gdscript.js +536 -0
- package/dist/integrations/godot/godot-project-settings.js +178 -0
- package/dist/integrations/godot/godot-runtime-testing.js +263 -0
- package/dist/integrations/godot/godot-tools.js +193 -0
- package/dist/integrations/images/image-tools.js +414 -0
- package/dist/integrations/images/png-codec.js +251 -0
- package/dist/integrations/images/view-image.js +99 -0
- package/dist/integrations/images/window-capture.js +148 -0
- package/dist/integrations/integration-discovery.js +185 -0
- package/dist/integrations/obsidian/obsidian-tools.js +205 -0
- package/dist/integrations/playwright/browser-session.js +516 -0
- package/dist/integrations/playwright/browser-stability.js +36 -0
- package/dist/integrations/playwright/playwright-runtime.js +105 -0
- package/dist/integrations/playwright/web-tools.js +504 -0
- package/dist/integrations/roblox/roblox-helpers.js +381 -0
- package/dist/integrations/roblox/roblox-studio-client.js +112 -0
- package/dist/integrations/roblox/roblox-tools.js +106 -0
- package/dist/integrations/serena/serena-manager.js +464 -0
- package/dist/integrations/serena/serena-tools.js +411 -0
- package/dist/logger.js +1 -76
- package/dist/mcp-event-store.js +1 -0
- package/dist/oauth-provider.js +1 -377
- package/dist/pi-tools.js +1 -81
- package/dist/playwright-runtime.js +1 -0
- package/dist/process/background-lifecycle.js +189 -0
- package/dist/process/control-retry.js +42 -0
- package/dist/process/crash-recovery.js +23 -0
- package/dist/process/processes.js +456 -0
- package/dist/processes.js +1 -218
- package/dist/request-context.js +1 -0
- package/dist/review-checkpoints.js +1 -142
- package/dist/room-registry.js +1 -0
- package/dist/roots.js +1 -53
- package/dist/search-discovery.js +1 -271
- package/dist/serena-manager.js +1 -443
- package/dist/serena-tools.js +1 -411
- package/dist/server/dashboard-page-styles.js +331 -0
- package/dist/server/dashboard-page.js +1509 -0
- package/dist/server/dashboard-routes.js +46 -0
- package/dist/server/dashboard.js +240 -0
- package/dist/server/http-helpers.js +30 -0
- package/dist/server/integration-profile-update.js +37 -0
- package/dist/server/mcp-policy.js +169 -0
- package/dist/server/mcp-server-factory.js +127 -0
- package/dist/server/mcp-tool-registrar.js +182 -0
- package/dist/server/openai-session-hint.js +14 -0
- package/dist/server/tool-groups.js +29 -0
- package/dist/server/tool-logging.js +33 -0
- package/dist/server/tool-registration-shared.js +59 -0
- package/dist/server/tools/aseprite-advanced-tools-registration.js +547 -0
- package/dist/server/tools/aseprite-tools-registration.js +213 -0
- package/dist/server/tools/blender-tools-registration.js +690 -0
- package/dist/server/tools/core-file-tools-registration.js +459 -0
- package/dist/server/tools/dotnet-godot-window-tools-registration.js +120 -0
- package/dist/server/tools/godot-csharp-tools-registration.js +252 -0
- package/dist/server/tools/godot-gdscript-tools-registration.js +189 -0
- package/dist/server/tools/process-project-tools-registration.js +155 -0
- package/dist/server/tools/roblox-tools-registration.js +514 -0
- package/dist/server/tools/web-image-tools-registration.js +326 -0
- package/dist/server/tools/workspace-lifecycle-tools-registration.js +130 -0
- package/dist/server/ui-assets.js +97 -0
- package/dist/server/workspace-analytics.js +92 -0
- package/dist/server.js +453 -2713
- package/dist/session-registry.js +1 -0
- package/dist/shutdown.js +1 -0
- package/dist/skills.js +1 -45
- package/dist/sse-heartbeat.js +1 -0
- package/dist/tool-capabilities.js +1 -0
- package/dist/tool-result-budget.js +1 -0
- package/dist/tools/pi-tools.js +81 -0
- package/dist/tunnels/cloudflare-tunnel.js +217 -0
- package/dist/tunnels/cloudflared-service.js +174 -0
- package/dist/tunnels/ngrok-tunnel.js +220 -0
- package/dist/tunnels/tunnel-manager.js +186 -0
- package/dist/tunnels/tunnel-types.js +1 -0
- package/dist/tunnels/tunnel-utils.js +62 -0
- package/dist/ui/.vite/manifest.json +9 -2487
- package/dist/ui/assets/heavy-payload-D42A9ceL.js +1 -0
- package/dist/ui/assets/lightweight-diff-Cv4g9Hdr.js +13 -0
- package/dist/ui/assets/review-payload-DKIg1cKF.js +1 -0
- package/dist/ui/assets/workspace-app-CeK3NhmB.css +1 -0
- package/dist/ui/assets/{workspace-app-C5QsE314.js → workspace-app-CkUXnpl4.js} +6 -6
- package/dist/ui/brand-theme.js +23 -0
- package/dist/ui/workspace-app.html +15 -15
- package/dist/user-config.js +1 -57
- package/dist/view-image.js +1 -104
- package/dist/web-tools.js +1 -200
- package/dist/window-capture.js +1 -74
- package/dist/workspace/artifact-registry.js +69 -0
- package/dist/workspace/git-worktrees.js +141 -0
- package/dist/workspace/git.js +42 -0
- package/dist/workspace/review-checkpoints.js +142 -0
- package/dist/workspace/roots.js +56 -0
- package/dist/workspace/search-discovery.js +264 -0
- package/dist/workspace/skills.js +45 -0
- package/dist/workspace/workspace-store.js +219 -0
- package/dist/workspace/workspaces.js +314 -0
- package/dist/workspace-store.js +1 -125
- package/dist/workspaces.js +1 -226
- package/docs/CREATOR_STORE_FREE_ASSETS.md +162 -0
- package/docs/DEVELOPMENT_TOOLS.md +136 -93
- package/docs/assets/auvrynt-icon.png +0 -0
- package/docs/assets/auvrynt-icon.svg +20 -0
- package/docs/chatgpt-coding-workflow.md +143 -143
- package/docs/configuration.md +156 -124
- package/docs/diagnostics.md +79 -0
- package/docs/gotchas.md +244 -202
- package/docs/multi-agent-and-long-projects.md +91 -0
- package/docs/security.md +138 -100
- package/docs/setup.md +171 -131
- package/docs/source-layout.md +60 -0
- package/extensions/auvrynt_bridge/auvrynt_bridge.lua +594 -0
- package/extensions/auvrynt_bridge/live_analysis.lua +181 -0
- package/extensions/auvrynt_bridge/live_animation.lua +134 -0
- package/extensions/auvrynt_bridge/live_commands.lua +24 -0
- package/extensions/auvrynt_bridge/live_common.lua +130 -0
- package/extensions/auvrynt_bridge/live_document.lua +78 -0
- package/extensions/auvrynt_bridge/live_drawing.lua +125 -0
- package/extensions/auvrynt_bridge/live_effects.lua +91 -0
- package/extensions/auvrynt_bridge/live_palette_template.lua +167 -0
- package/extensions/auvrynt_bridge/live_selection.lua +110 -0
- package/extensions/auvrynt_bridge/live_structure.lua +129 -0
- package/extensions/auvrynt_bridge/package.json +17 -0
- package/guides/ASEPRITE_AGENT_GUIDE.md +133 -0
- package/guides/BLENDER_AGENT_GUIDE.md +472 -0
- package/guides/GODOT_AGENT_GUIDE.md +298 -0
- package/guides/PROJECT_ROUTER.md +165 -0
- package/guides/ROBLOX_AGENT_GUIDE.md +75 -0
- package/guides/SOFTWARE_AGENT_GUIDE.md +104 -0
- package/guides/WEB_AGENT_GUIDE.md +287 -0
- package/package.json +78 -70
- package/scripts/dev-server.mjs +121 -120
- package/scripts/live-tunnel-smoke.mjs +538 -0
- package/scripts/repo-hygiene.mjs +74 -0
- package/scripts/restart-after-crash.mjs +49 -0
- package/scripts/run-tests.mjs +166 -0
- package/dist/ui/assets/abap-CLvhMVsD.js +0 -1
- package/dist/ui/assets/actionscript-3--17pq3dv.js +0 -1
- package/dist/ui/assets/ada-C5qYipkI.js +0 -1
- package/dist/ui/assets/andromeeda-vGVdxbeo.js +0 -1
- package/dist/ui/assets/angular-html-BJqQFYI6.js +0 -1
- package/dist/ui/assets/angular-ts-CMJECO0Y.js +0 -1
- package/dist/ui/assets/apache-U0d_L8uA.js +0 -1
- package/dist/ui/assets/apex-CGTLDQj6.js +0 -1
- package/dist/ui/assets/apl-DWeXpBBr.js +0 -1
- package/dist/ui/assets/applescript-CCn79oCD.js +0 -1
- package/dist/ui/assets/ara-4CJ0cIlV.js +0 -1
- package/dist/ui/assets/asciidoc-DE70LPWp.js +0 -1
- package/dist/ui/assets/asm-Cmm7eHzH.js +0 -1
- package/dist/ui/assets/astro-CLbttLOq.js +0 -1
- package/dist/ui/assets/aurora-x-CDeNXAV0.js +0 -1
- package/dist/ui/assets/awk-BWXHIvNe.js +0 -1
- package/dist/ui/assets/ayu-dark-DluEY0Gj.js +0 -1
- package/dist/ui/assets/ayu-light-C3h-C4tm.js +0 -1
- package/dist/ui/assets/ayu-mirage-Bqwy1Gya.js +0 -1
- package/dist/ui/assets/ballerina-B7ZEbQpA.js +0 -1
- package/dist/ui/assets/bat-Bo4NYOV-.js +0 -1
- package/dist/ui/assets/beancount-D-usSTwE.js +0 -1
- package/dist/ui/assets/berry-DKpUyyne.js +0 -1
- package/dist/ui/assets/bibtex-Ci_nEsc7.js +0 -1
- package/dist/ui/assets/bicep-CUHmPFLl.js +0 -1
- package/dist/ui/assets/bird2-C2hNVINV.js +0 -1
- package/dist/ui/assets/blade-BOzY0P2V.js +0 -1
- package/dist/ui/assets/bsl-BkkzgIyY.js +0 -1
- package/dist/ui/assets/c-BG-8uJvh.js +0 -1
- package/dist/ui/assets/c3-CnJL0r0V.js +0 -1
- package/dist/ui/assets/cadence-CQ2zXKGN.js +0 -1
- package/dist/ui/assets/cairo-DLTphjLi.js +0 -1
- package/dist/ui/assets/catppuccin-frappe-3VR1Za6u.js +0 -1
- package/dist/ui/assets/catppuccin-latte-DwIHMF0Q.js +0 -1
- package/dist/ui/assets/catppuccin-macchiato-DYnBP6_5.js +0 -1
- package/dist/ui/assets/catppuccin-mocha-DYhrFGRu.js +0 -1
- package/dist/ui/assets/clarity-SemFz856.js +0 -1
- package/dist/ui/assets/clojure-DqKBuwfJ.js +0 -1
- package/dist/ui/assets/cmake-Bj61d0ZC.js +0 -1
- package/dist/ui/assets/cobol-I_17IuGe.js +0 -1
- package/dist/ui/assets/codeowners-C8r90Shi.js +0 -1
- package/dist/ui/assets/codeql-oeQT6MSM.js +0 -1
- package/dist/ui/assets/coffee-C0B8hmok.js +0 -1
- package/dist/ui/assets/common-lisp-Cv5bFMCO.js +0 -1
- package/dist/ui/assets/coq-BrsZFFmf.js +0 -1
- package/dist/ui/assets/cpp-DDJXt6Vs.js +0 -1
- package/dist/ui/assets/crystal-Bexqace6.js +0 -1
- package/dist/ui/assets/csharp-Ct8U2NOr.js +0 -1
- package/dist/ui/assets/css-DSQhw_9R.js +0 -1
- package/dist/ui/assets/csv-Dx-8-gkx.js +0 -1
- package/dist/ui/assets/cue-CE9AQfxI.js +0 -1
- package/dist/ui/assets/cypher-ClKdZ_lG.js +0 -1
- package/dist/ui/assets/d-qD-0Kul2.js +0 -1
- package/dist/ui/assets/dark-plus-Cs2F2srj.js +0 -1
- package/dist/ui/assets/dart-DkHntEIa.js +0 -1
- package/dist/ui/assets/dax-BkyTk9wS.js +0 -1
- package/dist/ui/assets/desktop-Dlh5hvp9.js +0 -1
- package/dist/ui/assets/diff-woXpYk--.js +0 -1
- package/dist/ui/assets/docker-IyjqRm3v.js +0 -1
- package/dist/ui/assets/dotenv-_5a1GRtc.js +0 -1
- package/dist/ui/assets/dracula-BHWKrbxM.js +0 -1
- package/dist/ui/assets/dracula-soft-5eyTD99u.js +0 -1
- package/dist/ui/assets/dream-maker-DW3nJb8Q.js +0 -1
- package/dist/ui/assets/edge-Z8YYkHOr.js +0 -1
- package/dist/ui/assets/elixir-CG9uKtAF.js +0 -1
- package/dist/ui/assets/elm-GfWG2IfT.js +0 -1
- package/dist/ui/assets/emacs-lisp-C9PiwqqW.js +0 -1
- package/dist/ui/assets/erb-xe89e73J.js +0 -1
- package/dist/ui/assets/erlang-Cphh6RMH.js +0 -1
- package/dist/ui/assets/everforest-dark-sB-x3p7T.js +0 -1
- package/dist/ui/assets/everforest-light-Df2xbC6M.js +0 -1
- package/dist/ui/assets/fennel-DQxkIbk2.js +0 -1
- package/dist/ui/assets/fish-BJitypiv.js +0 -1
- package/dist/ui/assets/fluent-C03EYrpw.js +0 -1
- package/dist/ui/assets/fortran-fixed-form-DEKoE2YW.js +0 -1
- package/dist/ui/assets/fortran-free-form-CYNrtFtB.js +0 -1
- package/dist/ui/assets/fsharp-D13ZGOAj.js +0 -1
- package/dist/ui/assets/gdresource-C0sCabJj.js +0 -1
- package/dist/ui/assets/gdscript-Cp2uCuqX.js +0 -1
- package/dist/ui/assets/gdshader-CBce3t8t.js +0 -1
- package/dist/ui/assets/genie-CV2tkWYe.js +0 -1
- package/dist/ui/assets/gherkin-DExj1W_8.js +0 -1
- package/dist/ui/assets/git-commit-BSykSTBG.js +0 -1
- package/dist/ui/assets/git-rebase-CoTL_uSE.js +0 -1
- package/dist/ui/assets/github-dark-C-LZuMrd.js +0 -1
- package/dist/ui/assets/github-dark-default-DXG-b-1a.js +0 -1
- package/dist/ui/assets/github-dark-dimmed-Bx1FflLF.js +0 -1
- package/dist/ui/assets/github-dark-high-contrast-B_tTalzw.js +0 -1
- package/dist/ui/assets/github-light-EUqPIrTm.js +0 -1
- package/dist/ui/assets/github-light-default-BXViO-2h.js +0 -1
- package/dist/ui/assets/github-light-high-contrast-B68TUdTA.js +0 -1
- package/dist/ui/assets/gleam-CSRkHgEL.js +0 -1
- package/dist/ui/assets/glimmer-js-DAn4UCSu.js +0 -1
- package/dist/ui/assets/glimmer-ts-Tjyi6Gh5.js +0 -1
- package/dist/ui/assets/glsl-CtTDZoqR.js +0 -1
- package/dist/ui/assets/gn-ilITqXS6.js +0 -1
- package/dist/ui/assets/gnuplot-7GGW24-e.js +0 -1
- package/dist/ui/assets/go-BJwz_mda.js +0 -1
- package/dist/ui/assets/graphql-D5gcC_Jk.js +0 -1
- package/dist/ui/assets/groovy-CacY0gHj.js +0 -1
- package/dist/ui/assets/gruvbox-dark-hard-C820rvS2.js +0 -1
- package/dist/ui/assets/gruvbox-dark-medium-BPjhmG05.js +0 -1
- package/dist/ui/assets/gruvbox-dark-soft-MrdJrrXF.js +0 -1
- package/dist/ui/assets/gruvbox-light-hard-BC_s9l72.js +0 -1
- package/dist/ui/assets/gruvbox-light-medium-BAWPOn9u.js +0 -1
- package/dist/ui/assets/gruvbox-light-soft-BSMLrYjP.js +0 -1
- package/dist/ui/assets/hack-BJXY27dt.js +0 -1
- package/dist/ui/assets/haml-BLfFoZf7.js +0 -1
- package/dist/ui/assets/handlebars-Dw6CWkvN.js +0 -1
- package/dist/ui/assets/haskell-D8IpX4py.js +0 -1
- package/dist/ui/assets/haxe-OTjmBuCE.js +0 -1
- package/dist/ui/assets/hcl-Dh228itO.js +0 -1
- package/dist/ui/assets/heavy-payload-Dcg0-F-S.js +0 -4
- package/dist/ui/assets/hjson-CxZEssPk.js +0 -1
- package/dist/ui/assets/hlsl-Cvrh5tZx.js +0 -1
- package/dist/ui/assets/horizon-CE9ld1lL.js +0 -1
- package/dist/ui/assets/horizon-bright-Br1oVSNq.js +0 -1
- package/dist/ui/assets/houston-CsvMBhTu.js +0 -1
- package/dist/ui/assets/html-CAcAWvoN.js +0 -1
- package/dist/ui/assets/html-derivative-8aSW2E_7.js +0 -1
- package/dist/ui/assets/http-B2YR_3V1.js +0 -1
- package/dist/ui/assets/hurl-BnDJ9Zhf.js +0 -1
- package/dist/ui/assets/hxml-B0Qn7Nwc.js +0 -1
- package/dist/ui/assets/hy-CZbG8q4J.js +0 -1
- package/dist/ui/assets/imba-DsUTQ-LC.js +0 -1
- package/dist/ui/assets/ini-B5eOa1yu.js +0 -1
- package/dist/ui/assets/java-Doxi4W8u.js +0 -1
- package/dist/ui/assets/javascript-BbRdEqti.js +0 -1
- package/dist/ui/assets/jinja-CS3Tpv_Q.js +0 -1
- package/dist/ui/assets/jison-BkPGYVHR.js +0 -1
- package/dist/ui/assets/json-BMt1m3m8.js +0 -1
- package/dist/ui/assets/json5-BR5RXkoi.js +0 -1
- package/dist/ui/assets/jsonc-CYpm1nAK.js +0 -1
- package/dist/ui/assets/jsonl-CmCQp5Yx.js +0 -1
- package/dist/ui/assets/jsonnet-CJTPZ8u_.js +0 -1
- package/dist/ui/assets/jssm-DXw9l8Rf.js +0 -1
- package/dist/ui/assets/jsx-CQKrJXXY.js +0 -1
- package/dist/ui/assets/julia-BuN7i2du.js +0 -1
- package/dist/ui/assets/just-BswEPFPu.js +0 -1
- package/dist/ui/assets/kanagawa-dragon-CXtmUGW6.js +0 -1
- package/dist/ui/assets/kanagawa-lotus-BN08jTvb.js +0 -1
- package/dist/ui/assets/kanagawa-wave-CTweb8Dz.js +0 -1
- package/dist/ui/assets/kdl-CsD5j6eV.js +0 -1
- package/dist/ui/assets/kotlin-DhhofPvG.js +0 -1
- package/dist/ui/assets/kusto-BUv0MjJC.js +0 -1
- package/dist/ui/assets/laserwave-C_8bwKvT.js +0 -1
- package/dist/ui/assets/latex-DU2VyFfA.js +0 -1
- package/dist/ui/assets/lean-CewbzKMR.js +0 -1
- package/dist/ui/assets/less-DVTAwKKz.js +0 -1
- package/dist/ui/assets/light-plus-DVQuIRkW.js +0 -1
- package/dist/ui/assets/liquid-Cmz1L3dq.js +0 -1
- package/dist/ui/assets/llvm-Cm23YOpf.js +0 -1
- package/dist/ui/assets/log-BNLmms1o.js +0 -1
- package/dist/ui/assets/logo-Cluzi2Zq.js +0 -1
- package/dist/ui/assets/lua-CfVXhkaJ.js +0 -1
- package/dist/ui/assets/luau-CNKltnaQ.js +0 -1
- package/dist/ui/assets/make-Dixweg8N.js +0 -1
- package/dist/ui/assets/markdown-BYOwaDjH.js +0 -1
- package/dist/ui/assets/marko-C5bfqGiA.js +0 -1
- package/dist/ui/assets/material-theme-Bm3Qr25_.js +0 -1
- package/dist/ui/assets/material-theme-darker-2IIEA8gg.js +0 -1
- package/dist/ui/assets/material-theme-lighter-uhdI0v04.js +0 -1
- package/dist/ui/assets/material-theme-ocean-CHQ94UKr.js +0 -1
- package/dist/ui/assets/material-theme-palenight-B5W6OYN7.js +0 -1
- package/dist/ui/assets/matlab-D7qyCx1q.js +0 -1
- package/dist/ui/assets/mdc-CVBXYfyq.js +0 -1
- package/dist/ui/assets/mdx-DQZ5AkYe.js +0 -1
- package/dist/ui/assets/mermaid-Bk4SNUv9.js +0 -1
- package/dist/ui/assets/min-dark-BSWPekZh.js +0 -1
- package/dist/ui/assets/min-light-DDpmG2fV.js +0 -1
- package/dist/ui/assets/mipsasm-BMqwQI7S.js +0 -1
- package/dist/ui/assets/mojo-BgCJLMeH.js +0 -1
- package/dist/ui/assets/monokai-CdkpiU2Y.js +0 -1
- package/dist/ui/assets/moonbit-CaWjb8XO.js +0 -1
- package/dist/ui/assets/move-B1IS1UjX.js +0 -1
- package/dist/ui/assets/narrat-_X_XdTYD.js +0 -1
- package/dist/ui/assets/nextflow-Bbiyy34d.js +0 -1
- package/dist/ui/assets/nextflow-groovy-Dc_ddanL.js +0 -1
- package/dist/ui/assets/nginx-CzJafxLa.js +0 -1
- package/dist/ui/assets/night-owl-DhmEMT88.js +0 -1
- package/dist/ui/assets/night-owl-light-eJ-hLW7d.js +0 -1
- package/dist/ui/assets/nim-DABKtHtM.js +0 -1
- package/dist/ui/assets/nix-IvuFDN5E.js +0 -1
- package/dist/ui/assets/nord-Cb4Vim4T.js +0 -1
- package/dist/ui/assets/nushell-DcLAeLz5.js +0 -1
- package/dist/ui/assets/objective-c-D1A_Heim.js +0 -1
- package/dist/ui/assets/objective-cpp-BsSzOQcm.js +0 -1
- package/dist/ui/assets/ocaml-O90oeIOV.js +0 -1
- package/dist/ui/assets/odin-B1RWQWA5.js +0 -1
- package/dist/ui/assets/one-dark-pro-CLwyXe_n.js +0 -1
- package/dist/ui/assets/one-light-D7Lr4KcI.js +0 -1
- package/dist/ui/assets/openscad-BUDT5pXO.js +0 -1
- package/dist/ui/assets/pascal-4ZHwLPI5.js +0 -1
- package/dist/ui/assets/perl-CBh7L3lZ.js +0 -1
- package/dist/ui/assets/php-DFbI9q5p.js +0 -1
- package/dist/ui/assets/pierre-dark-sU4Zdns8.js +0 -1
- package/dist/ui/assets/pierre-dark-soft-HXgun5vs.js +0 -1
- package/dist/ui/assets/pierre-light-DWBk51d8.js +0 -1
- package/dist/ui/assets/pierre-light-soft-CodEzPxf.js +0 -1
- package/dist/ui/assets/pkl-ot-7Btpt.js +0 -1
- package/dist/ui/assets/plastic-DQwYfKfQ.js +0 -1
- package/dist/ui/assets/plsql-DGHpHOYJ.js +0 -1
- package/dist/ui/assets/po-BiJDBrnU.js +0 -1
- package/dist/ui/assets/poimandres-DRFjx7u4.js +0 -1
- package/dist/ui/assets/polar-C7UOKdEL.js +0 -1
- package/dist/ui/assets/postcss-BXeXVLqQ.js +0 -1
- package/dist/ui/assets/powerquery-DNMTfnFr.js +0 -1
- package/dist/ui/assets/powershell-DshXNtvi.js +0 -1
- package/dist/ui/assets/prisma-BsRQq5mF.js +0 -1
- package/dist/ui/assets/prolog-iXnhIJG7.js +0 -1
- package/dist/ui/assets/proto-DB4EqR-F.js +0 -1
- package/dist/ui/assets/pug-C_PxC7gO.js +0 -1
- package/dist/ui/assets/puppet-CDv2pdJW.js +0 -1
- package/dist/ui/assets/purescript-9MfHhQsQ.js +0 -1
- package/dist/ui/assets/python-gzcpVVnB.js +0 -1
- package/dist/ui/assets/qml-DtngoFFK.js +0 -1
- package/dist/ui/assets/qmldir-DCQb3MpD.js +0 -1
- package/dist/ui/assets/qss-Fe1Jh2GI.js +0 -1
- package/dist/ui/assets/r-DohkcevW.js +0 -1
- package/dist/ui/assets/racket-DcIDlBhZ.js +0 -1
- package/dist/ui/assets/raku-B3gFvitq.js +0 -1
- package/dist/ui/assets/razor-C4t8J0_E.js +0 -1
- package/dist/ui/assets/red-CJ3rzSJv.js +0 -1
- package/dist/ui/assets/reg-CRGYupPL.js +0 -1
- package/dist/ui/assets/regexp-OGbTbjgY.js +0 -1
- package/dist/ui/assets/rel-BtDbiS_P.js +0 -1
- package/dist/ui/assets/review-payload-C5Qz60Kq.js +0 -1
- package/dist/ui/assets/riscv-Ckw8ddFX.js +0 -1
- package/dist/ui/assets/ron-VUp2lXgN.js +0 -1
- package/dist/ui/assets/rose-pine-BthvhNj6.js +0 -1
- package/dist/ui/assets/rose-pine-dawn-Dg85fqjY.js +0 -1
- package/dist/ui/assets/rose-pine-moon-hon4tzzS.js +0 -1
- package/dist/ui/assets/rosmsg-CAekHB0j.js +0 -1
- package/dist/ui/assets/rst-CfBbbcvC.js +0 -1
- package/dist/ui/assets/ruby-Bw0mpxHY.js +0 -1
- package/dist/ui/assets/rust-Cfkwpbl8.js +0 -1
- package/dist/ui/assets/sas-Cs3s9JOf.js +0 -1
- package/dist/ui/assets/sass-DXrisJhu.js +0 -1
- package/dist/ui/assets/scala-DKOlJaKm.js +0 -1
- package/dist/ui/assets/scheme-DQCgrYNe.js +0 -1
- package/dist/ui/assets/scss-sRxNJS54.js +0 -1
- package/dist/ui/assets/sdbl-bTVj8UrX.js +0 -1
- package/dist/ui/assets/shaderlab-TOUzSsQk.js +0 -1
- package/dist/ui/assets/shellscript-B0X6wh0R.js +0 -1
- package/dist/ui/assets/shellsession-D2FdOioR.js +0 -1
- package/dist/ui/assets/slack-dark-DnToyrRv.js +0 -1
- package/dist/ui/assets/slack-ochin-B2OO5cIa.js +0 -1
- package/dist/ui/assets/smalltalk-B16xEiuN.js +0 -1
- package/dist/ui/assets/snazzy-light-4G7pJPwS.js +0 -1
- package/dist/ui/assets/solarized-dark-DV17i1UV.js +0 -1
- package/dist/ui/assets/solarized-light-DSh2HLQt.js +0 -1
- package/dist/ui/assets/solidity-CKzVLygQ.js +0 -1
- package/dist/ui/assets/soy-s6g9OjJ1.js +0 -1
- package/dist/ui/assets/sparql-D_iOobhT.js +0 -1
- package/dist/ui/assets/splunk-BC2Px7Mm.js +0 -1
- package/dist/ui/assets/sql-DVTnh5V-.js +0 -1
- package/dist/ui/assets/ssh-config-BgfXC-Er.js +0 -1
- package/dist/ui/assets/stata-DFIDiXF9.js +0 -1
- package/dist/ui/assets/stylus-B6D30XZt.js +0 -1
- package/dist/ui/assets/surrealql-DVfrsLyg.js +0 -1
- package/dist/ui/assets/svelte-D5GsxESq.js +0 -1
- package/dist/ui/assets/swift-DonLKvLd.js +0 -1
- package/dist/ui/assets/synthwave-84-nFMaYfgc.js +0 -1
- package/dist/ui/assets/system-verilog-DJ5XKQeo.js +0 -1
- package/dist/ui/assets/systemd-BxMlprV5.js +0 -1
- package/dist/ui/assets/talonscript-CohzipZa.js +0 -1
- package/dist/ui/assets/tasl-DMoTqEGO.js +0 -1
- package/dist/ui/assets/tcl-CZd0xW_V.js +0 -1
- package/dist/ui/assets/templ-DI-Zyqzd.js +0 -1
- package/dist/ui/assets/terraform-DswuEJGm.js +0 -1
- package/dist/ui/assets/tex-WHHmlbJI.js +0 -1
- package/dist/ui/assets/tokyo-night-oM2G3aXe.js +0 -1
- package/dist/ui/assets/toml-CcmNWLt0.js +0 -1
- package/dist/ui/assets/ts-tags-Dwpo2RFJ.js +0 -1
- package/dist/ui/assets/tsv-sltzmVWM.js +0 -1
- package/dist/ui/assets/tsx-ph_idaAW.js +0 -1
- package/dist/ui/assets/turtle-ByJddavk.js +0 -1
- package/dist/ui/assets/twig-YO17jFjR.js +0 -1
- package/dist/ui/assets/typescript-CbAxjhkl.js +0 -1
- package/dist/ui/assets/typespec-B88KGewJ.js +0 -1
- package/dist/ui/assets/typst-DI99ib-x.js +0 -1
- package/dist/ui/assets/useFileDiffInstance-B2DLX3Vg.js +0 -244
- package/dist/ui/assets/v-DETTlOr0.js +0 -1
- package/dist/ui/assets/vala-zf12oZj6.js +0 -1
- package/dist/ui/assets/vb-Djn5o6TS.js +0 -1
- package/dist/ui/assets/verilog-CiiDBU1e.js +0 -1
- package/dist/ui/assets/vesper-D5bVUKB1.js +0 -1
- package/dist/ui/assets/vhdl-BroJfC0k.js +0 -1
- package/dist/ui/assets/viml-DvXPmvsu.js +0 -1
- package/dist/ui/assets/vitesse-black-fwtXNY1n.js +0 -1
- package/dist/ui/assets/vitesse-dark-BZCL-v6S.js +0 -1
- package/dist/ui/assets/vitesse-light-VbXTXTou.js +0 -1
- package/dist/ui/assets/vue-CraHL-Ps.js +0 -1
- package/dist/ui/assets/vue-html-e9tyZNtS.js +0 -1
- package/dist/ui/assets/vue-vine-CofmxaUb.js +0 -1
- package/dist/ui/assets/vyper-CgoNMtux.js +0 -1
- package/dist/ui/assets/wasm-BnjxR4X6.js +0 -1
- package/dist/ui/assets/wasm-ByWQv1Qj.js +0 -1
- package/dist/ui/assets/wenyan-C8pVoKbM.js +0 -1
- package/dist/ui/assets/wgsl-BsKzXJz4.js +0 -1
- package/dist/ui/assets/wikitext-ClFFjSW2.js +0 -1
- package/dist/ui/assets/wit-DdvCle-K.js +0 -1
- package/dist/ui/assets/wolfram-DLL8P-h_.js +0 -1
- package/dist/ui/assets/workspace-app-8--oTbCd.css +0 -1
- package/dist/ui/assets/xml-BWSdPZHm.js +0 -1
- package/dist/ui/assets/xsl-BtCt7Hx8.js +0 -1
- package/dist/ui/assets/yaml-BZiTw7cQ.js +0 -1
- package/dist/ui/assets/zenscript-BnlCZFoB.js +0 -1
- package/dist/ui/assets/zig-CMLA9XwU.js +0 -1
- package/docs/assets/auvrynt-logo-light.png +0 -0
- package/docs/assets/auvrynt-screenshot.png +0 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { assertInteger, assertPositiveInteger, errorResponse, luaString, openSpriteScript, runLua, textResponse, workspacePath, } from "./aseprite-tools.js";
|
|
2
|
+
const MAX_READ_PIXELS = 65_536;
|
|
3
|
+
const MAX_ANALYSIS_PIXELS = 4_194_304;
|
|
4
|
+
function normalizeRegion(region) {
|
|
5
|
+
if (!region)
|
|
6
|
+
return undefined;
|
|
7
|
+
return {
|
|
8
|
+
x: assertInteger(region.x, "region.x"),
|
|
9
|
+
y: assertInteger(region.y, "region.y"),
|
|
10
|
+
width: assertPositiveInteger(region.width, "region.width"),
|
|
11
|
+
height: assertPositiveInteger(region.height, "region.height"),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export async function asepriteReadPixels(config, registry, input) {
|
|
15
|
+
try {
|
|
16
|
+
const file = workspacePath(registry, input.workspaceId, input.filePath);
|
|
17
|
+
const frame = input.frame === undefined ? 1 : assertPositiveInteger(input.frame, "frame");
|
|
18
|
+
const region = normalizeRegion(input.region);
|
|
19
|
+
const format = input.format ?? "rows";
|
|
20
|
+
const result = await runLua(config, registry, input.workspaceId, `
|
|
21
|
+
${openSpriteScript(file.absolute)}
|
|
22
|
+
local layer = ${input.layer ? `find_layer(sprite.layers, ${luaString(input.layer)})` : "sprite.layers[1]"}
|
|
23
|
+
if layer == nil or layer.isGroup then fail("A drawable layer was not found") end
|
|
24
|
+
if ${frame} > #sprite.frames then fail("Frame is outside the sprite") end
|
|
25
|
+
local x0 = ${region?.x ?? 0}
|
|
26
|
+
local y0 = ${region?.y ?? 0}
|
|
27
|
+
local width = ${region?.width ?? "sprite.width"}
|
|
28
|
+
local height = ${region?.height ?? "sprite.height"}
|
|
29
|
+
if x0 < 0 or y0 < 0 or x0 + width > sprite.width or y0 + height > sprite.height then fail("Region is outside the sprite") end
|
|
30
|
+
if width * height > ${MAX_READ_PIXELS} then fail("Requested region exceeds ${MAX_READ_PIXELS} pixels") end
|
|
31
|
+
local format = ${luaString(format)}
|
|
32
|
+
local rows = {}
|
|
33
|
+
local index_rows = {}
|
|
34
|
+
local points = {}
|
|
35
|
+
local histogram = {}
|
|
36
|
+
local transparent = 0
|
|
37
|
+
local semi_transparent = 0
|
|
38
|
+
local bounds = nil
|
|
39
|
+
for y = y0, y0 + height - 1 do
|
|
40
|
+
local row = {}
|
|
41
|
+
local index_row = {}
|
|
42
|
+
for x = x0, x0 + width - 1 do
|
|
43
|
+
local color = canvas_pixel(sprite, layer, ${frame}, x, y)
|
|
44
|
+
local hex = rgba_hex(color)
|
|
45
|
+
histogram[hex] = (histogram[hex] or 0) + 1
|
|
46
|
+
if color.a == 0 then transparent = transparent + 1
|
|
47
|
+
elseif color.a < 255 then semi_transparent = semi_transparent + 1 end
|
|
48
|
+
if color.a > 0 then
|
|
49
|
+
if bounds == nil then bounds = { x=x, y=y, right=x, bottom=y }
|
|
50
|
+
else
|
|
51
|
+
if x < bounds.x then bounds.x = x end
|
|
52
|
+
if y < bounds.y then bounds.y = y end
|
|
53
|
+
if x > bounds.right then bounds.right = x end
|
|
54
|
+
if y > bounds.bottom then bounds.bottom = y end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
if format == "rows" then
|
|
58
|
+
table.insert(row, hex)
|
|
59
|
+
if color.index ~= nil then table.insert(index_row, color.index) end
|
|
60
|
+
elseif format == "points" and (${input.includeTransparent === true ? "true" : "false"} or color.a > 0) then
|
|
61
|
+
table.insert(points, { x=x, y=y, color=hex, index=color.index })
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
if format == "rows" then
|
|
65
|
+
table.insert(rows, row)
|
|
66
|
+
if #index_row > 0 then table.insert(index_rows, index_row) end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
if bounds ~= nil then
|
|
70
|
+
bounds.width = bounds.right - bounds.x + 1
|
|
71
|
+
bounds.height = bounds.bottom - bounds.y + 1
|
|
72
|
+
bounds.right = nil
|
|
73
|
+
bounds.bottom = nil
|
|
74
|
+
end
|
|
75
|
+
local histogram_rows = {}
|
|
76
|
+
for color, count in pairs(histogram) do table.insert(histogram_rows, { color=color, count=count }) end
|
|
77
|
+
table.sort(histogram_rows, function(a, b) if a.count == b.count then return a.color < b.color else return a.count > b.count end end)
|
|
78
|
+
emit_result({
|
|
79
|
+
file=${luaString(file.relative)}, layer=layer.name, frame=${frame},
|
|
80
|
+
region={x=x0,y=y0,width=width,height=height}, format=format,
|
|
81
|
+
rows=format == "rows" and rows or nil,
|
|
82
|
+
palette_indices=(format == "rows" and #index_rows > 0) and index_rows or nil,
|
|
83
|
+
points=format == "points" and points or nil,
|
|
84
|
+
histogram=histogram_rows,
|
|
85
|
+
alpha_bounds=bounds,
|
|
86
|
+
transparent_pixels=transparent,
|
|
87
|
+
semi_transparent_pixels=semi_transparent,
|
|
88
|
+
})
|
|
89
|
+
sprite:close()
|
|
90
|
+
`);
|
|
91
|
+
return textResponse(result);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
return errorResponse(error instanceof Error ? error.message : String(error));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export async function asepriteAuditSprite(config, registry, input) {
|
|
98
|
+
try {
|
|
99
|
+
const file = workspacePath(registry, input.workspaceId, input.filePath);
|
|
100
|
+
const neighbors = input.isolatedNeighborMode === 4 ? 4 : 8;
|
|
101
|
+
const result = await runLua(config, registry, input.workspaceId, `
|
|
102
|
+
${openSpriteScript(file.absolute)}
|
|
103
|
+
if sprite.width * sprite.height * #sprite.frames > ${MAX_ANALYSIS_PIXELS} then fail("Sprite is too large for a full audit") end
|
|
104
|
+
local issues = {}
|
|
105
|
+
local colors = {}
|
|
106
|
+
local frame_rows = {}
|
|
107
|
+
local duplicate_map = {}
|
|
108
|
+
local empty_frames = {}
|
|
109
|
+
local semi = 0
|
|
110
|
+
local isolated = 0
|
|
111
|
+
local occupied_total = 0
|
|
112
|
+
local linked_images = {}
|
|
113
|
+
for _, cel in ipairs(sprite.cels) do
|
|
114
|
+
local id = tostring(cel.image.id or cel.image)
|
|
115
|
+
linked_images[id] = (linked_images[id] or 0) + 1
|
|
116
|
+
end
|
|
117
|
+
for frame_number = 1, #sprite.frames do
|
|
118
|
+
local render = Image(sprite.spec)
|
|
119
|
+
render:clear()
|
|
120
|
+
render:drawSprite(sprite, frame_number, Point(0, 0))
|
|
121
|
+
local hash_parts = {}
|
|
122
|
+
local bounds = nil
|
|
123
|
+
local occupied = 0
|
|
124
|
+
local frame_semi = 0
|
|
125
|
+
local frame_isolated = 0
|
|
126
|
+
for y = 0, sprite.height - 1 do
|
|
127
|
+
for x = 0, sprite.width - 1 do
|
|
128
|
+
local color = pixel_rgba(sprite, render:getPixel(x, y))
|
|
129
|
+
local hex = rgba_hex(color)
|
|
130
|
+
table.insert(hash_parts, hex)
|
|
131
|
+
colors[hex] = (colors[hex] or 0) + 1
|
|
132
|
+
if color.a > 0 then
|
|
133
|
+
occupied = occupied + 1
|
|
134
|
+
occupied_total = occupied_total + 1
|
|
135
|
+
if color.a < 255 then semi = semi + 1; frame_semi = frame_semi + 1 end
|
|
136
|
+
if bounds == nil then bounds = {x=x,y=y,right=x,bottom=y}
|
|
137
|
+
else
|
|
138
|
+
if x < bounds.x then bounds.x=x end
|
|
139
|
+
if y < bounds.y then bounds.y=y end
|
|
140
|
+
if x > bounds.right then bounds.right=x end
|
|
141
|
+
if y > bounds.bottom then bounds.bottom=y end
|
|
142
|
+
end
|
|
143
|
+
local count = 0
|
|
144
|
+
for dy=-1,1 do for dx=-1,1 do
|
|
145
|
+
if not (dx == 0 and dy == 0) and (${neighbors} == 8 or dx == 0 or dy == 0) then
|
|
146
|
+
local nx=x+dx local ny=y+dy
|
|
147
|
+
if nx>=0 and ny>=0 and nx<sprite.width and ny<sprite.height then
|
|
148
|
+
if pixel_rgba(sprite, render:getPixel(nx, ny)).a > 0 then count=count+1 end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end end
|
|
152
|
+
if count == 0 then isolated=isolated+1; frame_isolated=frame_isolated+1 end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
if bounds ~= nil then
|
|
157
|
+
bounds.width=bounds.right-bounds.x+1 bounds.height=bounds.bottom-bounds.y+1 bounds.right=nil bounds.bottom=nil
|
|
158
|
+
else table.insert(empty_frames, frame_number) end
|
|
159
|
+
local hash = table.concat(hash_parts)
|
|
160
|
+
if duplicate_map[hash] == nil then duplicate_map[hash] = {frame_number}
|
|
161
|
+
else table.insert(duplicate_map[hash], frame_number) end
|
|
162
|
+
table.insert(frame_rows, {
|
|
163
|
+
frame=frame_number,
|
|
164
|
+
duration_ms=math.floor(sprite.frames[frame_number].duration*1000+0.5),
|
|
165
|
+
occupied_pixels=occupied,
|
|
166
|
+
occupancy=occupied/(sprite.width*sprite.height),
|
|
167
|
+
alpha_bounds=bounds,
|
|
168
|
+
semi_transparent_pixels=frame_semi,
|
|
169
|
+
isolated_pixels=frame_isolated,
|
|
170
|
+
})
|
|
171
|
+
end
|
|
172
|
+
local duplicates = {}
|
|
173
|
+
for _, frames in pairs(duplicate_map) do if #frames > 1 then table.insert(duplicates, frames) end end
|
|
174
|
+
local palette = {}
|
|
175
|
+
local unused_palette = {}
|
|
176
|
+
local duplicate_palette = {}
|
|
177
|
+
if #sprite.palettes > 0 then
|
|
178
|
+
local seen = {}
|
|
179
|
+
local pal = sprite.palettes[1]
|
|
180
|
+
for index=0,#pal-1 do
|
|
181
|
+
local c=pal:getColor(index)
|
|
182
|
+
local hex=rgba_hex({r=c.red,g=c.green,b=c.blue,a=(index==sprite.transparentColor and 0 or c.alpha)})
|
|
183
|
+
table.insert(palette,{index=index,color=hex})
|
|
184
|
+
if colors[hex] == nil then table.insert(unused_palette,index) end
|
|
185
|
+
if seen[hex] ~= nil then table.insert(duplicate_palette,{index=index,duplicate_of=seen[hex],color=hex}) else seen[hex]=index end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
local overlapping_tags = {}
|
|
189
|
+
for i=1,#sprite.tags do for j=i+1,#sprite.tags do
|
|
190
|
+
local a=sprite.tags[i] local b=sprite.tags[j]
|
|
191
|
+
if a.fromFrame.frameNumber <= b.toFrame.frameNumber and b.fromFrame.frameNumber <= a.toFrame.frameNumber then
|
|
192
|
+
table.insert(overlapping_tags,{first=a.name,second=b.name})
|
|
193
|
+
end
|
|
194
|
+
end end
|
|
195
|
+
local linked_groups = 0
|
|
196
|
+
for _, count in pairs(linked_images) do if count > 1 then linked_groups=linked_groups+1 end end
|
|
197
|
+
if #empty_frames > 0 then table.insert(issues,{severity="warning",code="empty_frames",frames=empty_frames}) end
|
|
198
|
+
if #duplicates > 0 then table.insert(issues,{severity="info",code="duplicate_frames",groups=duplicates}) end
|
|
199
|
+
if semi > 0 then table.insert(issues,{severity="warning",code="semi_transparent_pixels",count=semi}) end
|
|
200
|
+
if isolated > 0 then table.insert(issues,{severity="info",code="isolated_pixels",count=isolated}) end
|
|
201
|
+
if #unused_palette > 0 then table.insert(issues,{severity="info",code="unused_palette_entries",indices=unused_palette}) end
|
|
202
|
+
if #duplicate_palette > 0 then table.insert(issues,{severity="info",code="duplicate_palette_entries",entries=duplicate_palette}) end
|
|
203
|
+
if #overlapping_tags > 0 then table.insert(issues,{severity="warning",code="overlapping_tags",pairs=overlapping_tags}) end
|
|
204
|
+
if #sprite.tags == 0 and #sprite.frames > 1 then table.insert(issues,{severity="warning",code="animation_without_tags"}) end
|
|
205
|
+
local average_occupancy = occupied_total / (sprite.width*sprite.height*#sprite.frames)
|
|
206
|
+
if average_occupancy < 0.05 then table.insert(issues,{severity="info",code="oversized_canvas",average_occupancy=average_occupancy}) end
|
|
207
|
+
emit_result({
|
|
208
|
+
file=${luaString(file.relative)}, width=sprite.width, height=sprite.height,
|
|
209
|
+
frames=frame_rows, issues=issues, colors_used=colors, palette=palette,
|
|
210
|
+
linked_cel_groups=linked_groups, average_occupancy=average_occupancy,
|
|
211
|
+
})
|
|
212
|
+
sprite:close()
|
|
213
|
+
`);
|
|
214
|
+
return textResponse(result);
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
return errorResponse(error instanceof Error ? error.message : String(error));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
export async function asepriteCompareDocuments(config, registry, input) {
|
|
221
|
+
try {
|
|
222
|
+
const reference = workspacePath(registry, input.workspaceId, input.referencePath);
|
|
223
|
+
const candidate = workspacePath(registry, input.workspaceId, input.candidatePath);
|
|
224
|
+
const result = await runLua(config, registry, input.workspaceId, `
|
|
225
|
+
local reference = app.open(${luaString(reference.absolute)})
|
|
226
|
+
if reference == nil then fail("Unable to open reference sprite") end
|
|
227
|
+
local candidate = app.open(${luaString(candidate.absolute)})
|
|
228
|
+
if candidate == nil then fail("Unable to open candidate sprite") end
|
|
229
|
+
if math.max(reference.width,candidate.width)*math.max(reference.height,candidate.height)*math.max(#reference.frames,#candidate.frames) > ${MAX_ANALYSIS_PIXELS} then fail("Documents are too large for full comparison") end
|
|
230
|
+
local differences = {}
|
|
231
|
+
local function add(code, expected, actual) table.insert(differences,{code=code,expected=expected,actual=actual}) end
|
|
232
|
+
if reference.width ~= candidate.width then add("width",reference.width,candidate.width) end
|
|
233
|
+
if reference.height ~= candidate.height then add("height",reference.height,candidate.height) end
|
|
234
|
+
if reference.colorMode ~= candidate.colorMode then add("color_mode",color_mode_name(reference.colorMode),color_mode_name(candidate.colorMode)) end
|
|
235
|
+
if #reference.frames ~= #candidate.frames then add("frame_count",#reference.frames,#candidate.frames) end
|
|
236
|
+
local ref_summary=sprite_summary(reference)
|
|
237
|
+
local cand_summary=sprite_summary(candidate)
|
|
238
|
+
local function encode(value) return json.encode(value) end
|
|
239
|
+
if encode(ref_summary.layers) ~= encode(cand_summary.layers) then add("layers",ref_summary.layers,cand_summary.layers) end
|
|
240
|
+
if encode(ref_summary.frames) ~= encode(cand_summary.frames) then add("frame_timing",ref_summary.frames,cand_summary.frames) end
|
|
241
|
+
if encode(ref_summary.tags) ~= encode(cand_summary.tags) then add("tags",ref_summary.tags,cand_summary.tags) end
|
|
242
|
+
if encode(ref_summary.slices) ~= encode(cand_summary.slices) then add("slices",ref_summary.slices,cand_summary.slices) end
|
|
243
|
+
local palette_changes = {}
|
|
244
|
+
local ref_pal = #reference.palettes > 0 and reference.palettes[1] or nil
|
|
245
|
+
local cand_pal = #candidate.palettes > 0 and candidate.palettes[1] or nil
|
|
246
|
+
local pal_count = math.max(ref_pal and #ref_pal or 0,cand_pal and #cand_pal or 0)
|
|
247
|
+
for index=0,pal_count-1 do
|
|
248
|
+
local a=ref_pal and index<#ref_pal and ref_pal:getColor(index) or nil
|
|
249
|
+
local b=cand_pal and index<#cand_pal and cand_pal:getColor(index) or nil
|
|
250
|
+
local ah=a and rgba_hex({r=a.red,g=a.green,b=a.blue,a=a.alpha}) or nil
|
|
251
|
+
local bh=b and rgba_hex({r=b.red,g=b.green,b=b.blue,a=b.alpha}) or nil
|
|
252
|
+
if ah~=bh then table.insert(palette_changes,{index=index,reference=ah,candidate=bh}) end
|
|
253
|
+
end
|
|
254
|
+
local pixel_frames = {}
|
|
255
|
+
local changed_total = 0
|
|
256
|
+
if ${input.comparePixels === false ? "false" : "true"} then
|
|
257
|
+
local max_frames=math.max(#reference.frames,#candidate.frames)
|
|
258
|
+
local max_width=math.max(reference.width,candidate.width)
|
|
259
|
+
local max_height=math.max(reference.height,candidate.height)
|
|
260
|
+
for frame=1,max_frames do
|
|
261
|
+
local a=Image{width=max_width,height=max_height,colorMode=ColorMode.RGB}
|
|
262
|
+
local b=Image{width=max_width,height=max_height,colorMode=ColorMode.RGB}
|
|
263
|
+
a:clear() b:clear()
|
|
264
|
+
if frame<=#reference.frames then a:drawSprite(reference,frame,Point(0,0)) end
|
|
265
|
+
if frame<=#candidate.frames then b:drawSprite(candidate,frame,Point(0,0)) end
|
|
266
|
+
local changed=0
|
|
267
|
+
local bounds=nil
|
|
268
|
+
for y=0,max_height-1 do for x=0,max_width-1 do
|
|
269
|
+
if a:getPixel(x,y) ~= b:getPixel(x,y) then
|
|
270
|
+
changed=changed+1 changed_total=changed_total+1
|
|
271
|
+
if bounds==nil then bounds={x=x,y=y,right=x,bottom=y}
|
|
272
|
+
else
|
|
273
|
+
if x<bounds.x then bounds.x=x end if y<bounds.y then bounds.y=y end
|
|
274
|
+
if x>bounds.right then bounds.right=x end if y>bounds.bottom then bounds.bottom=y end
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end end
|
|
278
|
+
if bounds~=nil then bounds.width=bounds.right-bounds.x+1 bounds.height=bounds.bottom-bounds.y+1 bounds.right=nil bounds.bottom=nil end
|
|
279
|
+
table.insert(pixel_frames,{frame=frame,changed_pixels=changed,bounds=bounds})
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
emit_result({
|
|
283
|
+
reference=${luaString(reference.relative)},candidate=${luaString(candidate.relative)},
|
|
284
|
+
exact_match=#differences==0 and #palette_changes==0 and changed_total==0,
|
|
285
|
+
structural_differences=differences,palette_changes=palette_changes,
|
|
286
|
+
changed_pixels=changed_total,pixel_frames=pixel_frames,
|
|
287
|
+
})
|
|
288
|
+
reference:close() candidate:close()
|
|
289
|
+
`);
|
|
290
|
+
return textResponse(result);
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
return errorResponse(error instanceof Error ? error.message : String(error));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
export async function asepriteAnimationAudit(config, registry, input) {
|
|
297
|
+
try {
|
|
298
|
+
const file = workspacePath(registry, input.workspaceId, input.filePath);
|
|
299
|
+
const result = await runLua(config, registry, input.workspaceId, `
|
|
300
|
+
${openSpriteScript(file.absolute)}
|
|
301
|
+
if sprite.width*sprite.height*#sprite.frames > ${MAX_ANALYSIS_PIXELS} then fail("Animation is too large for a full audit") end
|
|
302
|
+
local from_frame=1 local to_frame=#sprite.frames
|
|
303
|
+
${input.tag ? `
|
|
304
|
+
local selected_tag=nil
|
|
305
|
+
for _,tag in ipairs(sprite.tags) do if tag.name==${luaString(input.tag)} then selected_tag=tag break end end
|
|
306
|
+
if selected_tag==nil then fail("Animation tag was not found") end
|
|
307
|
+
from_frame=selected_tag.fromFrame.frameNumber to_frame=selected_tag.toFrame.frameNumber
|
|
308
|
+
` : ""}
|
|
309
|
+
local anchor_layer=${input.anchorLayer ? `find_layer(sprite.layers,${luaString(input.anchorLayer)})` : "nil"}
|
|
310
|
+
if ${input.anchorLayer ? "true" : "false"} and (anchor_layer==nil or anchor_layer.isGroup) then fail("Anchor layer was not found") end
|
|
311
|
+
local frames={}
|
|
312
|
+
local previous=nil
|
|
313
|
+
local first=nil
|
|
314
|
+
local duplicate_pairs={}
|
|
315
|
+
local duration_sum=0
|
|
316
|
+
for frame=from_frame,to_frame do
|
|
317
|
+
local render=Image(sprite.spec) render:clear() render:drawSprite(sprite,frame,Point(0,0))
|
|
318
|
+
local bounds=nil local occupied=0 local sum_x=0 local sum_y=0 local changed=0
|
|
319
|
+
local anchor_bounds=nil
|
|
320
|
+
for y=0,sprite.height-1 do for x=0,sprite.width-1 do
|
|
321
|
+
local c=pixel_rgba(sprite,render:getPixel(x,y))
|
|
322
|
+
if c.a>0 then
|
|
323
|
+
occupied=occupied+1 sum_x=sum_x+x sum_y=sum_y+y
|
|
324
|
+
if bounds==nil then bounds={x=x,y=y,right=x,bottom=y}
|
|
325
|
+
else if x<bounds.x then bounds.x=x end if y<bounds.y then bounds.y=y end if x>bounds.right then bounds.right=x end if y>bounds.bottom then bounds.bottom=y end end
|
|
326
|
+
end
|
|
327
|
+
if previous~=nil and render:getPixel(x,y)~=previous:getPixel(x,y) then changed=changed+1 end
|
|
328
|
+
if anchor_layer~=nil then
|
|
329
|
+
local ac=canvas_pixel(sprite,anchor_layer,frame,x,y)
|
|
330
|
+
if ac.a>0 then
|
|
331
|
+
if anchor_bounds==nil then anchor_bounds={x=x,y=y,right=x,bottom=y}
|
|
332
|
+
else if x<anchor_bounds.x then anchor_bounds.x=x end if y<anchor_bounds.y then anchor_bounds.y=y end if x>anchor_bounds.right then anchor_bounds.right=x end if y>anchor_bounds.bottom then anchor_bounds.bottom=y end end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
end end
|
|
336
|
+
if bounds~=nil then bounds.width=bounds.right-bounds.x+1 bounds.height=bounds.bottom-bounds.y+1 bounds.center_x=sum_x/occupied bounds.center_y=sum_y/occupied bounds.right=nil bounds.bottom=nil end
|
|
337
|
+
if anchor_bounds~=nil then anchor_bounds.width=anchor_bounds.right-anchor_bounds.x+1 anchor_bounds.height=anchor_bounds.bottom-anchor_bounds.y+1 anchor_bounds.right=nil anchor_bounds.bottom=nil end
|
|
338
|
+
local duration=math.floor(sprite.frames[frame].duration*1000+0.5) duration_sum=duration_sum+duration
|
|
339
|
+
if previous~=nil and changed==0 then table.insert(duplicate_pairs,{previous=frame-1,current=frame}) end
|
|
340
|
+
table.insert(frames,{frame=frame,duration_ms=duration,bounds=bounds,anchor_bounds=anchor_bounds,changed_from_previous=changed,motion_ratio=changed/(sprite.width*sprite.height)})
|
|
341
|
+
if first==nil then first=Image(render) end previous=Image(render)
|
|
342
|
+
end
|
|
343
|
+
local loop_difference=0
|
|
344
|
+
if first~=nil and previous~=nil then for y=0,sprite.height-1 do for x=0,sprite.width-1 do if first:getPixel(x,y)~=previous:getPixel(x,y) then loop_difference=loop_difference+1 end end end end
|
|
345
|
+
local average_duration=duration_sum/#frames
|
|
346
|
+
local issues={}
|
|
347
|
+
for _,row in ipairs(frames) do
|
|
348
|
+
if row.duration_ms>average_duration*2 or row.duration_ms<average_duration*0.5 then table.insert(issues,{severity="info",code="duration_outlier",frame=row.frame,duration_ms=row.duration_ms,average_ms=average_duration}) end
|
|
349
|
+
end
|
|
350
|
+
for i=2,#frames do
|
|
351
|
+
local a=frames[i-1].bounds local b=frames[i].bounds
|
|
352
|
+
if a~=nil and b~=nil then
|
|
353
|
+
local dx=b.center_x-a.center_x local dy=b.center_y-a.center_y
|
|
354
|
+
frames[i].center_delta={x=dx,y=dy}
|
|
355
|
+
frames[i].baseline_delta=b.y+b.height-(a.y+a.height)
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
if #duplicate_pairs>0 then table.insert(issues,{severity="info",code="duplicate_consecutive_frames",pairs=duplicate_pairs}) end
|
|
359
|
+
if loop_difference>sprite.width*sprite.height*0.25 then table.insert(issues,{severity="warning",code="loop_discontinuity",changed_pixels=loop_difference}) end
|
|
360
|
+
emit_result({file=${luaString(file.relative)},from=from_frame,to=to_frame,frames=frames,average_duration_ms=average_duration,loop_changed_pixels=loop_difference,issues=issues})
|
|
361
|
+
sprite:close()
|
|
362
|
+
`);
|
|
363
|
+
return textResponse(result);
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
return errorResponse(error instanceof Error ? error.message : String(error));
|
|
367
|
+
}
|
|
368
|
+
}
|