summer-engine 3.1.0 → 3.2.0
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +27 -5
- package/.codex-plugin/plugin.json +28 -6
- package/.cursor-plugin/plugin.json +27 -5
- package/.factory-plugin/plugin.json +27 -5
- package/.opencode/plugins/summer.js +1 -1
- package/CHANGELOG.md +102 -0
- package/README.md +18 -3
- package/assets/audit/scene_audit.gd +4136 -0
- package/assets/seeing/seeing_probe.gd +1873 -0
- package/dist/cli/commands/skills.js +20 -2
- package/dist/core/api-client.d.ts +9 -1
- package/dist/core/api-client.js +21 -4
- package/dist/core/capabilities/agent-playbook.js +46 -0
- package/dist/core/capabilities/audit/accept.d.ts +55 -0
- package/dist/core/capabilities/audit/accept.js +147 -0
- package/dist/core/capabilities/audit/args.d.ts +95 -0
- package/dist/core/capabilities/audit/args.js +89 -0
- package/dist/core/capabilities/audit/audit.d.ts +56 -0
- package/dist/core/capabilities/audit/audit.js +287 -0
- package/dist/core/capabilities/audit/frame.d.ts +14 -0
- package/dist/core/capabilities/audit/frame.js +35 -0
- package/dist/core/capabilities/audit/gaps.d.ts +96 -0
- package/dist/core/capabilities/audit/gaps.js +257 -0
- package/dist/core/capabilities/audit/judge.d.ts +162 -0
- package/dist/core/capabilities/audit/judge.js +1134 -0
- package/dist/core/capabilities/audit/math.d.ts +110 -0
- package/dist/core/capabilities/audit/math.js +263 -0
- package/dist/core/capabilities/audit/summary.d.ts +74 -0
- package/dist/core/capabilities/audit/summary.js +212 -0
- package/dist/core/capabilities/board.d.ts +31 -0
- package/dist/core/capabilities/board.js +43 -0
- package/dist/core/capabilities/camera-view.d.ts +4 -2
- package/dist/core/capabilities/camera-view.js +6 -3
- package/dist/core/capabilities/connect-signal.d.ts +85 -0
- package/dist/core/capabilities/connect-signal.js +285 -0
- package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
- package/dist/core/capabilities/engine-fallbacks.js +5 -0
- package/dist/core/capabilities/engine-ops.d.ts +5 -1
- package/dist/core/capabilities/engine-ops.js +0 -3
- package/dist/core/capabilities/engine-receipt.d.ts +12 -0
- package/dist/core/capabilities/engine-receipt.js +26 -0
- package/dist/core/capabilities/file-read.d.ts +64 -0
- package/dist/core/capabilities/file-read.js +325 -0
- package/dist/core/capabilities/game-task-plan.js +4 -2
- package/dist/core/capabilities/grep.d.ts +60 -0
- package/dist/core/capabilities/grep.js +190 -0
- package/dist/core/capabilities/inspect-node.d.ts +56 -0
- package/dist/core/capabilities/inspect-node.js +225 -0
- package/dist/core/capabilities/inspect-resource.d.ts +61 -0
- package/dist/core/capabilities/inspect-resource.js +376 -0
- package/dist/core/capabilities/math3d.d.ts +28 -0
- package/dist/core/capabilities/math3d.js +88 -0
- package/dist/core/capabilities/motion-generation.d.ts +62 -0
- package/dist/core/capabilities/motion-generation.js +138 -0
- package/dist/core/capabilities/placement-batch.d.ts +102 -0
- package/dist/core/capabilities/placement-batch.js +483 -0
- package/dist/core/capabilities/placement-math.d.ts +70 -0
- package/dist/core/capabilities/placement-math.js +209 -0
- package/dist/core/capabilities/placement-script.d.ts +42 -0
- package/dist/core/capabilities/placement-script.js +1096 -0
- package/dist/core/capabilities/placement.d.ts +485 -0
- package/dist/core/capabilities/placement.js +1731 -0
- package/dist/core/capabilities/project-context.d.ts +33 -2
- package/dist/core/capabilities/project-context.js +87 -4
- package/dist/core/capabilities/replace-node.d.ts +91 -0
- package/dist/core/capabilities/replace-node.js +423 -0
- package/dist/core/capabilities/runtime-control.d.ts +18 -2
- package/dist/core/capabilities/runtime-control.js +67 -2
- package/dist/core/capabilities/scene-batch.d.ts +63 -0
- package/dist/core/capabilities/scene-batch.js +394 -0
- package/dist/core/capabilities/scene-readback.d.ts +36 -0
- package/dist/core/capabilities/scene-readback.js +54 -0
- package/dist/core/capabilities/seeing/args.d.ts +348 -0
- package/dist/core/capabilities/seeing/args.js +178 -0
- package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
- package/dist/core/capabilities/seeing/candidates.js +282 -0
- package/dist/core/capabilities/seeing/math.d.ts +134 -0
- package/dist/core/capabilities/seeing/math.js +269 -0
- package/dist/core/capabilities/seeing/probe.d.ts +62 -0
- package/dist/core/capabilities/seeing/probe.js +188 -0
- package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
- package/dist/core/capabilities/seeing/scoring.js +639 -0
- package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
- package/dist/core/capabilities/seeing/seeing.js +1341 -0
- package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
- package/dist/core/capabilities/seeing/shot-store.js +204 -0
- package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
- package/dist/core/capabilities/surface-snap-mesh.js +425 -0
- package/dist/core/capabilities/surface-snap.d.ts +77 -0
- package/dist/core/capabilities/surface-snap.js +461 -0
- package/dist/core/capabilities/tool-dispatch.js +231 -72
- package/dist/core/capabilities/tscn.d.ts +85 -0
- package/dist/core/capabilities/tscn.js +391 -0
- package/dist/core/capabilities/world-snapshot.d.ts +58 -0
- package/dist/core/capabilities/world-snapshot.js +150 -0
- package/dist/core/capability-skew.d.ts +5 -5
- package/dist/core/capability-skew.js +14 -6
- package/dist/core/headless/worker-engine-client.d.ts +1 -1
- package/dist/core/headless/worker-engine-client.js +2 -2
- package/dist/core/library-read.d.ts +37 -5
- package/dist/core/library-read.js +264 -33
- package/dist/core/library-search.d.ts +2 -2
- package/dist/installer/agent-config.js +5 -3
- package/dist/installer/agent-table.d.ts +16 -0
- package/dist/installer/agent-table.js +52 -17
- package/dist/mcp/server.js +9 -3
- package/dist/mcp/tools/asset-tools.js +21 -3
- package/dist/mcp/tools/audit-tools.d.ts +23 -0
- package/dist/mcp/tools/audit-tools.js +60 -0
- package/dist/mcp/tools/debug-tools.js +3 -1
- package/dist/mcp/tools/file-tools.js +17 -4
- package/dist/mcp/tools/generate-tools.js +74 -66
- package/dist/mcp/tools/library-tools.js +2 -0
- package/dist/mcp/tools/perception-tools.js +6 -19
- package/dist/mcp/tools/placement-tools.d.ts +24 -0
- package/dist/mcp/tools/placement-tools.js +91 -0
- package/dist/mcp/tools/project-tools.js +18 -15
- package/dist/mcp/tools/scene-tools.js +71 -83
- package/dist/mcp/tools/seeing-tools.d.ts +24 -0
- package/dist/mcp/tools/seeing-tools.js +64 -0
- package/dist/mcp/tools/spatial-tools.js +17 -9
- package/dist/mcp/tools/visual-tools.js +59 -7
- package/gemini-extension.json +26 -4
- package/integrations/amp/README.md +1 -1
- package/integrations/crush/README.md +1 -1
- package/integrations/grok-build/README.md +1 -1
- package/integrations/hermes/README.md +1 -1
- package/integrations/kimi-code/README.md +1 -1
- package/integrations/mistral-vibe/README.md +1 -1
- package/integrations/opencode/README.md +1 -1
- package/integrations/rovo-dev/README.md +1 -1
- package/integrations/vscode-copilot/README.md +1 -1
- package/integrations/warp/README.md +1 -1
- package/integrations/windsurf/README.md +1 -1
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/references/summer-folder/resource.yaml +1 -1
- package/library/references/summer-folder/summer-folder.md +1 -1
- package/library/skills/3d-lighting/SKILL.md +1 -1
- package/library/skills/README.md +36 -14
- package/library/skills/adaptive-music/SKILL.md +1 -1
- package/library/skills/agent-playtesting/SKILL.md +1 -1
- package/library/skills/ai-characters-in-games/SKILL.md +220 -0
- package/library/skills/ai-characters-in-games/resource.yaml +30 -0
- package/library/skills/ambient-bed/SKILL.md +1 -1
- package/library/skills/animated-loop/SKILL.md +1 -1
- package/library/skills/animation-tree/SKILL.md +1 -1
- package/library/skills/art-direction/SKILL.md +1 -1
- package/library/skills/asset-strategy/SKILL.md +2 -1
- package/library/skills/asset-strategy/resource.yaml +2 -1
- package/library/skills/audio-direction/SKILL.md +1 -1
- package/library/skills/auto-fire-targeting/SKILL.md +1 -1
- package/library/skills/brainstorm-game/SKILL.md +1 -1
- package/library/skills/brainstorming/SKILL.md +1 -1
- package/library/skills/browse-templates/SKILL.md +3 -3
- package/library/skills/browse-templates/resource.yaml +1 -1
- package/library/skills/camera-rigs/SKILL.md +128 -0
- package/library/skills/camera-rigs/resource.yaml +29 -0
- package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
- package/library/skills/character-animation-wiring/SKILL.md +1 -1
- package/library/skills/character-model/SKILL.md +1 -1
- package/library/skills/character-movement/SKILL.md +326 -0
- package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
- package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
- package/library/skills/character-movement/references/movement-3d.md +136 -0
- package/library/skills/character-movement/references/platformer-feel.md +83 -0
- package/library/skills/character-movement/resource.yaml +40 -0
- package/library/skills/character-portrait/SKILL.md +1 -1
- package/library/skills/cinematic-cutscene/SKILL.md +1 -1
- package/library/skills/combat-basics/SKILL.md +159 -0
- package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
- package/library/skills/combat-basics/resource.yaml +34 -0
- package/library/skills/concept-art/SKILL.md +1 -1
- package/library/skills/create-asset-sheet/SKILL.md +1 -1
- package/library/skills/debug/SKILL.md +1 -1
- package/library/skills/debugging-game-feel/SKILL.md +1 -1
- package/library/skills/design-level/SKILL.md +1 -1
- package/library/skills/design-mechanic/SKILL.md +1 -1
- package/library/skills/design-npc/SKILL.md +1 -1
- package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
- package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
- package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
- package/library/skills/environment-kit/SKILL.md +1 -1
- package/library/skills/export-and-ship/SKILL.md +1 -1
- package/library/skills/fabricating-assets/SKILL.md +1 -1
- package/library/skills/facial-and-lipsync/SKILL.md +1 -1
- package/library/skills/fps-controller/SKILL.md +9 -7
- package/library/skills/fps-controller/resource.yaml +4 -1
- package/library/skills/game-feel/SKILL.md +1 -1
- package/library/skills/gameskill/SKILL.md +1 -1
- package/library/skills/gdscript-patterns/SKILL.md +1 -1
- package/library/skills/generate-motion/SKILL.md +9 -9
- package/library/skills/generate-motion/resource.yaml +2 -1
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
- package/library/skills/headless-scripting/SKILL.md +1 -1
- package/library/skills/in-game-purchases/SKILL.md +254 -0
- package/library/skills/in-game-purchases/resource.yaml +29 -0
- package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
- package/library/skills/investigating-bugs/SKILL.md +1 -1
- package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
- package/library/skills/make-game/SKILL.md +25 -3
- package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
- package/library/skills/make-game/references/2d-platformer.md +117 -0
- package/library/skills/make-game/references/2d-rpg-content.md +234 -0
- package/library/skills/make-game/references/2d-rpg.md +241 -0
- package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
- package/library/skills/make-game/references/2d-survivors.md +237 -0
- package/library/skills/make-game/references/3d-fps-systems.md +216 -0
- package/library/skills/make-game/references/3d-fps.md +177 -0
- package/library/skills/make-game/references/3d-horror-systems.md +186 -0
- package/library/skills/make-game/references/3d-horror.md +201 -0
- package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
- package/library/skills/make-game/references/3d-third-person.md +215 -0
- package/library/skills/make-game/resource.yaml +6 -1
- package/library/skills/multiplayer/SKILL.md +150 -0
- package/library/skills/multiplayer/resource.yaml +33 -0
- package/library/skills/multiplayer-movement/SKILL.md +510 -0
- package/library/skills/multiplayer-movement/files.md +501 -0
- package/library/skills/multiplayer-movement/resource.yaml +30 -0
- package/library/skills/multiplayer-project/SKILL.md +521 -0
- package/library/skills/multiplayer-project/files.md +448 -0
- package/library/skills/multiplayer-project/resource.yaml +36 -0
- package/library/skills/multiplayer-publish/SKILL.md +229 -0
- package/library/skills/multiplayer-publish/export-errors.md +89 -0
- package/library/skills/multiplayer-publish/resource.yaml +28 -0
- package/library/skills/multiplayer-state/SKILL.md +438 -0
- package/library/skills/multiplayer-state/files.md +592 -0
- package/library/skills/multiplayer-state/resource.yaml +35 -0
- package/library/skills/multiplayer-testing/SKILL.md +236 -0
- package/library/skills/multiplayer-testing/resource.yaml +39 -0
- package/library/skills/music-track/SKILL.md +1 -1
- package/library/skills/navigate-summer/SKILL.md +1 -1
- package/library/skills/new-project/SKILL.md +1 -1
- package/library/skills/organic-model/SKILL.md +1 -1
- package/library/skills/pixel-art/SKILL.md +1 -1
- package/library/skills/play/SKILL.md +1 -1
- package/library/skills/playtesting-a-feature/SKILL.md +1 -1
- package/library/skills/procedural-animation/SKILL.md +2 -2
- package/library/skills/procedural-animation/resource.yaml +1 -1
- package/library/skills/prop-model/SKILL.md +1 -1
- package/library/skills/psx-retro-rendering/SKILL.md +1 -1
- package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
- package/library/skills/remote-deploy/SKILL.md +1 -1
- package/library/skills/retarget/SKILL.md +1 -1
- package/library/skills/running-in-the-cloud/SKILL.md +1 -1
- package/library/skills/save-load/SKILL.md +156 -0
- package/library/skills/save-load/resource.yaml +27 -0
- package/library/skills/scene-composition/SKILL.md +1 -1
- package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
- package/library/skills/scene-scripting/SKILL.md +1 -1
- package/library/skills/scene-to-level/SKILL.md +1 -1
- package/library/skills/skill-create/SKILL.md +1 -1
- package/library/skills/skill-improve/SKILL.md +1 -1
- package/library/skills/skill-test/SKILL.md +1 -1
- package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
- package/library/skills/skybox-panorama/SKILL.md +1 -1
- package/library/skills/sound-effect/SKILL.md +1 -1
- package/library/skills/spatial-placement/SKILL.md +134 -3
- package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
- package/library/skills/spatial-placement/resource.yaml +16 -2
- package/library/skills/sprite-sheet/SKILL.md +1 -1
- package/library/skills/summer-analytics/SKILL.md +147 -0
- package/library/skills/summer-analytics/resource.yaml +28 -0
- package/library/skills/summer-friends/SKILL.md +226 -0
- package/library/skills/summer-friends/resource.yaml +28 -0
- package/library/skills/summer-leaderboards/SKILL.md +231 -0
- package/library/skills/summer-leaderboards/resource.yaml +30 -0
- package/library/skills/summer-match-results/SKILL.md +286 -0
- package/library/skills/summer-match-results/resource.yaml +32 -0
- package/library/skills/summer-matchmaking/SKILL.md +301 -0
- package/library/skills/summer-matchmaking/resource.yaml +32 -0
- package/library/skills/summer-parties/SKILL.md +253 -0
- package/library/skills/summer-parties/resource.yaml +30 -0
- package/library/skills/summer-player-data/SKILL.md +322 -0
- package/library/skills/summer-player-data/resource.yaml +30 -0
- package/library/skills/summer-store/SKILL.md +271 -0
- package/library/skills/summer-store/resource.yaml +29 -0
- package/library/skills/summer-world-chat/SKILL.md +195 -0
- package/library/skills/summer-world-chat/resource.yaml +30 -0
- package/library/skills/summer-world-saves/SKILL.md +284 -0
- package/library/skills/summer-world-saves/resource.yaml +29 -0
- package/library/skills/text-to-motion/SKILL.md +99 -0
- package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
- package/library/skills/text-to-motion/resource.yaml +41 -0
- package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
- package/library/skills/tileable-texture/SKILL.md +1 -1
- package/library/skills/trailer-shot/SKILL.md +1 -1
- package/library/skills/tune-performance/SKILL.md +1 -1
- package/library/skills/ui-basics/SKILL.md +10 -1
- package/library/skills/ui-graphics/SKILL.md +1 -1
- package/library/skills/use-widget-asset/SKILL.md +1 -1
- package/library/skills/using-summer/SKILL.md +2 -2
- package/library/skills/using-summer/resource.yaml +2 -2
- package/library/skills/vehicle-model/SKILL.md +1 -1
- package/library/skills/verification-before-completion/SKILL.md +1 -1
- package/library/skills/verifying-scenes/SKILL.md +76 -2
- package/library/skills/verifying-scenes/resource.yaml +13 -2
- package/library/skills/vfx-dissolve/SKILL.md +1 -1
- package/library/skills/vfx-fire/SKILL.md +1 -1
- package/library/skills/vfx-hit-spark/SKILL.md +1 -1
- package/library/skills/vfx-lightning/SKILL.md +1 -1
- package/library/skills/vfx-magic-glow/SKILL.md +1 -1
- package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
- package/library/skills/vfx-smoke/SKILL.md +1 -1
- package/library/skills/vfx-water-ripple/SKILL.md +1 -1
- package/library/skills/voice-line/SKILL.md +1 -1
- package/library/skills/web-and-touch-input/SKILL.md +38 -0
- package/library/skills/web-and-touch-input/resource.yaml +28 -0
- package/library/skills/web-compatibility-look/SKILL.md +62 -0
- package/library/skills/web-compatibility-look/resource.yaml +30 -0
- package/library/skills/world-building-3d/SKILL.md +8 -1
- package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
- package/library/skills/world-building-3d/resource.yaml +2 -1
- package/library/skills/writing-plans/SKILL.md +1 -1
- package/library/skills/writing-skills/SKILL.md +1 -1
- package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
- package/library/tools/attach-to-surface/resource.yaml +142 -0
- package/library/tools/batch/resource.yaml +9 -3
- package/library/tools/connect-ports/resource.yaml +120 -0
- package/library/tools/connect-signal/resource.yaml +3 -2
- package/library/tools/debug-views/resource.yaml +94 -0
- package/library/tools/frame-nodes/resource.yaml +104 -0
- package/library/tools/frame-shot/resource.yaml +134 -0
- package/library/tools/generate-motion/resource.yaml +44 -9
- package/library/tools/get-board/resource.yaml +50 -0
- package/library/tools/get-project-context/resource.yaml +13 -2
- package/library/tools/grep/resource.yaml +77 -0
- package/library/tools/inspect-asset/resource.yaml +71 -0
- package/library/tools/inspect-node/resource.yaml +9 -2
- package/library/tools/inspect-resource/resource.yaml +16 -5
- package/library/tools/instantiate-scene/resource.yaml +27 -2
- package/library/tools/measure/resource.yaml +96 -0
- package/library/tools/place-adjacent/resource.yaml +113 -0
- package/library/tools/play/resource.yaml +15 -2
- package/library/tools/raycast/resource.yaml +101 -0
- package/library/tools/read-file/resource.yaml +36 -2
- package/library/tools/read-library/resource.yaml +2 -2
- package/library/tools/repeat-along/resource.yaml +129 -0
- package/library/tools/replace-node/resource.yaml +11 -5
- package/library/tools/scene-audit/resource.yaml +144 -0
- package/library/tools/screenshot/resource.yaml +13 -2
- package/library/tools/search-assets/resource.yaml +18 -0
- package/library/tools/shot-sheet/resource.yaml +110 -0
- package/library/tools/snap-to-surface/resource.yaml +4 -1
- package/library/tools/world-snapshot/resource.yaml +24 -3
- package/library/tools/zoom/resource.yaml +105 -0
- package/package.json +1 -1
- package/registry/generated/aliases.json +17 -3
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +26 -4
- package/registry/generated/index.json +2154 -469
- package/registry/generated/marketplace.claude.json +2 -2
- package/registry/generated/plugin.claude.json +27 -5
- package/registry/generated/plugin.codex.json +28 -6
- package/registry/generated/plugin.cursor.json +27 -5
- package/registry/generated/plugin.factory.json +27 -5
- package/registry/generated/skills-index.md +36 -14
- package/registry/generated/skills-registry.json +421 -124
- package/registry/generated/templates-registry.json +2 -2
- package/library/skills/host-authoritative-state/SKILL.md +0 -332
- package/library/skills/host-authoritative-state/resource.yaml +0 -28
- package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
- package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
- package/library/skills/setup-multiplayer/SKILL.md +0 -336
- package/library/skills/setup-multiplayer/resource.yaml +0 -28
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scene-to-level
|
|
3
|
-
description:
|
|
3
|
+
description: "Go from a scene reference image or concept art to a playable scene — orchestrates concept, asset pack, terrain, composition, and scene assembly."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: level-design
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skill-create
|
|
3
|
-
description:
|
|
3
|
+
description: "Bootstrap a new Summer library skill (library/skills/<slug>/ with resource.yaml and SKILL.md), frontmatter, and stub sections."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: workflow
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skill-improve
|
|
3
|
-
description:
|
|
3
|
+
description: "Upgrade an underperforming Summer skill — run it against a behavioral spec with and without changes via a parallel-eval harness; ship the winner."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: workflow
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skill-test
|
|
3
|
-
description:
|
|
3
|
+
description: "Lint a Summer skill before commit, audit the whole library, or check a behavioral spec assertion — static structural rules plus behavioral specs."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: workflow
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skintokens-auto-rigging
|
|
3
|
-
description: "
|
|
3
|
+
description: "Offline auto-rigging with skin-tokens.cpp (GGML SkinTokens/TokenRig port) — skeleton and skin weights from a static GLB mesh on CPU/Vulkan, into Godot 4."
|
|
4
4
|
license: MIT
|
|
5
5
|
category: art-pipeline
|
|
6
6
|
tags:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skybox-panorama
|
|
3
|
-
description:
|
|
3
|
+
description: "Generate a 360-degree equirectangular sky panorama and wire it as a PanoramaSkyMaterial Sky resource on WorldEnvironment in a 3D scene."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: 2d-assets
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sound-effect
|
|
3
|
-
description:
|
|
3
|
+
description: "Generate short SFX one-shots — footsteps, weapon swings, UI clicks, hit impacts — wired as AudioStreamPlayer/2D/3D that auto-frees on finished."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: audio
|
|
@@ -1,20 +1,43 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spatial-placement
|
|
3
|
-
description:
|
|
3
|
+
description: "Place 3D objects and modular kit pieces from measured geometry — inspect, place, starcast, measure, correct; floor, wall, facade, pipe and alcove recipes."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: scene-and-project
|
|
7
7
|
user-invocable: false
|
|
8
|
-
allowed-tools: Read Grep summer_get_scene_tree summer_inspect_node summer_set_prop summer_batch summer_starcast
|
|
8
|
+
allowed-tools: Read Grep summer_get_scene_tree summer_inspect_node summer_set_prop summer_batch summer_starcast summer_inspect_asset summer_instantiate_scene summer_place_adjacent summer_attach_to_surface summer_repeat_along summer_connect_ports summer_raycast summer_measure summer_test_placement summer_snap_to_surface summer_align_distribute_3d summer_world_snapshot summer_snapshot_diff summer_screenshot
|
|
9
9
|
paths: ["**/*.tscn"]
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# Spatial Placement in Summer Engine
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Place from measured geometry, never from guesses about size or facing. Use
|
|
15
|
+
Starcast as spatial evidence, not as an automatic placement solver. Make a
|
|
15
16
|
reasonable transform from scene intent, inspect the result, then correct only
|
|
16
17
|
the axes that the evidence shows are wrong.
|
|
17
18
|
|
|
19
|
+
Every tool below is already shipped. Arguments, result shapes, limits and the
|
|
20
|
+
engine ops behind them: [references/kit-placement-tools.md](references/kit-placement-tools.md).
|
|
21
|
+
|
|
22
|
+
## Choose the tool
|
|
23
|
+
|
|
24
|
+
| Question | Tool |
|
|
25
|
+
|---|---|
|
|
26
|
+
| Size, origin, front/back plane, pipe ends of a piece not yet placed? | `summer_inspect_asset` |
|
|
27
|
+
| Place one piece at an exact pose | `summer_instantiate_scene` with `position`, `rotation_degrees` |
|
|
28
|
+
| Place many pieces, read the receipt | `summer_batch`, placed `InstantiateScene` ops, `receipt: "summary"` |
|
|
29
|
+
| Next module edge to edge, next storey on top | `summer_place_adjacent` |
|
|
30
|
+
| Pipe, lamp, AC unit or sign on a wall | `summer_attach_to_surface` |
|
|
31
|
+
| Clamps, braces, posts or windows along a line | `summer_repeat_along` |
|
|
32
|
+
| Pipe or duct end to end | `summer_connect_ports` |
|
|
33
|
+
| Surface and normal in front of a point | `summer_raycast` |
|
|
34
|
+
| Gap or overlap between two pieces; fronts flush? | `summer_measure` |
|
|
35
|
+
| What surrounds a placed piece, which side is blocked? | `summer_starcast` |
|
|
36
|
+
| Will this pose fit in a tight spot? | `summer_test_placement` before committing |
|
|
37
|
+
| Seat a prop on a floor, table or ledge | `summer_snap_to_surface` |
|
|
38
|
+
| Line up or space 2-16 placed pieces on one axis | `summer_align_distribute_3d` |
|
|
39
|
+
| Did exactly that change, does it look right? | `summer_world_snapshot` + `summer_snapshot_diff`, `summer_screenshot` |
|
|
40
|
+
|
|
18
41
|
## Placement loop
|
|
19
42
|
|
|
20
43
|
1. Call `summer_get_scene_tree` and inspect the subject and intended anchor.
|
|
@@ -46,6 +69,94 @@ defined relative to a rotated subject; then use `directionSpace="local"`.
|
|
|
46
69
|
- Warnings about missing collision shapes or visual bounds mean coverage is
|
|
47
70
|
partial; state that limitation rather than inventing certainty.
|
|
48
71
|
|
|
72
|
+
## Modular kit placement
|
|
73
|
+
|
|
74
|
+
1. `summer_inspect_asset` every piece type once and read its `summary` first:
|
|
75
|
+
size, where the origin sits (`origin.label`), the two largest opposite plane
|
|
76
|
+
pairs (a large `+z` plane at the max z offset means the visible face looks
|
|
77
|
+
along +z and the back is `-z`; a `one_sided` sheet with no opposite plane
|
|
78
|
+
is invisible from behind), port-like loops (pipe and duct ends), anchors
|
|
79
|
+
and colliders. Read the kit's own notes too, but trust the
|
|
80
|
+
measurement.
|
|
81
|
+
2. `summer_world_snapshot`; keep the `snapshot_id`.
|
|
82
|
+
3. Place the first piece of a line with `summer_instantiate_scene` and its
|
|
83
|
+
`position` / `rotation_degrees`. Place the rest relative to it:
|
|
84
|
+
`summer_place_adjacent` along the line, again along `y` for the next storey.
|
|
85
|
+
For many pieces at known poses use one `summer_batch` with
|
|
86
|
+
`receipt: "summary"`.
|
|
87
|
+
4. Mount wall pieces with `summer_attach_to_surface`, using the back axis from
|
|
88
|
+
step 1. Instance each at its mount height first: the tool keeps the height
|
|
89
|
+
and pushes the piece's back face onto the wall, and refuses (putting the
|
|
90
|
+
piece back) when the seat lands on another node. Join pipe and duct runs
|
|
91
|
+
with `summer_connect_ports`; its `other_ports` says where a bend's free end
|
|
92
|
+
now points. Add clamps and braces with `summer_repeat_along`.
|
|
93
|
+
5. Check: `summer_measure` plane mode on each facade line (every front on one
|
|
94
|
+
plane), pair mode on joints you doubt, `summer_starcast` with
|
|
95
|
+
`directionSpace: "local"` on mounted pieces, `summer_test_placement` before
|
|
96
|
+
committing a piece in a tight spot. Starcast's local names follow Godot:
|
|
97
|
+
`forward` is -Z, `back` is +Z. A piece with a -Z back should read
|
|
98
|
+
`forward` blocked by the wall at about the standoff (or the wall in
|
|
99
|
+
`contacts` when flush) and `back` open.
|
|
100
|
+
6. `summer_snapshot_diff` against the id from step 2, then `summer_screenshot`
|
|
101
|
+
and look at it. Fix facing from the measurement, not by eye.
|
|
102
|
+
|
|
103
|
+
### Worked example: two-storey facade wall with a downpipe and a lamp
|
|
104
|
+
|
|
105
|
+
Pieces (measured in step 1): `wall_double` is 2 x 3 x 0.2 m, origin bottom
|
|
106
|
+
centre, front `+z`; `window_double` the same size; `gutter_section` is 1 m tall
|
|
107
|
+
with its back `-z` and open loops at both ends; `wall_lamp` has its back `-z`;
|
|
108
|
+
`wall_clamp` is small with its back `-z`. Scene `res://facade_test.tscn` with a
|
|
109
|
+
`Facade` Node3D at the origin.
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
summer_instantiate_scene {scenePath:"res://facade_test.tscn", parent:"./Facade",
|
|
113
|
+
scene:"res://kit/wall_double.tscn", name:"G1", position:[0,0,0]}
|
|
114
|
+
summer_instantiate_scene {..., scene:"res://kit/window_double.tscn", name:"G2", position:[2,0,0]}
|
|
115
|
+
summer_place_adjacent {scenePath:"res://facade_test.tscn", subject:"./Facade/G2",
|
|
116
|
+
reference:"./Facade/G1", axis:"x", side:"max", alignOtherAxes:{y:"min", z:"max"}}
|
|
117
|
+
-> verify {gap:0, residuals:{y:0, z:0}}
|
|
118
|
+
summer_instantiate_scene {..., scene:"res://kit/window_double.tscn", name:"U1", position:[0,3,0]}
|
|
119
|
+
summer_place_adjacent {..., subject:"./Facade/U1", reference:"./Facade/G1",
|
|
120
|
+
axis:"y", side:"max", alignOtherAxes:{x:"min", z:"max"}}
|
|
121
|
+
summer_instantiate_scene {..., scene:"res://kit/window_double.tscn", name:"U2", position:[2,3,0]}
|
|
122
|
+
summer_place_adjacent {..., subject:"./Facade/U2", reference:"./Facade/U1",
|
|
123
|
+
axis:"x", side:"max", alignOtherAxes:{y:"min", z:"max"}}
|
|
124
|
+
summer_measure {scenePath:"res://facade_test.tscn", mode:"plane",
|
|
125
|
+
nodes:["./Facade/G1","./Facade/G2","./Facade/U1","./Facade/U2"], face:"+z"}
|
|
126
|
+
-> coplanar:true, spread 0
|
|
127
|
+
|
|
128
|
+
summer_raycast {scenePath:"res://facade_test.tscn", origin:[2.15,0.5,1], direction:[0,0,-1]}
|
|
129
|
+
-> hit ./Facade/G2, normal [0,0,1]: the wall front, by physics
|
|
130
|
+
summer_instantiate_scene {..., scene:"res://kit/gutter_section.tscn", name:"Pipe_1", position:[2.15,0.1,0.5]}
|
|
131
|
+
summer_attach_to_surface {scenePath:"res://facade_test.tscn", subject:"./Facade/Pipe_1",
|
|
132
|
+
ray:{origin:[2.15,0.5,1], direction:[0,0,-1]}, backAxis:"-z", upAxis:"+y", standoff:0.02}
|
|
133
|
+
-> seated_on "Facade/G2", final_gap 0.02, back_face_gap 0.02; the pipe keeps y 0.1
|
|
134
|
+
summer_instantiate_scene {..., scene:"res://kit/gutter_section.tscn", name:"Pipe_2", position:[2.15,1.1,0.1]}
|
|
135
|
+
summer_connect_ports {scenePath:"res://facade_test.tscn", subject:"./Facade/Pipe_2", subjectPort:"-Y",
|
|
136
|
+
target:"./Facade/Pipe_1", targetPort:"+Y"}
|
|
137
|
+
-> tilt_degrees 0, verify {distance:0, angle_degrees:0}, other_ports [{id:"+Y", direction:[0,1,0]}]
|
|
138
|
+
summer_repeat_along {scenePath:"res://facade_test.tscn", template:"res://kit/wall_clamp.tscn",
|
|
139
|
+
parent:"./Facade", start:[2.15,0.3,0.02], end:[2.15,1.9,0.02], spacing:0.45}
|
|
140
|
+
-> count 4, created ["Facade/wall_clamp_1", ...]
|
|
141
|
+
|
|
142
|
+
summer_instantiate_scene {..., scene:"res://kit/wall_lamp.tscn", name:"Lamp", position:[1,2.6,0.5]}
|
|
143
|
+
summer_attach_to_surface {scenePath:"res://facade_test.tscn", subject:"./Facade/Lamp",
|
|
144
|
+
surface:"./Facade/G1", backAxis:"-z", standoff:0}
|
|
145
|
+
summer_starcast {scenePath:"res://facade_test.tscn", path:"./Facade/Lamp", directionSpace:"local"}
|
|
146
|
+
-> contacts ["Facade/G1"], forward (-Z, the lamp's back) blocked at 0, back (+Z) open
|
|
147
|
+
summer_snapshot_diff {from_id:"<id>"} then summer_screenshot
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Loop ids come from the section's `open_loops` in step 1 (its
|
|
151
|
+
`summary.port_like_loops`): `+Y` is the outermost loop facing +Y in the
|
|
152
|
+
piece's own axes (here the top end), `-Y` the bottom; a second loop facing the
|
|
153
|
+
same way is `+Y#2`. The ids do not depend on radius or pose.
|
|
154
|
+
On the target pick the loop whose `direction` points where the run continues;
|
|
155
|
+
on the subject, the one that points back at the target. A join that would tilt
|
|
156
|
+
the piece more than 5 degrees is refused and lists the ports that fit; pass
|
|
157
|
+
`allowTilt: true` only for an intended tilt. With kits that ship Marker3D
|
|
158
|
+
anchors, pass their names instead.
|
|
159
|
+
|
|
49
160
|
## Placement recipes
|
|
50
161
|
|
|
51
162
|
- **Floor/platform:** require downward support, no unintended contacts, and open
|
|
@@ -60,6 +171,17 @@ defined relative to a rotated subject; then use `directionSpace="local"`.
|
|
|
60
171
|
refers to the object's orientation; use world directions for level axes.
|
|
61
172
|
- **Overlap repair:** move along the clearest axis with the shortest correction,
|
|
62
173
|
then rerun. Do not resize the asset unless the user asked for that.
|
|
174
|
+
- **Facade line:** modules edge to edge with `summer_place_adjacent`
|
|
175
|
+
(`alignOtherAxes` `{y: "min", z: "max"}` for a +z front), then
|
|
176
|
+
`summer_measure` plane mode on the fronts. A module reported `proud` or
|
|
177
|
+
`recessed` is moved along the face axis by its `deviation`.
|
|
178
|
+
- **Pipes and gutters:** back on the wall's front plane (`summer_attach_to_surface`
|
|
179
|
+
with the measured back axis), runs joined with `summer_connect_ports`, clamps
|
|
180
|
+
with `summer_repeat_along`. Starcast in local space: the back-axis direction
|
|
181
|
+
(`forward` for a -Z back) blocked at about the standoff.
|
|
182
|
+
- **Wall fixtures (lamps, AC units, signs):** `summer_raycast` to find the
|
|
183
|
+
wall point, `summer_test_placement` if the spot is crowded, then
|
|
184
|
+
`summer_attach_to_surface`.
|
|
63
185
|
|
|
64
186
|
## Guardrails
|
|
65
187
|
|
|
@@ -72,3 +194,12 @@ defined relative to a rotated subject; then use `directionSpace="local"`.
|
|
|
72
194
|
- Cameras, lights, audio, navigation nodes, scripts, and plain Nodes are not
|
|
73
195
|
obstacles unless they own collision or renderable geometry.
|
|
74
196
|
- Prefer two useful summary calls around one correction over repeated full calls.
|
|
197
|
+
- Never infer a piece's facing from its file name or a screenshot alone.
|
|
198
|
+
Measure it (`summer_inspect_asset`), place it, then confirm with Starcast
|
|
199
|
+
(local) and a screenshot.
|
|
200
|
+
- Batch receipts over a few ops: always `receipt: "summary"`.
|
|
201
|
+
- `visual_aabb` measurements (measure, place_adjacent) are box bounds: an
|
|
202
|
+
overhang or a lip sets the face. Say so when it matters.
|
|
203
|
+
- A piece seated flush against a single-sided wall can read `open` in the
|
|
204
|
+
wall's direction while `contacts` lists the wall: Starcast's one ray per
|
|
205
|
+
direction starts at the touching face. Read `contacts` too.
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# Kit placement tools
|
|
2
|
+
|
|
3
|
+
Reference for the tools that place modular kit pieces from measured geometry.
|
|
4
|
+
Read it before the first call in a task. The workflow that uses them is in
|
|
5
|
+
[`SKILL.md`](../SKILL.md).
|
|
6
|
+
|
|
7
|
+
## Shared rules
|
|
8
|
+
|
|
9
|
+
- **Exact paths.** `scenePath` is an exact `res://...tscn`; node paths are
|
|
10
|
+
relative to the scene root (`./Facade/Wall_01` or `Facade/Wall_01`). Editor
|
|
11
|
+
selection is never used.
|
|
12
|
+
- **The scene must be open** in the editor (any tab). A scene mutation with
|
|
13
|
+
`scenePath` opens it; `summer_open_scene` does too. A closed scene answers
|
|
14
|
+
`scene_not_open`.
|
|
15
|
+
- **Physics needs the active tab.** Only the active scene's bodies are in the
|
|
16
|
+
editor's physics space. Ray queries on another tab fall back to visual AABBs
|
|
17
|
+
and say so.
|
|
18
|
+
- **Scene space.** Points, normals and bounds in results are in the scene
|
|
19
|
+
root's frame (world space in the editor). `position` / `start` / `end` that
|
|
20
|
+
you pass for new instances are parent-local, like `summer_set_prop`.
|
|
21
|
+
- **Evidence** is named in every result:
|
|
22
|
+
- `visual_aabb`: bounds of visible `GeometryInstance3D` nodes (the definition
|
|
23
|
+
`summer_align_distribute_3d` uses). In `space: "local"` the mesh boxes are
|
|
24
|
+
projected onto the node's own axes, so a rotated facade measures tightly.
|
|
25
|
+
Never triangle contact.
|
|
26
|
+
- `physics`: a collider query (exact shapes, needs the active tab).
|
|
27
|
+
- `mesh_triangles`: computed from the mesh triangles themselves.
|
|
28
|
+
- `markers`: Marker3D anchors shipped with the kit.
|
|
29
|
+
- **Compact results.** Every result is under 5 KB. A list cut to fit is
|
|
30
|
+
declared in `truncated: {list: {shown, total}}`.
|
|
31
|
+
- **No silent fallback.** A missing op answers `engine_lacks_op`; a measurement
|
|
32
|
+
that cannot be made answers a named `failure_reason`.
|
|
33
|
+
- **Engine ops.** No new engine op. Reads run one read-only GDScript probe
|
|
34
|
+
through `RunSceneScript` (the op behind `summer_run_script`: in-process, no
|
|
35
|
+
child editor, `undo: "none"`, no checkpoint). Mutations are ordinary
|
|
36
|
+
`SetProp`, `SnapToSurface` and `InstantiateScene` ops: one undo step per
|
|
37
|
+
request and one final `SaveScene`.
|
|
38
|
+
- **Side effects of the probe.** It blocks the editor for the few milliseconds
|
|
39
|
+
it runs, and the engine marks the *active* tab as unsaved after any
|
|
40
|
+
`RunSceneScript`, even a read-only one. Nothing in the scene changes.
|
|
41
|
+
|
|
42
|
+
## Which tool answers which question
|
|
43
|
+
|
|
44
|
+
| Question | Tool |
|
|
45
|
+
|---|---|
|
|
46
|
+
| How big is this piece, where is its origin, which face is its back, where are its pipe ends? | `summer_inspect_asset` |
|
|
47
|
+
| Place a piece at an exact pose in one call | `summer_instantiate_scene` with `position` / `rotation_degrees` / `scale` / `transform` |
|
|
48
|
+
| Place many pieces in one call and read the receipt | `summer_batch` with placed `InstantiateScene` ops and `receipt: "summary"` |
|
|
49
|
+
| Next facade module edge to edge, next storey on top | `summer_place_adjacent` |
|
|
50
|
+
| Downpipe, lamp, AC unit or sign on the wall | `summer_attach_to_surface` |
|
|
51
|
+
| Clamps every 0.45 m, a row of posts or windows | `summer_repeat_along` |
|
|
52
|
+
| Pipe or duct end to end | `summer_connect_ports` |
|
|
53
|
+
| What is in front of this point, and its normal? | `summer_raycast` |
|
|
54
|
+
| Gap or overlap between two pieces; is the facade front flat? | `summer_measure` |
|
|
55
|
+
| What surrounds a placed piece, which side is blocked? | `summer_starcast` (existing) |
|
|
56
|
+
| Will a pose fit before I commit it in a tight spot? | `summer_test_placement` (existing) |
|
|
57
|
+
| Seat a prop on a floor, table or ledge | `summer_snap_to_surface` (existing) |
|
|
58
|
+
| Line up or equally space 2-16 placed pieces on one axis | `summer_align_distribute_3d` (existing) |
|
|
59
|
+
| Did exactly that change, and does it look right? | `summer_world_snapshot` + `summer_snapshot_diff`, then `summer_screenshot` (existing) |
|
|
60
|
+
|
|
61
|
+
## `summer_inspect_asset`
|
|
62
|
+
|
|
63
|
+
Measure an asset file without adding it to a scene. The probe loads the file,
|
|
64
|
+
instances it off the scene tree, measures, and frees it.
|
|
65
|
+
|
|
66
|
+
- **Use when:** before placing any kit piece you have not measured.
|
|
67
|
+
- **Arguments:** `path` (`res://` `.tscn` `.scn` `.glb` `.gltf` `.res`
|
|
68
|
+
`.tres` `.mesh` `.obj`), `maxTriangles` (100-300000, default 60000) for the
|
|
69
|
+
face and loop analysis, `detail` (`summary`, the default, or `full`).
|
|
70
|
+
- **Result:** `{ok, tool, detail, summary {aabb, origin, plane_pairs,
|
|
71
|
+
port_like_loops, triangles, mesh_count, anchor_count, collision_count,
|
|
72
|
+
warnings?}, frame: "asset_root", root_class, root_transform_identity,
|
|
73
|
+
aabb {min, max, size}, origin {fraction [x,y,z], label}, mesh_count,
|
|
74
|
+
meshes [{path, tris, min, max, hidden?}], triangles,
|
|
75
|
+
planes [{normal, offset, area, tris, cull_back, one_sided}] (top 6 by area),
|
|
76
|
+
open_loop_count, open_loops [{id, index, mesh, center, direction, radius,
|
|
77
|
+
vertices, max_dev, direction_ambiguous?}], open_loops_listed?,
|
|
78
|
+
open_loops_omitted?, open_chains, anchor_count, anchors [{name, path,
|
|
79
|
+
position, forward, up}], collision_count, collision [{path, shape,
|
|
80
|
+
size|radius|height|faces|points, center, min, max, disabled?}], analysis
|
|
81
|
+
{triangles_analyzed, triangle_budget, truncated, weld_m, plane_bin},
|
|
82
|
+
evidence: "mesh_triangles"}`.
|
|
83
|
+
- **The summary block** comes first and holds the facing evidence:
|
|
84
|
+
- `plane_pairs`: the two largest pairs of opposite planes (a pair under 1% of
|
|
85
|
+
the largest one's area is left out), each `{larger, opposite, separation}`.
|
|
86
|
+
`opposite` is `null` for a single sheet. Every plane is `{axis?, normal,
|
|
87
|
+
offset, area, one_sided}`; `axis` (such as `+z`) is given only when the
|
|
88
|
+
normal is within about 1 degree of it, so a baked yaw or a 45-degree corner
|
|
89
|
+
face shows its exact normal with no label. `separation` is the distance
|
|
90
|
+
between the two planes (the thickness; 0 for a sheet modelled with both
|
|
91
|
+
faces).
|
|
92
|
+
- `one_sided: true` means the plane's material culls back faces: it is
|
|
93
|
+
invisible from behind its normal. A one-sided sheet with no opposite plane
|
|
94
|
+
faces along its normal, and its back is the opposite axis.
|
|
95
|
+
- `port_like_loops`: ids of the open loops that look like pipe or duct
|
|
96
|
+
ends: radius over 2 cm, a decided direction, and either a partner loop of
|
|
97
|
+
similar radius facing more than 60 degrees away (the other end of a
|
|
98
|
+
straight run or a bend) or, for an end piece with one opening (an outlet's
|
|
99
|
+
socket, a funnel's mouth), the only loop opening on the bounding-box face
|
|
100
|
+
it points through, with the piece reaching at least two radii behind it.
|
|
101
|
+
- `warnings`: says when the triangle budget cut the analysis and which
|
|
102
|
+
`maxTriangles` covers the whole mesh.
|
|
103
|
+
- **`detail`:** `summary` lists in `open_loops` only the port-like loops (with
|
|
104
|
+
their ids and indices, which `summer_connect_ports` accepts) and says how
|
|
105
|
+
many it omitted. `full` lists every loop, including the outline and holes of
|
|
106
|
+
flat sheets.
|
|
107
|
+
- **Loop ids and order:** loops are grouped by the piece axis their outward
|
|
108
|
+
direction is nearest (`+X`, `-X`, `+Y`, `-Y`, `+Z`, `-Z`, then `~X`, `~Y`,
|
|
109
|
+
`~Z` for loops whose direction is undecided), the outermost along that axis
|
|
110
|
+
first, then by centre x, y, z (in millimetres); the radius only breaks exact
|
|
111
|
+
ties. The `id` follows that order: `+Y` is the outermost loop facing +Y,
|
|
112
|
+
`+Y#2` the next one. `index` is the position in the same order. Both are
|
|
113
|
+
computed in the piece's own frame, so they name the same loop on the placed
|
|
114
|
+
node in `summer_connect_ports`, whatever its pose. A loop 30 degrees off +Y
|
|
115
|
+
still groups under `+Y`: read its `direction`.
|
|
116
|
+
- **Reading it:** the asset frame is the root's own frame (its own transform
|
|
117
|
+
excluded), the frame `position` and `rotation_degrees` apply in. `origin.label`
|
|
118
|
+
such as `x:center y:min z:center` means bottom centre. Plane normals follow
|
|
119
|
+
triangle winding, so they point out of the visible side. The largest planes
|
|
120
|
+
with normals along one axis are usually the front and back: a wall with a
|
|
121
|
+
large `+z` plane at the max z offset faces +z and its back is `-z`. The tool
|
|
122
|
+
reports planes; you decide which is the front. Open loops are holes in the
|
|
123
|
+
mesh: pipe and duct ends (`direction` points out of the piece), and also the
|
|
124
|
+
open edge of single-sided geometry. `max_dev` is how far the loop is from
|
|
125
|
+
flat.
|
|
126
|
+
- **Limits:** planes are binned at about 1.4 degrees and 1 cm. Vertices are
|
|
127
|
+
welded at 0.1 mm, so UV seams do not count as holes; double-sided or capped
|
|
128
|
+
ends have no loop. Hidden meshes are listed but not analysed. `one_sided`
|
|
129
|
+
reads `cull_mode` of a `BaseMaterial3D`, or `cull_disabled` / `cull_front`
|
|
130
|
+
in a shader's code; a mesh with no material counts as one-sided (the default
|
|
131
|
+
material culls back faces).
|
|
132
|
+
- **Ops:** `RunSceneScript` (read-only probe).
|
|
133
|
+
|
|
134
|
+
## `summer_instantiate_scene` (placed)
|
|
135
|
+
|
|
136
|
+
- **Arguments added:** `position`, `rotation_degrees`, `scale` (`[x, y, z]`,
|
|
137
|
+
parent-local) or `transform` (`"Transform3D(xx, xy, xz, yx, yy, yz, zx, zy,
|
|
138
|
+
zz, ox, oy, oz)"`). Not `transform` with the others; not `scale` or
|
|
139
|
+
`transform` with `target_size`.
|
|
140
|
+
- **Behaviour:** `InstantiateScene` (its own request, as the engine requires),
|
|
141
|
+
then one `SetProp` request on the node path the receipt reports (a name
|
|
142
|
+
collision rename is followed), then `SaveScene`. Without the new fields it is
|
|
143
|
+
unchanged.
|
|
144
|
+
- **Result:** the merged receipt (`results` holds every op; the per-request
|
|
145
|
+
`receipts` copies are kept only when something failed) plus
|
|
146
|
+
`placement {nodePath, applied, fields, space: "parent_local"}`.
|
|
147
|
+
- **Ops:** `InstantiateScene`, `SetProp`, `SaveScene`.
|
|
148
|
+
|
|
149
|
+
## `summer_batch` additions
|
|
150
|
+
|
|
151
|
+
- `InstantiateScene` ops may carry the same placement fields (arrays or
|
|
152
|
+
`"Vector3(...)"` strings). Each piece is one op; its `SetProp`s are sent right
|
|
153
|
+
after it is created. Other ops are forwarded verbatim.
|
|
154
|
+
- `receipt: "summary"` returns `{ok, receipt, ops, requests, applied, failed,
|
|
155
|
+
not_sent, saved, error?, failures [{index, op, step?, failure_reason?,
|
|
156
|
+
error}], created_total, created [paths], renamed [{index, requested,
|
|
157
|
+
actual}]}`. `index` is the position in your `ops` list. Use it for every batch
|
|
158
|
+
over a few ops: a full receipt for about 30 or more ops overflows the tool
|
|
159
|
+
output limit.
|
|
160
|
+
- **Cost:** the engine runs each `InstantiateScene` as its own request. The
|
|
161
|
+
transforms of a run of `InstantiateScene` ops are held back and sent
|
|
162
|
+
together (up to 200 `SetProp`s per request) just before the next op that is
|
|
163
|
+
not an `InstantiateScene`, riding along with it when it can. A batch of N
|
|
164
|
+
placed pieces is therefore about N + 2 requests and N + 2 undo steps (it was
|
|
165
|
+
2N + 1). Every later op in the list (a `SetProp`, `SnapToSurface`, a query,
|
|
166
|
+
the save) runs after the transforms land. If an `InstantiateScene` fails,
|
|
167
|
+
the pieces created before it still get their transforms; nothing is saved.
|
|
168
|
+
|
|
169
|
+
## `summer_place_adjacent`
|
|
170
|
+
|
|
171
|
+
- **Use when:** facade modules edge to edge, a storey on the storey below, a
|
|
172
|
+
cornice on a wall, a pier beside a bay.
|
|
173
|
+
- **Arguments:** `subject` (moves), `reference` (stays), `axis` (`x|y|z`),
|
|
174
|
+
`side` (`max`: subject on the reference's +axis side; `min`: the -axis side),
|
|
175
|
+
`gap` (default 0; negative overlaps), `alignOtherAxes` (`min|center|max|none`
|
|
176
|
+
for both other axes, or per axis `{y: "min", z: "max"}`), `space`
|
|
177
|
+
(`world`, or `local` for the reference's own axes).
|
|
178
|
+
- **Result:** `{subject, reference, evidence: "visual_aabb", space, moved,
|
|
179
|
+
moved_by [world], position [parent-local], saved, reference_excludes_subject?,
|
|
180
|
+
verify {gap, residuals}}`. `verify` is a fresh read after the move.
|
|
181
|
+
- **Limits:** bounds are visible-mesh AABBs; a piece with an overhang (a
|
|
182
|
+
cornice lip) meets at its outermost point. If the subject is inside the
|
|
183
|
+
reference, its geometry is left out of the reference's bounds. A reference
|
|
184
|
+
inside the subject is refused.
|
|
185
|
+
- **Ops:** `RunSceneScript` (read, verify), `SetProp` (position),
|
|
186
|
+
`SaveScene`.
|
|
187
|
+
|
|
188
|
+
## `summer_attach_to_surface`
|
|
189
|
+
|
|
190
|
+
- **Use when:** mounting downpipes, gutters, lamps, AC units, signs, fire
|
|
191
|
+
escapes on a wall (or anything on a ceiling or floor) with the right side
|
|
192
|
+
against it.
|
|
193
|
+
- **Arguments:** `subject`; `surface` (node: the ray runs from the subject's
|
|
194
|
+
origin to the nearest point of the node's bounds) and/or `ray {origin,
|
|
195
|
+
direction}` (with both, hits on other nodes are skipped); `backAxis` (the
|
|
196
|
+
subject's local axis that faces into the surface, default `-z`); `upAxis`
|
|
197
|
+
(default `+y`); `worldUp` (default `[0,1,0]`); `standoff` (default 0);
|
|
198
|
+
`placeAt` (`current`, the default, or `hit`); `maxMove` (default 2);
|
|
199
|
+
`maxDistance` (ray length, default 20); `collisionMask`.
|
|
200
|
+
- **Place the piece near its mount first** (`summer_instantiate_scene` with
|
|
201
|
+
`position`): this tool turns it and pushes it onto the surface.
|
|
202
|
+
- **Behaviour:** the probe reads the piece's visible bounds along its own axes
|
|
203
|
+
and casts the ray (physics first, visual AABB fallback declared). The piece is
|
|
204
|
+
turned so `backAxis` points along -normal and `upAxis` follows `worldUp`
|
|
205
|
+
projected onto the surface (on a floor or ceiling, where that is undefined,
|
|
206
|
+
the current up is kept and a warning says so). The planned seat puts its
|
|
207
|
+
**back face** (the extreme of its visible bounds along `backAxis`, not its
|
|
208
|
+
origin) at `standoff` in front of the plane through the hit point:
|
|
209
|
+
- `placeAt: "current"`: the piece keeps its height and its place along the
|
|
210
|
+
surface and moves only along the surface normal.
|
|
211
|
+
- `placeAt: "hit"`: it also slides so the centre of its back face lands on
|
|
212
|
+
the hit point (its height then follows the ray).
|
|
213
|
+
One `SetProp` turns it and puts its back face 5 cm in front of the planned
|
|
214
|
+
seat; `SnapToSurface` sweeps it along -normal (at most `standoff` + 0.3) and
|
|
215
|
+
seats it at `standoff` by its own evidence.
|
|
216
|
+
- **Checked before saving:**
|
|
217
|
+
- a planned move longer than `maxMove` is refused before anything changes
|
|
218
|
+
(`move_exceeds_max_move`, `mutationApplied: false`), and so is, with
|
|
219
|
+
`placeAt: "current"`, a ray hit farther than `maxMove` along the surface
|
|
220
|
+
from the piece's back face (`hit_far_from_piece`: aim the ray at the piece,
|
|
221
|
+
or pass `placeAt: "hit"` to move it there);
|
|
222
|
+
- with `surface`, the seat must be on that node or inside it; with a ray
|
|
223
|
+
only, a seat on another node is accepted only when it lies on the hit plane
|
|
224
|
+
(a coplanar neighbour module, warned `seated_on_coplanar_<path>`). Anything
|
|
225
|
+
else is refused as `seated_on_other_node`;
|
|
226
|
+
- a failed seat (`overlap_recovery_exceeded`, `gap_exceeds_hit_travel`,
|
|
227
|
+
`surface_not_found`, `subject_not_ready`) is reported with `blockers
|
|
228
|
+
{evidence, overlapping, overlaps, first_contact {path, distance}}`, read
|
|
229
|
+
where the seat started, and a `next_step`.
|
|
230
|
+
|
|
231
|
+
A refusal or failure puts the piece back exactly where it started
|
|
232
|
+
(`restored: true`), saves nothing and answers `ok: false` with `seated_on`,
|
|
233
|
+
`intended_surface`, `in_front_of_plan` (how far in front of the planned seat
|
|
234
|
+
it stopped) and `next_step`.
|
|
235
|
+
- **Result:** `{subject, placed_at, seated_on, final_gap (the collider gap
|
|
236
|
+
from SnapToSurface), back_face_gap (visible back face to the hit plane),
|
|
237
|
+
moved_by, surface_hit {evidence, path, point, normal, distance}, orientation
|
|
238
|
+
{backAxis, upAxis, world_back, world_up}, back_face_offset (origin to back
|
|
239
|
+
face along backAxis), seat {ok, evidence, supportPath, finalGap,
|
|
240
|
+
gapErrorBound, initiallyOverlapping, backoffDistance, hitTravel, origin,
|
|
241
|
+
warnings}, standoff, saved, warnings}`.
|
|
242
|
+
- **Warnings worth acting on:** `visible_back_X_into_surface` (the collider
|
|
243
|
+
sits X behind the visible back face, so the mesh pokes into the wall: add X
|
|
244
|
+
to `standoff`); `surface_not_flat_under_piece` (it seated on the surface but
|
|
245
|
+
in front of the hit plane); `hit_normal_pointed_away_from_the_ray_flipped`
|
|
246
|
+
(the ray hit a back face; the piece still mounts on the ray's side).
|
|
247
|
+
- **Check after:** `summer_starcast` with `directionSpace: "local"`. Its local
|
|
248
|
+
names follow Godot (`forward` = -Z, `back` = +Z), so a -Z back reads
|
|
249
|
+
`forward` blocked (or the surface in `contacts` when seated flush) and `back`
|
|
250
|
+
open.
|
|
251
|
+
- **Limits:** the back face is the visible-mesh AABB in the piece's own axes;
|
|
252
|
+
the seat itself is collider-exact when the piece has colliders. A mesh-only
|
|
253
|
+
wall gives an AABB face normal (axis-aligned), and SnapToSurface's own
|
|
254
|
+
evidence is then `visual_aabb`. A mirrored (negative-scale) piece is refused.
|
|
255
|
+
Pass `backAxis` from `summer_inspect_asset`, never a guess.
|
|
256
|
+
- **Ops:** `RunSceneScript` (bounds and ray; the blockers read after a failed
|
|
257
|
+
seat), `SetProp` (transform; the restore), `SnapToSurface`, `SaveScene`.
|
|
258
|
+
|
|
259
|
+
## `summer_repeat_along`
|
|
260
|
+
|
|
261
|
+
- **Use when:** clamps every 0.45 m up a pipe, braces every 0.8 m along a duct,
|
|
262
|
+
fence posts, bollards, a row of window modules.
|
|
263
|
+
- **Arguments:** `template` (scene), `parent`, `start`; then `end` with
|
|
264
|
+
`spacing` (as many as fit) or `count` (spread start to end), or `direction`
|
|
265
|
+
with `count` and `spacing`. `align` (`start|center|end`) places the leftover
|
|
266
|
+
length with `end` + `spacing`. `rotationDegrees`, `scale`, `namePrefix`
|
|
267
|
+
(copies are `<prefix>_<n>`, default the template file name). Coordinates are
|
|
268
|
+
parent-local. At most 64 copies per call.
|
|
269
|
+
- **Result:** the batch summary plus `{template, parent, count, spacing,
|
|
270
|
+
direction, first, last}`.
|
|
271
|
+
- **Ops:** `InstantiateScene` (one request per copy), `SetProp` (every copy's
|
|
272
|
+
transform in one request), `SaveScene`: N copies cost N + 2 requests.
|
|
273
|
+
|
|
274
|
+
## `summer_connect_ports`
|
|
275
|
+
|
|
276
|
+
- **Use when:** pipe to pipe, duct to duct, gutter section to funnel or outlet,
|
|
277
|
+
any two pieces with named anchors.
|
|
278
|
+
- **Arguments:** `subject` (moves), `subjectPort`, `target` (stays),
|
|
279
|
+
`targetPort`, `gap` (default 0), `rollDegrees` (default 0),
|
|
280
|
+
`maxTiltDegrees` (0-180, default 5), `allowTilt` (default false),
|
|
281
|
+
`maxTriangles`. A port is an open-loop id from `summer_inspect_asset` on
|
|
282
|
+
that node's scene (`+Y`, `-Z#2`; case does not matter, `+Y#1` is `+Y`), a
|
|
283
|
+
Marker3D (or any Node3D) name under the node whose -Z axis points out of the
|
|
284
|
+
port, or an open-loop index in the same stable order. A string shaped like
|
|
285
|
+
an id is always read as an id.
|
|
286
|
+
- **Behaviour:** the subject turns by the shortest rotation that makes its port
|
|
287
|
+
direction the opposite of the target's, then by `rollDegrees` about the
|
|
288
|
+
joined axis, then moves so the ports meet, `gap` apart along the target port
|
|
289
|
+
direction.
|
|
290
|
+
- **`rollDegrees` exactly:**
|
|
291
|
+
- axis: the target port's direction reversed, pointing from the joint into
|
|
292
|
+
the target (`roll_axis` in the receipt);
|
|
293
|
+
- sign: right-hand rule about that axis; positive turns counter-clockwise
|
|
294
|
+
when you look back along the axis from inside the target toward the
|
|
295
|
+
subject;
|
|
296
|
+
- zero: the shortest turn from the subject's current orientation, so the same
|
|
297
|
+
value gives different results from different start poses. Once the ports
|
|
298
|
+
are joined, a second call turns by exactly `rollDegrees` about the joint:
|
|
299
|
+
180 flips a bend's free end to the other side.
|
|
300
|
+
- **Tilt guard:** the tilt is how far the join turns the subject's up axis
|
|
301
|
+
(its local +Y); a turn about the up axis is no tilt. Over `maxTiltDegrees`
|
|
302
|
+
the join is refused before anything changes: `failure_reason:
|
|
303
|
+
"tilt_exceeds_limit"`, `tilt_degrees` (predicted), `max_tilt_degrees`,
|
|
304
|
+
`subject_port`, `target_port`, `ports_within_limit [{id|name, index,
|
|
305
|
+
tilt_degrees, direction}]` (the subject's ports that would join within the
|
|
306
|
+
limit, least tilt first) and `saved: false`. Pass `allowTilt: true` when the
|
|
307
|
+
tilt is intended (a bend laid on its side, a sloped run); the receipt then
|
|
308
|
+
warns `tilt_allowed`.
|
|
309
|
+
- **Result:** `{evidence (markers|mesh_triangles), subject_port, target_port,
|
|
310
|
+
roll_axis, roll_degrees, rotated_degrees, tilt_degrees, max_tilt_degrees,
|
|
311
|
+
moved_by, other_ports [{kind, id|name, index?, position, direction,
|
|
312
|
+
radius?, direction_ambiguous?}], other_ports_total?, other_ports_predicted?,
|
|
313
|
+
saved, verify {distance, angle_degrees, tilt_degrees}, warnings}`. A port
|
|
314
|
+
that is not found answers `port_not_found` with the node's loops by id
|
|
315
|
+
(`subject_ports` or `target_ports`).
|
|
316
|
+
- **`other_ports`:** every other port of the subject (its other Marker3D
|
|
317
|
+
anchors for a marker port, its other open loops for an open-loop port, up to
|
|
318
|
+
8) with world position and outward direction after the move, measured by the
|
|
319
|
+
verify read (`other_ports_predicted: true` when that read failed and they
|
|
320
|
+
were computed from the move). Read where a bend's free end now points
|
|
321
|
+
instead of measuring it; if it points the wrong way, call again with the
|
|
322
|
+
`rollDegrees` that turns it about `roll_axis`.
|
|
323
|
+
- **Limits:** open-loop ports are only as exact as the mesh; an end whose
|
|
324
|
+
direction cannot be decided is flagged `direction_ambiguous`.
|
|
325
|
+
- **Ops:** `RunSceneScript` (read, verify), `SetProp` (transform),
|
|
326
|
+
`SaveScene`.
|
|
327
|
+
|
|
328
|
+
## `summer_raycast`
|
|
329
|
+
|
|
330
|
+
- **Use when:** you need a surface and its normal at an arbitrary point before
|
|
331
|
+
anything is placed. (`summer_starcast` casts from an existing node.)
|
|
332
|
+
- **Arguments:** `origin`, `direction`, `maxDistance` (default 100),
|
|
333
|
+
`collisionMask`, `collideWithAreas`, `evidence` (`auto|physics|visual_aabb`),
|
|
334
|
+
`exclude` (up to 16 nodes).
|
|
335
|
+
- **Result:** `{hit, evidence, path, point, normal, distance, fallback?,
|
|
336
|
+
fallback_reason?, nearer_visual_only?, origin, direction, physics_available,
|
|
337
|
+
physics_unavailable_reason?, warnings}`.
|
|
338
|
+
- **Limits:** visual AABB hits ignore boxes that contain the origin (counted in
|
|
339
|
+
`warnings`); their normal is a box face normal.
|
|
340
|
+
- **Ops:** `RunSceneScript` (read-only).
|
|
341
|
+
|
|
342
|
+
## `summer_measure`
|
|
343
|
+
|
|
344
|
+
- **Use when:** checking a placement numerically: facade gaps, overlaps,
|
|
345
|
+
modules standing proud. (`summer_starcast` reports clearance around one node
|
|
346
|
+
in 26 directions; this compares named nodes.)
|
|
347
|
+
- **Arguments:** `mode` (`pair` with `a`, `b`, optional `axis`; `plane` with
|
|
348
|
+
`nodes` (2-32) and `face` such as `+z`), `space` (`world`, or `local` for the
|
|
349
|
+
axes of `a` / `nodes[0]`), `tolerance` (default 0.005).
|
|
350
|
+
- **Result, pair:** `{axes {x|y|z: {gap, relation: gap|touching|overlap, a,
|
|
351
|
+
b, delta_min, delta_max, delta_center}}, boxes_overlap}`; `gap < 0` is the
|
|
352
|
+
overlap depth, `delta_*` is b minus a.
|
|
353
|
+
- **Result, plane:** `{coplanar, plane, spread, off_plane_count, nodes [{path,
|
|
354
|
+
face, deviation, off_plane: proud|recessed}], no_geometry?}`.
|
|
355
|
+
- **Ops:** `RunSceneScript` (read-only).
|
|
356
|
+
|
|
357
|
+
## What belongs in the engine later
|
|
358
|
+
|
|
359
|
+
These tools compose existing ops. Natively they would be faster and exact:
|
|
360
|
+
an `InstantiateScene` that takes a transform (one request, one undo step per
|
|
361
|
+
piece), a compact `summer_batch` receipt mode in the ops executor, a raycast and
|
|
362
|
+
a measure op that need no script and do not mark the active tab unsaved, an
|
|
363
|
+
asset-geometry op that reads the import cache without instancing, and an
|
|
364
|
+
oriented-bounds (OBB) query so rotated pieces stop needing `space: "local"`.
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
id: skill/spatial-placement
|
|
2
2
|
kind: skill
|
|
3
|
-
version: 1.0
|
|
4
|
-
summary: Place and
|
|
3
|
+
version: 1.1.0
|
|
4
|
+
summary: Place 3D objects and modular kit pieces from measured geometry — inspect, place, starcast, measure, correct; floor, wall, facade, pipe and alcove recipes.
|
|
5
5
|
use_when:
|
|
6
6
|
- positioning a prop, character, collider, or platform so it sits flush, avoids overlap, or keeps clearance
|
|
7
7
|
- placing something against a wall, inside an alcove, or on a shelf and needing to know which side is blocked and by how much
|
|
8
8
|
- repairing an overlap or a floating object after a placement
|
|
9
9
|
- post-placement checks on a rotated prop using its own local axes
|
|
10
|
+
- placing modular kit pieces — facade or wall modules edge to edge, storeys stacked, pipes, gutters and lamps on a wall, clamps along a pipe
|
|
11
|
+
- measuring a kit piece's size, origin and which way it faces before placing it
|
|
12
|
+
- checking that a facade line is flush, with no gaps and no module standing proud
|
|
10
13
|
do_not_use_when:
|
|
11
14
|
- the scene is 2D — Starcast reads Node3D bounds, 3D physics, and visual AABBs
|
|
12
15
|
- you want the engine to seat or align for you — skill/world-building-3d (summer_snap_to_surface, summer_align_distribute_3d)
|
|
@@ -27,6 +30,17 @@ compatibility:
|
|
|
27
30
|
related:
|
|
28
31
|
tools:
|
|
29
32
|
- tool/starcast
|
|
33
|
+
- tool/inspect-asset
|
|
34
|
+
- tool/place-adjacent
|
|
35
|
+
- tool/attach-to-surface
|
|
36
|
+
- tool/repeat-along
|
|
37
|
+
- tool/connect-ports
|
|
38
|
+
- tool/raycast
|
|
39
|
+
- tool/measure
|
|
40
|
+
- tool/instantiate-scene
|
|
41
|
+
- tool/test-placement
|
|
42
|
+
- tool/snap-to-surface
|
|
43
|
+
- tool/align-distribute-3d
|
|
30
44
|
- tool/get-scene-tree
|
|
31
45
|
- tool/inspect-node
|
|
32
46
|
- tool/set-prop
|