@funpixel/tools 0.0.0-stage → 0.1.1
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 +115 -0
- package/NOTICE +28 -0
- package/README.md +110 -2
- package/bench/LICENSE +674 -0
- package/bench/README.md +10 -0
- package/bench/entrypoint.py +94 -0
- package/bench/handlers/__init__.py +53 -0
- package/bench/handlers/apply_skin.py +192 -0
- package/bench/handlers/apply_texture.py +195 -0
- package/bench/handlers/audit_clips.py +351 -0
- package/bench/handlers/author_clips.py +297 -0
- package/bench/handlers/author_motion.py +298 -0
- package/bench/handlers/bake_emissive.py +136 -0
- package/bench/handlers/build_level.py +395 -0
- package/bench/handlers/decimate.py +220 -0
- package/bench/handlers/fit_rig.py +273 -0
- package/bench/handlers/fracture.py +233 -0
- package/bench/handlers/humanoid.py +119 -0
- package/bench/handlers/inspect.py +212 -0
- package/bench/handlers/level_check.py +68 -0
- package/bench/handlers/level_geo.py +150 -0
- package/bench/handlers/level_proof.py +117 -0
- package/bench/handlers/level_props.py +135 -0
- package/bench/handlers/lod.py +83 -0
- package/bench/handlers/merge_clips.py +122 -0
- package/bench/handlers/mirror_limb.py +336 -0
- package/bench/handlers/motion_specs.json +11 -0
- package/bench/handlers/normalize_materials.py +182 -0
- package/bench/handlers/normalize_transform.py +174 -0
- package/bench/handlers/prune_clips.py +141 -0
- package/bench/handlers/raster.py +98 -0
- package/bench/handlers/render.py +239 -0
- package/bench/handlers/render_views.py +101 -0
- package/bench/handlers/retarget_clips.py +185 -0
- package/bench/handlers/scene.py +311 -0
- package/bench/handlers/sheet.py +118 -0
- package/bench/handlers/texels.py +176 -0
- package/bench/handlers/views.py +232 -0
- package/dist/api/generated/openapi.js +1 -0
- package/dist/api/http.js +71 -0
- package/dist/api/jobs.js +94 -0
- package/dist/assets/bakeoff.js +61 -0
- package/dist/assets/counts.js +60 -0
- package/dist/assets/gen.js +230 -0
- package/dist/assets/lock.js +77 -0
- package/dist/assets/manifest.js +236 -0
- package/dist/assets/palette-fit.js +99 -0
- package/dist/assets/pixelart.js +192 -0
- package/dist/assets/pixels.js +131 -0
- package/dist/assets/plan.js +169 -0
- package/dist/assets/process.js +209 -0
- package/dist/assets/script.js +194 -0
- package/dist/assets/steps.js +294 -0
- package/dist/bin.js +8 -0
- package/dist/board/board.js +99 -0
- package/dist/cast/library.js +102 -0
- package/dist/cast/measure.js +222 -0
- package/dist/cli.js +2917 -0
- package/dist/clip/clip.js +83 -0
- package/dist/commands/account.js +158 -0
- package/dist/commands/assets-pixels.js +106 -0
- package/dist/commands/assets.js +473 -0
- package/dist/commands/beats.js +77 -0
- package/dist/commands/board.js +162 -0
- package/dist/commands/boxes.js +89 -0
- package/dist/commands/capture-all.js +92 -0
- package/dist/commands/cast.js +84 -0
- package/dist/commands/character.js +58 -0
- package/dist/commands/check.js +404 -0
- package/dist/commands/clip.js +112 -0
- package/dist/commands/compare-takes.js +204 -0
- package/dist/commands/compare-target.js +149 -0
- package/dist/commands/compare.js +117 -0
- package/dist/commands/compose-variations.js +202 -0
- package/dist/commands/compose.js +163 -0
- package/dist/commands/cut.js +13 -0
- package/dist/commands/decide.js +90 -0
- package/dist/commands/depth.js +171 -0
- package/dist/commands/dev.js +138 -0
- package/dist/commands/directions.js +106 -0
- package/dist/commands/doctor.js +281 -0
- package/dist/commands/export.js +88 -0
- package/dist/commands/feedback.js +496 -0
- package/dist/commands/feel.js +144 -0
- package/dist/commands/fidelity.js +95 -0
- package/dist/commands/find.js +116 -0
- package/dist/commands/firstlook.js +138 -0
- package/dist/commands/flow.js +600 -0
- package/dist/commands/framing.js +53 -0
- package/dist/commands/gdd.js +227 -0
- package/dist/commands/gen.js +512 -0
- package/dist/commands/greenlight.js +148 -0
- package/dist/commands/hook.js +171 -0
- package/dist/commands/init.js +234 -0
- package/dist/commands/inspect.js +161 -0
- package/dist/commands/job.js +41 -0
- package/dist/commands/jobs.js +87 -0
- package/dist/commands/journal.js +58 -0
- package/dist/commands/journey.js +228 -0
- package/dist/commands/judge.js +191 -0
- package/dist/commands/lanes.js +571 -0
- package/dist/commands/lessons.js +74 -0
- package/dist/commands/life.js +134 -0
- package/dist/commands/login.js +134 -0
- package/dist/commands/look-3d.js +105 -0
- package/dist/commands/look-fit.js +116 -0
- package/dist/commands/look-hud.js +180 -0
- package/dist/commands/look-read.js +162 -0
- package/dist/commands/look-sheet.js +152 -0
- package/dist/commands/look-theme.js +136 -0
- package/dist/commands/look.js +373 -0
- package/dist/commands/loop.js +112 -0
- package/dist/commands/loudness.js +69 -0
- package/dist/commands/mobile-qa.js +119 -0
- package/dist/commands/model.js +256 -0
- package/dist/commands/models.js +93 -0
- package/dist/commands/motion.js +305 -0
- package/dist/commands/next.js +72 -0
- package/dist/commands/note.js +294 -0
- package/dist/commands/optimize.js +212 -0
- package/dist/commands/owner.js +109 -0
- package/dist/commands/pack.js +66 -0
- package/dist/commands/parts.js +635 -0
- package/dist/commands/phone.js +398 -0
- package/dist/commands/pick.js +146 -0
- package/dist/commands/pitch.js +205 -0
- package/dist/commands/places.js +89 -0
- package/dist/commands/play.js +368 -0
- package/dist/commands/playable.js +51 -0
- package/dist/commands/playtest.js +262 -0
- package/dist/commands/profile.js +292 -0
- package/dist/commands/progress.js +537 -0
- package/dist/commands/publish.js +165 -0
- package/dist/commands/reach.js +72 -0
- package/dist/commands/reel.js +177 -0
- package/dist/commands/review.js +112 -0
- package/dist/commands/rooms.js +180 -0
- package/dist/commands/schema.js +29 -0
- package/dist/commands/score.js +326 -0
- package/dist/commands/serve.js +67 -0
- package/dist/commands/setup.js +254 -0
- package/dist/commands/sim.js +179 -0
- package/dist/commands/simulator.js +154 -0
- package/dist/commands/smoke-build.js +305 -0
- package/dist/commands/smoke.js +37 -0
- package/dist/commands/spec.js +114 -0
- package/dist/commands/store.js +154 -0
- package/dist/commands/test.js +104 -0
- package/dist/commands/trailer.js +255 -0
- package/dist/commands/unity-editor.js +322 -0
- package/dist/commands/unity-player.js +672 -0
- package/dist/commands/unity.js +198 -0
- package/dist/commands/upgrade.js +186 -0
- package/dist/commands/variety.js +108 -0
- package/dist/commands/verify.js +293 -0
- package/dist/commands/walk.js +449 -0
- package/dist/commands/widen.js +133 -0
- package/dist/commands/world.js +175 -0
- package/dist/commands/wow.js +143 -0
- package/dist/commands/zero.js +71 -0
- package/dist/compose/adsheet.js +61 -0
- package/dist/compose/contract.js +248 -0
- package/dist/compose/facts.js +81 -0
- package/dist/compose/hyperframes.js +102 -0
- package/dist/compose/page.js +216 -0
- package/dist/compose/probe.js +160 -0
- package/dist/compose/run.js +170 -0
- package/dist/compose/sheet.js +92 -0
- package/dist/compose/starters.js +247 -0
- package/dist/compose/variations.js +203 -0
- package/dist/criteria.js +35 -0
- package/dist/depth/experience.js +61 -0
- package/dist/depth/fill.js +102 -0
- package/dist/depth/inventory.js +161 -0
- package/dist/depth/pacing.js +173 -0
- package/dist/depth/story.js +97 -0
- package/dist/dev/devtools.js +119 -0
- package/dist/dev/hold.js +46 -0
- package/dist/dev/lan.js +15 -0
- package/dist/dev/open.js +30 -0
- package/dist/dev/qr.js +124 -0
- package/dist/devtools/LICENSES/pixi.js.LICENSE +21 -0
- package/dist/devtools/LICENSES/preact.LICENSE +21 -0
- package/dist/devtools/LICENSES/source-map-js.LICENSE +28 -0
- package/dist/devtools/LICENSES/three.LICENSE +21 -0
- package/dist/devtools/inspector/funpixel-inspector.pixi.min.js +1 -0
- package/dist/devtools/inspector/funpixel-inspector.threejs.min.js +1 -0
- package/dist/devtools/inspector/hooked-engines/pixi.min.js +8 -0
- package/dist/devtools/inspector/hooked-engines/preact.min.js +1 -0
- package/dist/devtools/inspector/hooked-engines/threejs.min.js +12 -0
- package/dist/devtools/kapture/funpixel-kapture.min.js +1 -0
- package/dist/devtools/profiler/funpixel-profiler.pixi.min.js +1 -0
- package/dist/devtools/profiler/funpixel-profiler.threejs.min.js +1 -0
- package/dist/direct/moves.js +234 -0
- package/dist/direct/read.js +59 -0
- package/dist/direct/round.js +80 -0
- package/dist/doctor/host.js +245 -0
- package/dist/doctor/unity-checks.js +380 -0
- package/dist/doctor/unity-history.js +589 -0
- package/dist/doctor/unity-host.js +160 -0
- package/dist/doctor/unity-import-rules.js +874 -0
- package/dist/doctor/unity-meta.js +225 -0
- package/dist/doctor/unity-project.js +297 -0
- package/dist/doctor/unity.js +171 -0
- package/dist/export/export.js +165 -0
- package/dist/export/metadata.js +25 -0
- package/dist/export/runtime.js +119 -0
- package/dist/export/scan.js +78 -0
- package/dist/export/select.js +193 -0
- package/dist/export/strip.js +42 -0
- package/dist/feedback/ab.js +55 -0
- package/dist/feedback/auto.js +44 -0
- package/dist/feedback/learn.js +255 -0
- package/dist/feedback/measure.js +49 -0
- package/dist/feedback/page.js +66 -0
- package/dist/feel/feedback.js +85 -0
- package/dist/feel/judge.js +420 -0
- package/dist/feel/run.js +185 -0
- package/dist/feel/spec.js +124 -0
- package/dist/feel/sweep.js +156 -0
- package/dist/fidelity/consistency.js +205 -0
- package/dist/fidelity/match.js +675 -0
- package/dist/fidelity/run.js +107 -0
- package/dist/find/keywords.js +97 -0
- package/dist/find/names.js +45 -0
- package/dist/find/route.js +59 -0
- package/dist/firstlook/quality.js +261 -0
- package/dist/firstlook/render.js +111 -0
- package/dist/firstlook/set.js +218 -0
- package/dist/flow/flow.js +455 -0
- package/dist/flow/look.js +139 -0
- package/dist/frame/behaviour.js +53 -0
- package/dist/frame/clock.js +117 -0
- package/dist/frame/contract.js +111 -0
- package/dist/frame/genre.js +65 -0
- package/dist/frame/idle.js +58 -0
- package/dist/frame/opening.js +171 -0
- package/dist/frames/loop.js +52 -0
- package/dist/frames/sheet.js +69 -0
- package/dist/gdd/book.js +483 -0
- package/dist/gdd/chapters.js +71 -0
- package/dist/gdd/design.js +135 -0
- package/dist/gdd/doc.js +32 -0
- package/dist/gdd/levelmap.js +428 -0
- package/dist/gdd/measures.js +477 -0
- package/dist/gdd/page.js +111 -0
- package/dist/gdd/rubric.js +250 -0
- package/dist/gdd/size.js +83 -0
- package/dist/gdd/tiers.js +148 -0
- package/dist/gdd/world.js +98 -0
- package/dist/gdd/worth.js +507 -0
- package/dist/gen/kinds.js +451 -0
- package/dist/gen/local/doctor.js +25 -0
- package/dist/gen/local/index.js +3 -0
- package/dist/gen/local/kokoro.js +334 -0
- package/dist/gen/local/master.js +248 -0
- package/dist/gen/local/provider.js +65 -0
- package/dist/gen/local/voice-rules.js +156 -0
- package/dist/gen/models.generated.js +469 -0
- package/dist/gen/models.js +53 -0
- package/dist/gen/prompt-lint.js +35 -0
- package/dist/gen/record.js +73 -0
- package/dist/gen/save.js +101 -0
- package/dist/gen/title.js +55 -0
- package/dist/gen/unity.js +334 -0
- package/dist/goals/goals.js +204 -0
- package/dist/goals/run.js +90 -0
- package/dist/greenlight/ambition.js +42 -0
- package/dist/greenlight/bible.js +138 -0
- package/dist/greenlight/lock.js +48 -0
- package/dist/greenlight/match.js +19 -0
- package/dist/greenlight/md.js +82 -0
- package/dist/greenlight/page.js +100 -0
- package/dist/greenlight/pitches.js +66 -0
- package/dist/greenlight/worth.js +90 -0
- package/dist/guidance.js +24 -0
- package/dist/init/bare.js +114 -0
- package/dist/init/git.js +56 -0
- package/dist/init/starter.js +166 -0
- package/dist/init/starters.js +179 -0
- package/dist/inspect/describe.js +125 -0
- package/dist/inspect/devserver.js +40 -0
- package/dist/journey/diff.js +74 -0
- package/dist/journey/from-round.js +44 -0
- package/dist/journey/record.js +76 -0
- package/dist/journey/run.js +139 -0
- package/dist/journey/script.js +223 -0
- package/dist/judge/common.js +60 -0
- package/dist/judge/identity.js +68 -0
- package/dist/judge/sources.js +37 -0
- package/dist/judge/structure.js +59 -0
- package/dist/keys/device.js +145 -0
- package/dist/keys/store.js +167 -0
- package/dist/lanes/fence.js +108 -0
- package/dist/lanes/gate.js +123 -0
- package/dist/lanes/lanes.js +355 -0
- package/dist/lanes/union.js +62 -0
- package/dist/lanes/where.js +49 -0
- package/dist/lessons/motifs.js +97 -0
- package/dist/lessons/store.js +56 -0
- package/dist/look/anim.js +206 -0
- package/dist/look/boxes.js +209 -0
- package/dist/look/dressing.js +24 -0
- package/dist/look/feedback.js +50 -0
- package/dist/look/fit.js +123 -0
- package/dist/look/held.js +92 -0
- package/dist/look/hook.js +169 -0
- package/dist/look/hud.js +189 -0
- package/dist/look/image-io.js +50 -0
- package/dist/look/life.js +96 -0
- package/dist/look/light.js +42 -0
- package/dist/look/look.js +85 -0
- package/dist/look/loops.js +108 -0
- package/dist/look/made-of.js +242 -0
- package/dist/look/moments.js +32 -0
- package/dist/look/motion.js +44 -0
- package/dist/look/phone-play.js +142 -0
- package/dist/look/player.js +32 -0
- package/dist/look/png.js +117 -0
- package/dist/look/readability.js +100 -0
- package/dist/look/roles.js +109 -0
- package/dist/look/sheet.js +104 -0
- package/dist/look/theme.js +278 -0
- package/dist/look/touch.js +129 -0
- package/dist/look/ui-style.js +102 -0
- package/dist/machine/procs.js +117 -0
- package/dist/managed.js +15 -0
- package/dist/mcp/hosted.js +174 -0
- package/dist/mcp/models.generated.js +538 -0
- package/dist/mcp/models.js +35 -0
- package/dist/mcp/server.js +330 -0
- package/dist/memory/decisions.js +138 -0
- package/dist/memory/journal.js +108 -0
- package/dist/model/bench.js +83 -0
- package/dist/model/blender.js +106 -0
- package/dist/model/clips.js +34 -0
- package/dist/model/finalize.js +33 -0
- package/dist/motion/checks.js +173 -0
- package/dist/motion/contract.js +177 -0
- package/dist/motion/encode.js +37 -0
- package/dist/motion/render.js +167 -0
- package/dist/motion/starter.js +54 -0
- package/dist/optimize/check.js +29 -0
- package/dist/optimize/helper.js +80 -0
- package/dist/owner/bar.js +285 -0
- package/dist/owner/match.js +105 -0
- package/dist/pack/build.js +97 -0
- package/dist/pack/deps.js +28 -0
- package/dist/pack/leaks.js +77 -0
- package/dist/pack/limits.js +51 -0
- package/dist/pack/report.js +35 -0
- package/dist/phone/baguette.js +139 -0
- package/dist/phone/listen.js +65 -0
- package/dist/pipeline/pipeline.js +929 -0
- package/dist/plan/actions.js +18 -0
- package/dist/plan/notes.js +15 -0
- package/dist/play/clock.js +40 -0
- package/dist/play/condition.js +45 -0
- package/dist/play/frames.js +60 -0
- package/dist/play/input.js +118 -0
- package/dist/play/pointer.js +21 -0
- package/dist/play/report.js +124 -0
- package/dist/play/server.js +274 -0
- package/dist/play/session.js +231 -0
- package/dist/play/steps.js +192 -0
- package/dist/playable/build.js +90 -0
- package/dist/playable/cta.js +88 -0
- package/dist/playable/networks.js +33 -0
- package/dist/playable/scan.js +46 -0
- package/dist/playtest/after-round.js +60 -0
- package/dist/playtest/assemble.js +168 -0
- package/dist/playtest/experience-run.js +69 -0
- package/dist/playtest/experience.js +77 -0
- package/dist/playtest/facts.js +90 -0
- package/dist/playtest/fidelity.js +179 -0
- package/dist/playtest/history.js +115 -0
- package/dist/playtest/hits.js +48 -0
- package/dist/playtest/hosted.js +98 -0
- package/dist/playtest/keep.js +110 -0
- package/dist/playtest/ledger.js +77 -0
- package/dist/playtest/length.js +113 -0
- package/dist/playtest/measure.js +181 -0
- package/dist/playtest/mobile-qa.js +391 -0
- package/dist/playtest/mockups.js +198 -0
- package/dist/playtest/moments.js +28 -0
- package/dist/playtest/prepare.js +162 -0
- package/dist/playtest/rank.js +184 -0
- package/dist/playtest/report.js +209 -0
- package/dist/playtest/route.js +139 -0
- package/dist/playtest/seats.js +128 -0
- package/dist/playtest/sheet.js +38 -0
- package/dist/playtest/stop.js +54 -0
- package/dist/playtest/stuck.js +47 -0
- package/dist/production/contract.js +61 -0
- package/dist/production/mirror.js +96 -0
- package/dist/production/tier.js +66 -0
- package/dist/profile/compare.js +171 -0
- package/dist/progress/answers.js +35 -0
- package/dist/progress/holds.js +106 -0
- package/dist/progress/notify.js +25 -0
- package/dist/progress/progress.js +300 -0
- package/dist/publish/build.js +54 -0
- package/dist/publish/folder.js +106 -0
- package/dist/publish/funpixel.js +96 -0
- package/dist/publish/hosts.js +48 -0
- package/dist/reach/envelope.js +111 -0
- package/dist/reach/load.js +84 -0
- package/dist/reach/side.js +320 -0
- package/dist/reach/spec3d.js +338 -0
- package/dist/reach/tiles.js +163 -0
- package/dist/reel/encode.js +34 -0
- package/dist/reel/tour.js +81 -0
- package/dist/relay/bots.js +62 -0
- package/dist/relay/bridge.js +54 -0
- package/dist/relay/local.js +82 -0
- package/dist/relay/redis.js +40 -0
- package/dist/review/audio.js +72 -0
- package/dist/review/ledger.js +60 -0
- package/dist/review/media.js +114 -0
- package/dist/review/model.js +348 -0
- package/dist/review/picture.js +113 -0
- package/dist/review/specs.js +134 -0
- package/dist/review/video.js +248 -0
- package/dist/schema/game.js +308 -0
- package/dist/score/comfort.js +79 -0
- package/dist/score/light.js +62 -0
- package/dist/score/measure.js +386 -0
- package/dist/score/vision.js +59 -0
- package/dist/serve/webgl.js +415 -0
- package/dist/setup/lsp.js +42 -0
- package/dist/sim/curve.js +122 -0
- package/dist/sim/judge.js +240 -0
- package/dist/sim/skeleton.js +65 -0
- package/dist/simulator/lease.js +159 -0
- package/dist/simulator/orient.js +57 -0
- package/dist/simulator/screen.js +113 -0
- package/dist/simulator/simctl.js +79 -0
- package/dist/smoke/art.js +20 -0
- package/dist/smoke/checks.js +165 -0
- package/dist/smoke/logic.js +73 -0
- package/dist/smoke/orphans.js +78 -0
- package/dist/smoke/palette.js +16 -0
- package/dist/smoke/sources.js +36 -0
- package/dist/sound/beats.js +95 -0
- package/dist/sound/loudness.js +94 -0
- package/dist/spec/extract.js +123 -0
- package/dist/spec/lint.js +261 -0
- package/dist/spec/presets.js +30 -0
- package/dist/spec/rooms.js +188 -0
- package/dist/spec/scaffold.js +457 -0
- package/dist/spec/sections.js +16 -0
- package/dist/spec/tunables.js +74 -0
- package/dist/stage/harnessignore.js +90 -0
- package/dist/stage/stage.js +57 -0
- package/dist/stage/tar.js +41 -0
- package/dist/status/board.js +172 -0
- package/dist/status/file.js +112 -0
- package/dist/status/inbox.js +55 -0
- package/dist/status/status.js +311 -0
- package/dist/store/answers.js +47 -0
- package/dist/store/doctor.js +120 -0
- package/dist/store/images.js +65 -0
- package/dist/store/init.js +101 -0
- package/dist/store/lint.js +392 -0
- package/dist/store/plan.js +133 -0
- package/dist/store/sdks.js +107 -0
- package/dist/studio/forks.js +93 -0
- package/dist/studio/pitch.js +294 -0
- package/dist/studio/widen.js +212 -0
- package/dist/suite/node-run.js +81 -0
- package/dist/suite/test-types.js +71 -0
- package/dist/trailer/assemble.js +90 -0
- package/dist/trailer/beats.js +74 -0
- package/dist/trailer/cards.js +77 -0
- package/dist/trailer/cues.js +78 -0
- package/dist/trailer/cut.js +49 -0
- package/dist/trailer/find.js +33 -0
- package/dist/trailer/mix.js +109 -0
- package/dist/trailer/placement.js +30 -0
- package/dist/types.js +1 -0
- package/dist/ui.js +79 -0
- package/dist/unity/bridge.js +251 -0
- package/dist/unity/disk.js +666 -0
- package/dist/unity/editor.js +471 -0
- package/dist/unity/gc.js +140 -0
- package/dist/unity/mcp-stdio.js +141 -0
- package/dist/unity/probe/budgets.js +84 -0
- package/dist/unity/probe/client.js +93 -0
- package/dist/unity/probe/install.js +118 -0
- package/dist/unity/probe/player.js +255 -0
- package/dist/unity/probe/report.js +102 -0
- package/dist/unity/probe/script.js +225 -0
- package/dist/unity/queue.js +353 -0
- package/dist/unity/run.js +172 -0
- package/dist/update.js +111 -0
- package/dist/variety/compare.js +104 -0
- package/dist/variety/places.js +109 -0
- package/dist/variety/profile.js +127 -0
- package/dist/vendor/verify/README.md +19 -0
- package/dist/vendor/verify/package.json +14 -0
- package/dist/vendor/verify/src/index.d.ts +105 -0
- package/dist/vendor/verify/src/index.js +78 -0
- package/dist/vendor/verify/src/init/preview_shim.js +63 -0
- package/dist/vendor/verify/src/page/actors.js +258 -0
- package/dist/vendor/verify/src/page/audio.js +106 -0
- package/dist/vendor/verify/src/page/audio_cues.js +141 -0
- package/dist/vendor/verify/src/page/audio_files.js +56 -0
- package/dist/vendor/verify/src/page/bot_sweep.js +72 -0
- package/dist/vendor/verify/src/page/capture_view.js +164 -0
- package/dist/vendor/verify/src/page/context_loss_listener.js +23 -0
- package/dist/vendor/verify/src/page/dressing.js +106 -0
- package/dist/vendor/verify/src/page/enter_view.js +33 -0
- package/dist/vendor/verify/src/page/feel.js +126 -0
- package/dist/vendor/verify/src/page/feel_sweep.js +75 -0
- package/dist/vendor/verify/src/page/first_paint.js +54 -0
- package/dist/vendor/verify/src/page/fonts.js +50 -0
- package/dist/vendor/verify/src/page/frame_honesty.js +44 -0
- package/dist/vendor/verify/src/page/front_door.js +197 -0
- package/dist/vendor/verify/src/page/grounding.js +448 -0
- package/dist/vendor/verify/src/page/hooks.js +74 -0
- package/dist/vendor/verify/src/page/hud.js +261 -0
- package/dist/vendor/verify/src/page/inventory.js +15 -0
- package/dist/vendor/verify/src/page/layout.js +378 -0
- package/dist/vendor/verify/src/page/levels.js +40 -0
- package/dist/vendor/verify/src/page/life.js +123 -0
- package/dist/vendor/verify/src/page/life_anim.js +501 -0
- package/dist/vendor/verify/src/page/made_of.js +83 -0
- package/dist/vendor/verify/src/page/mechanic_check.js +272 -0
- package/dist/vendor/verify/src/page/moments.js +36 -0
- package/dist/vendor/verify/src/page/motion.js +139 -0
- package/dist/vendor/verify/src/page/perf.js +255 -0
- package/dist/vendor/verify/src/page/phone_check.js +229 -0
- package/dist/vendor/verify/src/page/play.js +117 -0
- package/dist/vendor/verify/src/page/play_act.js +164 -0
- package/dist/vendor/verify/src/page/preview.js +33 -0
- package/dist/vendor/verify/src/page/recorder.js +54 -0
- package/dist/vendor/verify/src/page/render_health.js +83 -0
- package/dist/vendor/verify/src/page/renderer.js +75 -0
- package/dist/vendor/verify/src/page/scene.js +222 -0
- package/dist/vendor/verify/src/page/self_test.js +25 -0
- package/dist/vendor/verify/src/page/step_clock.js +247 -0
- package/dist/vendor/verify/src/page/surfaces.js +261 -0
- package/dist/vendor/verify/src/page/world_actors.js +264 -0
- package/dist/verify/browser.js +245 -0
- package/dist/verify/console.js +34 -0
- package/dist/verify/fingerprint.js +72 -0
- package/dist/verify/gpu.js +33 -0
- package/dist/verify/health.js +172 -0
- package/dist/verify/hooks.js +34 -0
- package/dist/verify/judge.js +303 -0
- package/dist/verify/players.js +123 -0
- package/dist/verify/probe.js +236 -0
- package/dist/verify/reads.js +32 -0
- package/dist/verify/run.js +56 -0
- package/dist/verify/serve.js +36 -0
- package/dist/walk/film.js +37 -0
- package/dist/walk/judge.js +287 -0
- package/dist/walk/routes.js +199 -0
- package/dist/walk/world.js +292 -0
- package/dist/world/brief.js +86 -0
- package/dist/world/check.js +254 -0
- package/dist/world/forge.js +542 -0
- package/dist/world/format.js +40 -0
- package/dist/world/variety.js +59 -0
- package/dist/wow/catalogue.js +86 -0
- package/dist/wow/picks.js +74 -0
- package/package.json +51 -4
- package/panel/asset-identity.md +61 -0
- package/panel/asset-structure.md +55 -0
- package/panel/blockers.md +47 -0
- package/panel/brief.md +89 -0
- package/panel/clip.md +54 -0
- package/panel/experience-personas.json +4 -0
- package/panel/experience.md +96 -0
- package/panel/fidelity-ui.md +74 -0
- package/panel/fidelity.md +83 -0
- package/panel/greenlight-pitch.md +69 -0
- package/panel/greenlight.md +87 -0
- package/panel/mobile-qa.md +128 -0
- package/panel/personas.json +6 -0
- package/panel/reference-match.md +12 -0
- package/panel/versus.md +31 -0
- package/plugins/.agents/plugins/marketplace.json +18 -0
- package/plugins/.claude-plugin/marketplace.json +17 -0
- package/plugins/.cursor-plugin/marketplace.json +13 -0
- package/plugins/LICENSE +115 -0
- package/plugins/README.md +16 -0
- package/plugins/THIRD_PARTY_NOTICES.md +75 -0
- package/plugins/claude/.claude-plugin/plugin.json +19 -0
- package/plugins/claude/.mcp.json +10 -0
- package/plugins/claude/LICENSE +115 -0
- package/plugins/claude/README.md +14 -0
- package/plugins/claude/THIRD_PARTY_NOTICES.md +75 -0
- package/plugins/claude/agents/art-director.md +54 -0
- package/plugins/claude/agents/audio-director.md +51 -0
- package/plugins/claude/agents/critic.md +113 -0
- package/plugins/claude/agents/lane.md +38 -0
- package/plugins/claude/agents/level-designer.md +45 -0
- package/plugins/claude/agents/mobile-qa.md +71 -0
- package/plugins/claude/agents/player.md +144 -0
- package/plugins/claude/agents/qa-lead.md +52 -0
- package/plugins/claude/commands/first-look.md +59 -0
- package/plugins/claude/commands/flow.md +50 -0
- package/plugins/claude/commands/lanes.md +38 -0
- package/plugins/claude/commands/mobile-qa.md +28 -0
- package/plugins/claude/commands/new.md +94 -0
- package/plugins/claude/commands/playtest.md +66 -0
- package/plugins/claude/commands/publish.md +23 -0
- package/plugins/claude/commands/smoke-build.md +25 -0
- package/plugins/claude/commands/verify.md +20 -0
- package/plugins/claude/hooks/brief.md +135 -0
- package/plugins/claude/hooks/critic-receipts.mjs +86 -0
- package/plugins/claude/hooks/durable.mjs +56 -0
- package/plugins/claude/hooks/fence.mjs +30 -0
- package/plugins/claude/hooks/floors.mjs +181 -0
- package/plugins/claude/hooks/flow.mjs +154 -0
- package/plugins/claude/hooks/front-door.mjs +68 -0
- package/plugins/claude/hooks/guidance.json +3 -0
- package/plugins/claude/hooks/hints.mjs +183 -0
- package/plugins/claude/hooks/hooks.json +62 -0
- package/plugins/claude/hooks/lib.mjs +362 -0
- package/plugins/claude/hooks/memory.mjs +92 -0
- package/plugins/claude/hooks/mobile-qa.mjs +43 -0
- package/plugins/claude/hooks/note.mjs +63 -0
- package/plugins/claude/hooks/nudge.mjs +98 -0
- package/plugins/claude/hooks/pipeline.mjs +207 -0
- package/plugins/claude/hooks/prompt.mjs +51 -0
- package/plugins/claude/hooks/quality.mjs +310 -0
- package/plugins/claude/hooks/reach.mjs +93 -0
- package/plugins/claude/hooks/scope.mjs +44 -0
- package/plugins/claude/hooks/session-log.mjs +101 -0
- package/plugins/claude/hooks/session-start.mjs +194 -0
- package/plugins/claude/hooks/skill-names.json +19 -0
- package/plugins/claude/hooks/stop-gate.mjs +303 -0
- package/plugins/claude/hooks/vendor/direct/round.mjs +81 -0
- package/plugins/claude/hooks/vendor/find/names.mjs +46 -0
- package/plugins/claude/hooks/vendor/firstlook/set.mjs +219 -0
- package/plugins/claude/hooks/vendor/flow/flow.mjs +456 -0
- package/plugins/claude/hooks/vendor/flow/look.mjs +140 -0
- package/plugins/claude/hooks/vendor/gdd/book.mjs +484 -0
- package/plugins/claude/hooks/vendor/gdd/chapters.mjs +72 -0
- package/plugins/claude/hooks/vendor/gdd/doc.mjs +33 -0
- package/plugins/claude/hooks/vendor/gdd/levelmap.mjs +429 -0
- package/plugins/claude/hooks/vendor/gdd/rubric.mjs +251 -0
- package/plugins/claude/hooks/vendor/gdd/worth.mjs +508 -0
- package/plugins/claude/hooks/vendor/lanes/fence.mjs +109 -0
- package/plugins/claude/hooks/vendor/lanes/lanes.mjs +356 -0
- package/plugins/claude/hooks/vendor/lanes/union.mjs +63 -0
- package/plugins/claude/hooks/vendor/lessons/motifs.mjs +98 -0
- package/plugins/claude/hooks/vendor/lessons/store.mjs +57 -0
- package/plugins/claude/hooks/vendor/look/made-of.mjs +243 -0
- package/plugins/claude/hooks/vendor/look/roles.mjs +110 -0
- package/plugins/claude/hooks/vendor/memory/decisions.mjs +139 -0
- package/plugins/claude/hooks/vendor/memory/journal.mjs +109 -0
- package/plugins/claude/hooks/vendor/owner/bar.mjs +286 -0
- package/plugins/claude/hooks/vendor/pipeline/pipeline.mjs +930 -0
- package/plugins/claude/hooks/vendor/playtest/keep.mjs +111 -0
- package/plugins/claude/hooks/vendor/playtest/stuck.mjs +48 -0
- package/plugins/claude/hooks/vendor/progress/holds.mjs +107 -0
- package/plugins/claude/hooks/vendor/progress/progress.mjs +301 -0
- package/plugins/claude/hooks/vendor/sim/judge.mjs +241 -0
- package/plugins/claude/hooks/vendor/spec/rooms.mjs +189 -0
- package/plugins/claude/hooks/vendor/spec/tunables.mjs +75 -0
- package/plugins/claude/hooks/vendor/stage/harnessignore.mjs +91 -0
- package/plugins/claude/hooks/vendor/stage/stage.mjs +58 -0
- package/plugins/claude/hooks/vendor/status/board.mjs +173 -0
- package/plugins/claude/hooks/vendor/status/file.mjs +113 -0
- package/plugins/claude/hooks/vendor/studio/forks.mjs +94 -0
- package/plugins/claude/hooks/vendor/studio/pitch.mjs +295 -0
- package/plugins/claude/hooks/vendor/verify/fingerprint.mjs +73 -0
- package/plugins/claude/hooks/vendor/verify/reads.mjs +33 -0
- package/plugins/claude/hooks/vendor/wow/picks.mjs +75 -0
- package/plugins/claude/skills/3d/SKILL.md +89 -0
- package/plugins/claude/skills/3d/references/bake-off.md +48 -0
- package/plugins/claude/skills/3d/references/bench.md +103 -0
- package/plugins/claude/skills/3d/references/budgets.md +48 -0
- package/plugins/claude/skills/3d/references/characters.md +67 -0
- package/plugins/claude/skills/3d/references/concept-image.md +47 -0
- package/plugins/claude/skills/3d/references/engine-targets.md +31 -0
- package/plugins/claude/skills/3d/references/hero-route.md +104 -0
- package/plugins/claude/skills/3d/references/level-spec.md +109 -0
- package/plugins/claude/skills/3d/references/levels.md +84 -0
- package/plugins/claude/skills/3d/references/light-and-places.md +141 -0
- package/plugins/claude/skills/3d/references/models.md +111 -0
- package/plugins/claude/skills/3d/references/painted-target.md +184 -0
- package/plugins/claude/skills/3d/references/reading.md +41 -0
- package/plugins/claude/skills/3d/references/skin.md +85 -0
- package/plugins/claude/skills/3d/references/skyboxes.md +65 -0
- package/plugins/claude/skills/3d/references/textures.md +71 -0
- package/plugins/claude/skills/3d/references/three-loading.md +199 -0
- package/plugins/claude/skills/3d/references/unity.md +78 -0
- package/plugins/claude/skills/art/SKILL.md +104 -0
- package/plugins/claude/skills/art/references/2d-assets.md +108 -0
- package/plugins/claude/skills/art/references/animation.md +126 -0
- package/plugins/claude/skills/art/references/cast.md +73 -0
- package/plugins/claude/skills/art/references/characters.md +49 -0
- package/plugins/claude/skills/art/references/cost.md +107 -0
- package/plugins/claude/skills/art/references/effects.md +85 -0
- package/plugins/claude/skills/art/references/frames.md +87 -0
- package/plugins/claude/skills/art/references/judging-frames.md +64 -0
- package/plugins/claude/skills/art/references/look.md +102 -0
- package/plugins/claude/skills/art/references/measure.md +119 -0
- package/plugins/claude/skills/art/references/pipeline.md +185 -0
- package/plugins/claude/skills/art/references/pixi.md +277 -0
- package/plugins/claude/skills/art/references/planes.md +27 -0
- package/plugins/claude/skills/art/references/prompts.md +171 -0
- package/plugins/claude/skills/art/references/sheets.md +141 -0
- package/plugins/claude/skills/art/references/style-file.md +39 -0
- package/plugins/claude/skills/art/references/three.md +232 -0
- package/plugins/claude/skills/art/references/ui.md +163 -0
- package/plugins/claude/skills/art/references/unity.md +78 -0
- package/plugins/claude/skills/art/references/wiring.md +41 -0
- package/plugins/claude/skills/audio/SKILL.md +92 -0
- package/plugins/claude/skills/audio/references/adaptive-music.md +204 -0
- package/plugins/claude/skills/audio/references/engine.md +78 -0
- package/plugins/claude/skills/audio/references/measure.md +101 -0
- package/plugins/claude/skills/audio/references/unity.md +74 -0
- package/plugins/claude/skills/feedback/SKILL.md +120 -0
- package/plugins/claude/skills/feedback/references/memory.md +99 -0
- package/plugins/claude/skills/game-feel/SKILL.md +104 -0
- package/plugins/claude/skills/game-feel/references/contact.md +110 -0
- package/plugins/claude/skills/game-feel/references/measure.md +125 -0
- package/plugins/claude/skills/game-feel/references/motion.md +134 -0
- package/plugins/claude/skills/game-feel/references/payoffs.md +35 -0
- package/plugins/claude/skills/game-feel/references/recipes.md +107 -0
- package/plugins/claude/skills/game-feel/references/unity.md +73 -0
- package/plugins/claude/skills/game-logic/SKILL.md +113 -0
- package/plugins/claude/skills/game-logic/references/balance.md +88 -0
- package/plugins/claude/skills/game-logic/references/content-at-scale.md +147 -0
- package/plugins/claude/skills/game-logic/references/depth.md +89 -0
- package/plugins/claude/skills/game-logic/references/escalation.md +41 -0
- package/plugins/claude/skills/game-logic/references/levels.md +61 -0
- package/plugins/claude/skills/game-logic/references/probes.md +122 -0
- package/plugins/claude/skills/game-logic/references/unity.md +108 -0
- package/plugins/claude/skills/game-spine/SKILL.md +118 -0
- package/plugins/claude/skills/game-spine/references/camera.md +94 -0
- package/plugins/claude/skills/game-spine/references/multiplayer.md +101 -0
- package/plugins/claude/skills/game-spine/references/patterns.md +103 -0
- package/plugins/claude/skills/game-spine/references/performance.md +96 -0
- package/plugins/claude/skills/game-spine/references/pixi.md +26 -0
- package/plugins/claude/skills/game-spine/references/replay.md +102 -0
- package/plugins/claude/skills/game-spine/references/room-api.md +63 -0
- package/plugins/claude/skills/game-spine/references/room-modes.md +40 -0
- package/plugins/claude/skills/game-spine/references/sdk.md +114 -0
- package/plugins/claude/skills/game-spine/references/three.md +62 -0
- package/plugins/claude/skills/gdd/SKILL.md +116 -0
- package/plugins/claude/skills/gdd/references/as-built.md +40 -0
- package/plugins/claude/skills/gdd/references/design-measures.md +24 -0
- package/plugins/claude/skills/gdd/references/design-note.md +88 -0
- package/plugins/claude/skills/gdd/references/experience.md +92 -0
- package/plugins/claude/skills/gdd/references/first-look.md +226 -0
- package/plugins/claude/skills/gdd/references/floors.md +62 -0
- package/plugins/claude/skills/gdd/references/frame.md +75 -0
- package/plugins/claude/skills/gdd/references/gameplay-contract.md +81 -0
- package/plugins/claude/skills/gdd/references/gdd-template.md +417 -0
- package/plugins/claude/skills/gdd/references/genre-card.md +109 -0
- package/plugins/claude/skills/gdd/references/genre-platformer.md +159 -0
- package/plugins/claude/skills/gdd/references/genre-puzzle.md +145 -0
- package/plugins/claude/skills/gdd/references/genre-racing.md +137 -0
- package/plugins/claude/skills/gdd/references/genre-rpg.md +125 -0
- package/plugins/claude/skills/gdd/references/genre-shooter.md +128 -0
- package/plugins/claude/skills/gdd/references/genre-simulation.md +112 -0
- package/plugins/claude/skills/gdd/references/genre-strategy.md +116 -0
- package/plugins/claude/skills/gdd/references/genre-survival.md +122 -0
- package/plugins/claude/skills/gdd/references/in-the-loop.md +106 -0
- package/plugins/claude/skills/gdd/references/invent-first.md +131 -0
- package/plugins/claude/skills/gdd/references/level-and-fun.md +112 -0
- package/plugins/claude/skills/gdd/references/pages.md +47 -0
- package/plugins/claude/skills/gdd/references/plan-at-size.md +140 -0
- package/plugins/claude/skills/gdd/references/production-tiers.md +117 -0
- package/plugins/claude/skills/gdd/references/sections.md +148 -0
- package/plugins/claude/skills/gdd/references/spec-folder.md +131 -0
- package/plugins/claude/skills/gdd/references/start.md +110 -0
- package/plugins/claude/skills/gdd/references/starters.md +175 -0
- package/plugins/claude/skills/gdd/references/the-path.md +133 -0
- package/plugins/claude/skills/gdd/references/track.md +29 -0
- package/plugins/claude/skills/gdd/references/world-and-identity.md +165 -0
- package/plugins/claude/skills/gdd/references/worth.md +74 -0
- package/plugins/claude/skills/mobile-ui/SKILL.md +107 -0
- package/plugins/claude/skills/mobile-ui/references/contrast.md +123 -0
- package/plugins/claude/skills/mobile-ui/references/hud-and-title.md +108 -0
- package/plugins/claude/skills/mobile-ui/references/hud-genres.md +124 -0
- package/plugins/claude/skills/mobile-ui/references/phone-check.md +156 -0
- package/plugins/claude/skills/mobile-ui/references/recipes.md +279 -0
- package/plugins/claude/skills/mobile-ui/references/restyle-ui.md +229 -0
- package/plugins/claude/skills/mobile-ui/references/unity.md +61 -0
- package/plugins/claude/skills/publishing/SKILL.md +109 -0
- package/plugins/claude/skills/publishing/references/compose.md +113 -0
- package/plugins/claude/skills/publishing/references/motion.md +120 -0
- package/plugins/claude/skills/publishing/references/networks.md +75 -0
- package/plugins/claude/skills/publishing/references/other-hosts.md +65 -0
- package/plugins/claude/skills/publishing/references/playable-ad.md +90 -0
- package/plugins/claude/skills/publishing/references/server-build.md +85 -0
- package/plugins/claude/skills/publishing/references/store-shots.md +85 -0
- package/plugins/claude/skills/publishing/references/trailer.md +55 -0
- package/plugins/claude/skills/publishing/references/what-ships.md +30 -0
- package/plugins/claude/skills/store/SKILL.md +81 -0
- package/plugins/claude/skills/store/references/app-store.md +73 -0
- package/plugins/claude/skills/store/references/google-play.md +141 -0
- package/plugins/claude/skills/store/references/ios-release.md +63 -0
- package/plugins/claude/skills/store/references/money.md +66 -0
- package/plugins/claude/skills/store/references/purchases-and-review.md +74 -0
- package/plugins/claude/skills/store/references/readiness-page.md +24 -0
- package/plugins/claude/skills/store/references/readiness.md +107 -0
- package/plugins/claude/skills/store/references/steam.md +38 -0
- package/plugins/claude/skills/store/references/unity-store.md +55 -0
- package/plugins/claude/skills/store/references/web-portals.md +43 -0
- package/plugins/claude/skills/unity-game/SKILL.md +103 -0
- package/plugins/claude/skills/unity-game/references/agent-ops.md +54 -0
- package/plugins/claude/skills/unity-game/references/fixes.md +40 -0
- package/plugins/claude/skills/unity-game/references/from-a-web-game.md +108 -0
- package/plugins/claude/skills/unity-game/references/handing-off.md +42 -0
- package/plugins/claude/skills/unity-game/references/performance.md +59 -0
- package/plugins/claude/skills/unity-game/references/probe.md +80 -0
- package/plugins/claude/skills/unity-game/references/shared-mac.md +121 -0
- package/plugins/claude/skills/unity-game/references/traps.md +108 -0
- package/plugins/claude/skills/verifying/SKILL.md +109 -0
- package/plugins/claude/skills/verifying/references/actors.md +94 -0
- package/plugins/claude/skills/verifying/references/bar.md +62 -0
- package/plugins/claude/skills/verifying/references/checks.md +69 -0
- package/plugins/claude/skills/verifying/references/experience.md +67 -0
- package/plugins/claude/skills/verifying/references/eyes.md +54 -0
- package/plugins/claude/skills/verifying/references/fidelity.md +126 -0
- package/plugins/claude/skills/verifying/references/hit-bar.md +31 -0
- package/plugins/claude/skills/verifying/references/journeys.md +77 -0
- package/plugins/claude/skills/verifying/references/mobile-qa.md +123 -0
- package/plugins/claude/skills/verifying/references/playtest.md +161 -0
- package/plugins/claude/skills/verifying/references/review.md +105 -0
- package/plugins/claude/skills/verifying/references/rubric.md +67 -0
- package/plugins/claude/skills/verifying/references/scenes.md +49 -0
- package/plugins/claude/skills/verifying/references/unity.md +60 -0
- package/plugins/claude/skills/world-and-story/SKILL.md +99 -0
- package/plugins/claude/skills/world-and-story/references/atmosphere.md +208 -0
- package/plugins/claude/skills/world-and-story/references/forged-world.md +79 -0
- package/plugins/claude/skills/world-and-story/references/living-world.md +237 -0
- package/plugins/claude/skills/world-and-story/references/opening-and-chapters.md +215 -0
- package/plugins/claude/skills/world-and-story/references/shelf.md +80 -0
- package/plugins/claude/skills/world-and-story/references/story-at-size.md +159 -0
- package/plugins/claude/skills/world-and-story/references/voice.md +175 -0
- package/plugins/claude/skills/world-and-story/references/world-kit.md +154 -0
- package/plugins/codex/.codex-plugin/plugin.json +27 -0
- package/plugins/codex/.mcp.json +7 -0
- package/plugins/codex/AGENTS.md +135 -0
- package/plugins/codex/LICENSE +115 -0
- package/plugins/codex/README.md +17 -0
- package/plugins/codex/THIRD_PARTY_NOTICES.md +75 -0
- package/plugins/codex/hooks/brief.md +135 -0
- package/plugins/codex/hooks/codex-critic.mjs +15 -0
- package/plugins/codex/hooks/critic-receipts.mjs +86 -0
- package/plugins/codex/hooks/durable.mjs +56 -0
- package/plugins/codex/hooks/fence.mjs +30 -0
- package/plugins/codex/hooks/floors.mjs +181 -0
- package/plugins/codex/hooks/flow.mjs +154 -0
- package/plugins/codex/hooks/front-door.mjs +68 -0
- package/plugins/codex/hooks/guidance.json +3 -0
- package/plugins/codex/hooks/hints.mjs +183 -0
- package/plugins/codex/hooks/hooks.json +59 -0
- package/plugins/codex/hooks/host.md +54 -0
- package/plugins/codex/hooks/lib.mjs +362 -0
- package/plugins/codex/hooks/memory.mjs +92 -0
- package/plugins/codex/hooks/mobile-qa.mjs +43 -0
- package/plugins/codex/hooks/note.mjs +63 -0
- package/plugins/codex/hooks/nudge.mjs +98 -0
- package/plugins/codex/hooks/pipeline.mjs +207 -0
- package/plugins/codex/hooks/prompt.mjs +51 -0
- package/plugins/codex/hooks/quality.mjs +310 -0
- package/plugins/codex/hooks/reach.mjs +93 -0
- package/plugins/codex/hooks/scope.mjs +44 -0
- package/plugins/codex/hooks/session-log.mjs +101 -0
- package/plugins/codex/hooks/session-start.mjs +194 -0
- package/plugins/codex/hooks/stop-gate.mjs +303 -0
- package/plugins/codex/hooks/vendor/direct/round.mjs +81 -0
- package/plugins/codex/hooks/vendor/find/names.mjs +46 -0
- package/plugins/codex/hooks/vendor/firstlook/set.mjs +219 -0
- package/plugins/codex/hooks/vendor/flow/flow.mjs +456 -0
- package/plugins/codex/hooks/vendor/flow/look.mjs +140 -0
- package/plugins/codex/hooks/vendor/gdd/book.mjs +484 -0
- package/plugins/codex/hooks/vendor/gdd/chapters.mjs +72 -0
- package/plugins/codex/hooks/vendor/gdd/doc.mjs +33 -0
- package/plugins/codex/hooks/vendor/gdd/levelmap.mjs +429 -0
- package/plugins/codex/hooks/vendor/gdd/rubric.mjs +251 -0
- package/plugins/codex/hooks/vendor/gdd/worth.mjs +508 -0
- package/plugins/codex/hooks/vendor/lanes/fence.mjs +109 -0
- package/plugins/codex/hooks/vendor/lanes/lanes.mjs +356 -0
- package/plugins/codex/hooks/vendor/lanes/union.mjs +63 -0
- package/plugins/codex/hooks/vendor/lessons/motifs.mjs +98 -0
- package/plugins/codex/hooks/vendor/lessons/store.mjs +57 -0
- package/plugins/codex/hooks/vendor/look/made-of.mjs +243 -0
- package/plugins/codex/hooks/vendor/look/roles.mjs +110 -0
- package/plugins/codex/hooks/vendor/memory/decisions.mjs +139 -0
- package/plugins/codex/hooks/vendor/memory/journal.mjs +109 -0
- package/plugins/codex/hooks/vendor/owner/bar.mjs +286 -0
- package/plugins/codex/hooks/vendor/pipeline/pipeline.mjs +930 -0
- package/plugins/codex/hooks/vendor/playtest/keep.mjs +111 -0
- package/plugins/codex/hooks/vendor/playtest/stuck.mjs +48 -0
- package/plugins/codex/hooks/vendor/progress/holds.mjs +107 -0
- package/plugins/codex/hooks/vendor/progress/progress.mjs +301 -0
- package/plugins/codex/hooks/vendor/sim/judge.mjs +241 -0
- package/plugins/codex/hooks/vendor/spec/rooms.mjs +189 -0
- package/plugins/codex/hooks/vendor/spec/tunables.mjs +75 -0
- package/plugins/codex/hooks/vendor/stage/harnessignore.mjs +91 -0
- package/plugins/codex/hooks/vendor/stage/stage.mjs +58 -0
- package/plugins/codex/hooks/vendor/status/board.mjs +173 -0
- package/plugins/codex/hooks/vendor/status/file.mjs +113 -0
- package/plugins/codex/hooks/vendor/studio/forks.mjs +94 -0
- package/plugins/codex/hooks/vendor/studio/pitch.mjs +295 -0
- package/plugins/codex/hooks/vendor/verify/fingerprint.mjs +73 -0
- package/plugins/codex/hooks/vendor/verify/reads.mjs +33 -0
- package/plugins/codex/hooks/vendor/wow/picks.mjs +75 -0
- package/plugins/codex/mcp.json +9 -0
- package/plugins/codex/plugin.json +26 -0
- package/plugins/codex/skills/fp-art-director/SKILL.md +58 -0
- package/plugins/codex/skills/fp-art-director/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-art-director/references/codex.md +54 -0
- package/plugins/codex/skills/fp-audio-director/SKILL.md +55 -0
- package/plugins/codex/skills/fp-audio-director/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-audio-director/references/codex.md +54 -0
- package/plugins/codex/skills/fp-critic/SKILL.md +117 -0
- package/plugins/codex/skills/fp-critic/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-critic/references/codex.md +54 -0
- package/plugins/codex/skills/fp-first-look/SKILL.md +59 -0
- package/plugins/codex/skills/fp-first-look/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-flow/SKILL.md +50 -0
- package/plugins/codex/skills/fp-flow/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-lane/SKILL.md +41 -0
- package/plugins/codex/skills/fp-lane/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-lane/references/codex.md +54 -0
- package/plugins/codex/skills/fp-lanes/SKILL.md +38 -0
- package/plugins/codex/skills/fp-lanes/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-level-designer/SKILL.md +49 -0
- package/plugins/codex/skills/fp-level-designer/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-level-designer/references/codex.md +54 -0
- package/plugins/codex/skills/fp-mobile-qa/SKILL.md +28 -0
- package/plugins/codex/skills/fp-mobile-qa/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-mobile-qa-seat/SKILL.md +74 -0
- package/plugins/codex/skills/fp-mobile-qa-seat/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-mobile-qa-seat/references/codex.md +54 -0
- package/plugins/codex/skills/fp-new/SKILL.md +94 -0
- package/plugins/codex/skills/fp-new/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-player/SKILL.md +147 -0
- package/plugins/codex/skills/fp-player/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-player/references/codex.md +54 -0
- package/plugins/codex/skills/fp-playtest/SKILL.md +66 -0
- package/plugins/codex/skills/fp-playtest/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-publish/SKILL.md +23 -0
- package/plugins/codex/skills/fp-publish/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-qa-lead/SKILL.md +56 -0
- package/plugins/codex/skills/fp-qa-lead/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-qa-lead/references/codex.md +54 -0
- package/plugins/codex/skills/fp-smoke-build/SKILL.md +25 -0
- package/plugins/codex/skills/fp-smoke-build/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-studio/SKILL.md +59 -0
- package/plugins/codex/skills/fp-studio/agents/openai.yaml +12 -0
- package/plugins/codex/skills/fp-verify/SKILL.md +20 -0
- package/plugins/codex/skills/fp-verify/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-3d/SKILL.md +89 -0
- package/plugins/codex/skills/funpixel-3d/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-3d/references/bake-off.md +48 -0
- package/plugins/codex/skills/funpixel-3d/references/bench.md +103 -0
- package/plugins/codex/skills/funpixel-3d/references/budgets.md +48 -0
- package/plugins/codex/skills/funpixel-3d/references/characters.md +67 -0
- package/plugins/codex/skills/funpixel-3d/references/concept-image.md +47 -0
- package/plugins/codex/skills/funpixel-3d/references/engine-targets.md +31 -0
- package/plugins/codex/skills/funpixel-3d/references/hero-route.md +104 -0
- package/plugins/codex/skills/funpixel-3d/references/level-spec.md +109 -0
- package/plugins/codex/skills/funpixel-3d/references/levels.md +84 -0
- package/plugins/codex/skills/funpixel-3d/references/light-and-places.md +141 -0
- package/plugins/codex/skills/funpixel-3d/references/models.md +111 -0
- package/plugins/codex/skills/funpixel-3d/references/painted-target.md +184 -0
- package/plugins/codex/skills/funpixel-3d/references/reading.md +41 -0
- package/plugins/codex/skills/funpixel-3d/references/skin.md +85 -0
- package/plugins/codex/skills/funpixel-3d/references/skyboxes.md +65 -0
- package/plugins/codex/skills/funpixel-3d/references/textures.md +71 -0
- package/plugins/codex/skills/funpixel-3d/references/three-loading.md +199 -0
- package/plugins/codex/skills/funpixel-3d/references/unity.md +78 -0
- package/plugins/codex/skills/funpixel-art/SKILL.md +104 -0
- package/plugins/codex/skills/funpixel-art/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-art/references/2d-assets.md +108 -0
- package/plugins/codex/skills/funpixel-art/references/animation.md +126 -0
- package/plugins/codex/skills/funpixel-art/references/cast.md +73 -0
- package/plugins/codex/skills/funpixel-art/references/characters.md +49 -0
- package/plugins/codex/skills/funpixel-art/references/cost.md +107 -0
- package/plugins/codex/skills/funpixel-art/references/effects.md +85 -0
- package/plugins/codex/skills/funpixel-art/references/frames.md +87 -0
- package/plugins/codex/skills/funpixel-art/references/judging-frames.md +64 -0
- package/plugins/codex/skills/funpixel-art/references/look.md +102 -0
- package/plugins/codex/skills/funpixel-art/references/measure.md +119 -0
- package/plugins/codex/skills/funpixel-art/references/pipeline.md +185 -0
- package/plugins/codex/skills/funpixel-art/references/pixi.md +277 -0
- package/plugins/codex/skills/funpixel-art/references/planes.md +27 -0
- package/plugins/codex/skills/funpixel-art/references/prompts.md +171 -0
- package/plugins/codex/skills/funpixel-art/references/sheets.md +141 -0
- package/plugins/codex/skills/funpixel-art/references/style-file.md +39 -0
- package/plugins/codex/skills/funpixel-art/references/three.md +232 -0
- package/plugins/codex/skills/funpixel-art/references/ui.md +163 -0
- package/plugins/codex/skills/funpixel-art/references/unity.md +78 -0
- package/plugins/codex/skills/funpixel-art/references/wiring.md +41 -0
- package/plugins/codex/skills/funpixel-audio/SKILL.md +92 -0
- package/plugins/codex/skills/funpixel-audio/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-audio/references/adaptive-music.md +204 -0
- package/plugins/codex/skills/funpixel-audio/references/engine.md +78 -0
- package/plugins/codex/skills/funpixel-audio/references/measure.md +101 -0
- package/plugins/codex/skills/funpixel-audio/references/unity.md +74 -0
- package/plugins/codex/skills/funpixel-feedback/SKILL.md +120 -0
- package/plugins/codex/skills/funpixel-feedback/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-feedback/references/memory.md +99 -0
- package/plugins/codex/skills/funpixel-game-feel/SKILL.md +104 -0
- package/plugins/codex/skills/funpixel-game-feel/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-game-feel/references/contact.md +110 -0
- package/plugins/codex/skills/funpixel-game-feel/references/measure.md +125 -0
- package/plugins/codex/skills/funpixel-game-feel/references/motion.md +134 -0
- package/plugins/codex/skills/funpixel-game-feel/references/payoffs.md +35 -0
- package/plugins/codex/skills/funpixel-game-feel/references/recipes.md +107 -0
- package/plugins/codex/skills/funpixel-game-feel/references/unity.md +73 -0
- package/plugins/codex/skills/funpixel-game-logic/SKILL.md +113 -0
- package/plugins/codex/skills/funpixel-game-logic/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-game-logic/references/balance.md +88 -0
- package/plugins/codex/skills/funpixel-game-logic/references/content-at-scale.md +147 -0
- package/plugins/codex/skills/funpixel-game-logic/references/depth.md +89 -0
- package/plugins/codex/skills/funpixel-game-logic/references/escalation.md +41 -0
- package/plugins/codex/skills/funpixel-game-logic/references/levels.md +61 -0
- package/plugins/codex/skills/funpixel-game-logic/references/probes.md +122 -0
- package/plugins/codex/skills/funpixel-game-logic/references/unity.md +108 -0
- package/plugins/codex/skills/funpixel-game-spine/SKILL.md +118 -0
- package/plugins/codex/skills/funpixel-game-spine/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-game-spine/references/camera.md +94 -0
- package/plugins/codex/skills/funpixel-game-spine/references/multiplayer.md +101 -0
- package/plugins/codex/skills/funpixel-game-spine/references/patterns.md +103 -0
- package/plugins/codex/skills/funpixel-game-spine/references/performance.md +96 -0
- package/plugins/codex/skills/funpixel-game-spine/references/pixi.md +26 -0
- package/plugins/codex/skills/funpixel-game-spine/references/replay.md +102 -0
- package/plugins/codex/skills/funpixel-game-spine/references/room-api.md +63 -0
- package/plugins/codex/skills/funpixel-game-spine/references/room-modes.md +40 -0
- package/plugins/codex/skills/funpixel-game-spine/references/sdk.md +114 -0
- package/plugins/codex/skills/funpixel-game-spine/references/three.md +62 -0
- package/plugins/codex/skills/funpixel-gdd/SKILL.md +116 -0
- package/plugins/codex/skills/funpixel-gdd/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-gdd/references/as-built.md +40 -0
- package/plugins/codex/skills/funpixel-gdd/references/design-measures.md +24 -0
- package/plugins/codex/skills/funpixel-gdd/references/design-note.md +88 -0
- package/plugins/codex/skills/funpixel-gdd/references/experience.md +92 -0
- package/plugins/codex/skills/funpixel-gdd/references/first-look.md +226 -0
- package/plugins/codex/skills/funpixel-gdd/references/floors.md +62 -0
- package/plugins/codex/skills/funpixel-gdd/references/frame.md +75 -0
- package/plugins/codex/skills/funpixel-gdd/references/gameplay-contract.md +81 -0
- package/plugins/codex/skills/funpixel-gdd/references/gdd-template.md +417 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-card.md +109 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-platformer.md +159 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-puzzle.md +145 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-racing.md +137 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-rpg.md +125 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-shooter.md +128 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-simulation.md +112 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-strategy.md +116 -0
- package/plugins/codex/skills/funpixel-gdd/references/genre-survival.md +122 -0
- package/plugins/codex/skills/funpixel-gdd/references/in-the-loop.md +106 -0
- package/plugins/codex/skills/funpixel-gdd/references/invent-first.md +131 -0
- package/plugins/codex/skills/funpixel-gdd/references/level-and-fun.md +112 -0
- package/plugins/codex/skills/funpixel-gdd/references/pages.md +47 -0
- package/plugins/codex/skills/funpixel-gdd/references/plan-at-size.md +140 -0
- package/plugins/codex/skills/funpixel-gdd/references/production-tiers.md +117 -0
- package/plugins/codex/skills/funpixel-gdd/references/sections.md +148 -0
- package/plugins/codex/skills/funpixel-gdd/references/spec-folder.md +131 -0
- package/plugins/codex/skills/funpixel-gdd/references/start.md +110 -0
- package/plugins/codex/skills/funpixel-gdd/references/starters.md +175 -0
- package/plugins/codex/skills/funpixel-gdd/references/the-path.md +133 -0
- package/plugins/codex/skills/funpixel-gdd/references/track.md +29 -0
- package/plugins/codex/skills/funpixel-gdd/references/world-and-identity.md +165 -0
- package/plugins/codex/skills/funpixel-gdd/references/worth.md +74 -0
- package/plugins/codex/skills/funpixel-mobile-ui/SKILL.md +107 -0
- package/plugins/codex/skills/funpixel-mobile-ui/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-mobile-ui/references/contrast.md +123 -0
- package/plugins/codex/skills/funpixel-mobile-ui/references/hud-and-title.md +108 -0
- package/plugins/codex/skills/funpixel-mobile-ui/references/hud-genres.md +124 -0
- package/plugins/codex/skills/funpixel-mobile-ui/references/phone-check.md +156 -0
- package/plugins/codex/skills/funpixel-mobile-ui/references/recipes.md +279 -0
- package/plugins/codex/skills/funpixel-mobile-ui/references/restyle-ui.md +229 -0
- package/plugins/codex/skills/funpixel-mobile-ui/references/unity.md +61 -0
- package/plugins/codex/skills/funpixel-publish/SKILL.md +109 -0
- package/plugins/codex/skills/funpixel-publish/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-publish/references/compose.md +113 -0
- package/plugins/codex/skills/funpixel-publish/references/motion.md +120 -0
- package/plugins/codex/skills/funpixel-publish/references/networks.md +75 -0
- package/plugins/codex/skills/funpixel-publish/references/other-hosts.md +65 -0
- package/plugins/codex/skills/funpixel-publish/references/playable-ad.md +90 -0
- package/plugins/codex/skills/funpixel-publish/references/server-build.md +85 -0
- package/plugins/codex/skills/funpixel-publish/references/store-shots.md +85 -0
- package/plugins/codex/skills/funpixel-publish/references/trailer.md +55 -0
- package/plugins/codex/skills/funpixel-publish/references/what-ships.md +30 -0
- package/plugins/codex/skills/funpixel-store/SKILL.md +81 -0
- package/plugins/codex/skills/funpixel-store/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-store/references/app-store.md +73 -0
- package/plugins/codex/skills/funpixel-store/references/google-play.md +141 -0
- package/plugins/codex/skills/funpixel-store/references/ios-release.md +63 -0
- package/plugins/codex/skills/funpixel-store/references/money.md +66 -0
- package/plugins/codex/skills/funpixel-store/references/purchases-and-review.md +74 -0
- package/plugins/codex/skills/funpixel-store/references/readiness-page.md +24 -0
- package/plugins/codex/skills/funpixel-store/references/readiness.md +107 -0
- package/plugins/codex/skills/funpixel-store/references/steam.md +38 -0
- package/plugins/codex/skills/funpixel-store/references/unity-store.md +55 -0
- package/plugins/codex/skills/funpixel-store/references/web-portals.md +43 -0
- package/plugins/codex/skills/funpixel-unity-game/SKILL.md +103 -0
- package/plugins/codex/skills/funpixel-unity-game/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-unity-game/references/agent-ops.md +54 -0
- package/plugins/codex/skills/funpixel-unity-game/references/fixes.md +40 -0
- package/plugins/codex/skills/funpixel-unity-game/references/from-a-web-game.md +108 -0
- package/plugins/codex/skills/funpixel-unity-game/references/handing-off.md +42 -0
- package/plugins/codex/skills/funpixel-unity-game/references/performance.md +59 -0
- package/plugins/codex/skills/funpixel-unity-game/references/probe.md +80 -0
- package/plugins/codex/skills/funpixel-unity-game/references/shared-mac.md +121 -0
- package/plugins/codex/skills/funpixel-unity-game/references/traps.md +108 -0
- package/plugins/codex/skills/funpixel-verify/SKILL.md +109 -0
- package/plugins/codex/skills/funpixel-verify/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-verify/references/actors.md +94 -0
- package/plugins/codex/skills/funpixel-verify/references/bar.md +62 -0
- package/plugins/codex/skills/funpixel-verify/references/checks.md +69 -0
- package/plugins/codex/skills/funpixel-verify/references/experience.md +67 -0
- package/plugins/codex/skills/funpixel-verify/references/eyes.md +54 -0
- package/plugins/codex/skills/funpixel-verify/references/fidelity.md +126 -0
- package/plugins/codex/skills/funpixel-verify/references/hit-bar.md +31 -0
- package/plugins/codex/skills/funpixel-verify/references/journeys.md +77 -0
- package/plugins/codex/skills/funpixel-verify/references/mobile-qa.md +123 -0
- package/plugins/codex/skills/funpixel-verify/references/playtest.md +161 -0
- package/plugins/codex/skills/funpixel-verify/references/review.md +105 -0
- package/plugins/codex/skills/funpixel-verify/references/rubric.md +67 -0
- package/plugins/codex/skills/funpixel-verify/references/scenes.md +49 -0
- package/plugins/codex/skills/funpixel-verify/references/unity.md +60 -0
- package/plugins/codex/skills/funpixel-world-and-story/SKILL.md +99 -0
- package/plugins/codex/skills/funpixel-world-and-story/agents/openai.yaml +12 -0
- package/plugins/codex/skills/funpixel-world-and-story/references/atmosphere.md +208 -0
- package/plugins/codex/skills/funpixel-world-and-story/references/forged-world.md +79 -0
- package/plugins/codex/skills/funpixel-world-and-story/references/living-world.md +237 -0
- package/plugins/codex/skills/funpixel-world-and-story/references/opening-and-chapters.md +215 -0
- package/plugins/codex/skills/funpixel-world-and-story/references/shelf.md +80 -0
- package/plugins/codex/skills/funpixel-world-and-story/references/story-at-size.md +159 -0
- package/plugins/codex/skills/funpixel-world-and-story/references/voice.md +175 -0
- package/plugins/codex/skills/funpixel-world-and-story/references/world-kit.md +154 -0
- package/plugins/cursor/.cursor-plugin/plugin.json +26 -0
- package/plugins/cursor/LICENSE +115 -0
- package/plugins/cursor/README.md +13 -0
- package/plugins/cursor/THIRD_PARTY_NOTICES.md +75 -0
- package/plugins/cursor/agents/art-director.md +54 -0
- package/plugins/cursor/agents/audio-director.md +51 -0
- package/plugins/cursor/agents/critic.md +113 -0
- package/plugins/cursor/agents/lane.md +37 -0
- package/plugins/cursor/agents/level-designer.md +45 -0
- package/plugins/cursor/agents/mobile-qa.md +70 -0
- package/plugins/cursor/agents/player.md +143 -0
- package/plugins/cursor/agents/qa-lead.md +52 -0
- package/plugins/cursor/commands/first-look.md +59 -0
- package/plugins/cursor/commands/flow.md +50 -0
- package/plugins/cursor/commands/lanes.md +38 -0
- package/plugins/cursor/commands/mobile-qa.md +28 -0
- package/plugins/cursor/commands/new.md +94 -0
- package/plugins/cursor/commands/playtest.md +66 -0
- package/plugins/cursor/commands/publish.md +23 -0
- package/plugins/cursor/commands/smoke-build.md +25 -0
- package/plugins/cursor/commands/verify.md +20 -0
- package/plugins/cursor/hooks/brief.md +135 -0
- package/plugins/cursor/hooks/critic-receipts.mjs +86 -0
- package/plugins/cursor/hooks/durable.mjs +56 -0
- package/plugins/cursor/hooks/fence.mjs +30 -0
- package/plugins/cursor/hooks/floors.mjs +181 -0
- package/plugins/cursor/hooks/flow.mjs +154 -0
- package/plugins/cursor/hooks/front-door.mjs +68 -0
- package/plugins/cursor/hooks/guidance.json +3 -0
- package/plugins/cursor/hooks/hints.mjs +183 -0
- package/plugins/cursor/hooks/hooks.json +26 -0
- package/plugins/cursor/hooks/lib.mjs +362 -0
- package/plugins/cursor/hooks/memory.mjs +92 -0
- package/plugins/cursor/hooks/mobile-qa.mjs +43 -0
- package/plugins/cursor/hooks/note.mjs +63 -0
- package/plugins/cursor/hooks/nudge.mjs +98 -0
- package/plugins/cursor/hooks/pipeline.mjs +207 -0
- package/plugins/cursor/hooks/prompt.mjs +51 -0
- package/plugins/cursor/hooks/quality.mjs +310 -0
- package/plugins/cursor/hooks/reach.mjs +93 -0
- package/plugins/cursor/hooks/scope.mjs +44 -0
- package/plugins/cursor/hooks/session-log.mjs +101 -0
- package/plugins/cursor/hooks/session-start.mjs +194 -0
- package/plugins/cursor/hooks/stop-gate.mjs +303 -0
- package/plugins/cursor/hooks/vendor/direct/round.mjs +81 -0
- package/plugins/cursor/hooks/vendor/find/names.mjs +46 -0
- package/plugins/cursor/hooks/vendor/firstlook/set.mjs +219 -0
- package/plugins/cursor/hooks/vendor/flow/flow.mjs +456 -0
- package/plugins/cursor/hooks/vendor/flow/look.mjs +140 -0
- package/plugins/cursor/hooks/vendor/gdd/book.mjs +484 -0
- package/plugins/cursor/hooks/vendor/gdd/chapters.mjs +72 -0
- package/plugins/cursor/hooks/vendor/gdd/doc.mjs +33 -0
- package/plugins/cursor/hooks/vendor/gdd/levelmap.mjs +429 -0
- package/plugins/cursor/hooks/vendor/gdd/rubric.mjs +251 -0
- package/plugins/cursor/hooks/vendor/gdd/worth.mjs +508 -0
- package/plugins/cursor/hooks/vendor/lanes/fence.mjs +109 -0
- package/plugins/cursor/hooks/vendor/lanes/lanes.mjs +356 -0
- package/plugins/cursor/hooks/vendor/lanes/union.mjs +63 -0
- package/plugins/cursor/hooks/vendor/lessons/motifs.mjs +98 -0
- package/plugins/cursor/hooks/vendor/lessons/store.mjs +57 -0
- package/plugins/cursor/hooks/vendor/look/made-of.mjs +243 -0
- package/plugins/cursor/hooks/vendor/look/roles.mjs +110 -0
- package/plugins/cursor/hooks/vendor/memory/decisions.mjs +139 -0
- package/plugins/cursor/hooks/vendor/memory/journal.mjs +109 -0
- package/plugins/cursor/hooks/vendor/owner/bar.mjs +286 -0
- package/plugins/cursor/hooks/vendor/pipeline/pipeline.mjs +930 -0
- package/plugins/cursor/hooks/vendor/playtest/keep.mjs +111 -0
- package/plugins/cursor/hooks/vendor/playtest/stuck.mjs +48 -0
- package/plugins/cursor/hooks/vendor/progress/holds.mjs +107 -0
- package/plugins/cursor/hooks/vendor/progress/progress.mjs +301 -0
- package/plugins/cursor/hooks/vendor/sim/judge.mjs +241 -0
- package/plugins/cursor/hooks/vendor/spec/rooms.mjs +189 -0
- package/plugins/cursor/hooks/vendor/spec/tunables.mjs +75 -0
- package/plugins/cursor/hooks/vendor/stage/harnessignore.mjs +91 -0
- package/plugins/cursor/hooks/vendor/stage/stage.mjs +58 -0
- package/plugins/cursor/hooks/vendor/status/board.mjs +173 -0
- package/plugins/cursor/hooks/vendor/status/file.mjs +113 -0
- package/plugins/cursor/hooks/vendor/studio/forks.mjs +94 -0
- package/plugins/cursor/hooks/vendor/studio/pitch.mjs +295 -0
- package/plugins/cursor/hooks/vendor/verify/fingerprint.mjs +73 -0
- package/plugins/cursor/hooks/vendor/verify/reads.mjs +33 -0
- package/plugins/cursor/hooks/vendor/wow/picks.mjs +75 -0
- package/plugins/cursor/mcp.json +10 -0
- package/plugins/cursor/rules/funpixel-brief.mdc +141 -0
- package/plugins/cursor/skills/funpixel-3d/SKILL.md +89 -0
- package/plugins/cursor/skills/funpixel-3d/references/bake-off.md +48 -0
- package/plugins/cursor/skills/funpixel-3d/references/bench.md +103 -0
- package/plugins/cursor/skills/funpixel-3d/references/budgets.md +48 -0
- package/plugins/cursor/skills/funpixel-3d/references/characters.md +67 -0
- package/plugins/cursor/skills/funpixel-3d/references/concept-image.md +47 -0
- package/plugins/cursor/skills/funpixel-3d/references/engine-targets.md +31 -0
- package/plugins/cursor/skills/funpixel-3d/references/hero-route.md +104 -0
- package/plugins/cursor/skills/funpixel-3d/references/level-spec.md +109 -0
- package/plugins/cursor/skills/funpixel-3d/references/levels.md +84 -0
- package/plugins/cursor/skills/funpixel-3d/references/light-and-places.md +141 -0
- package/plugins/cursor/skills/funpixel-3d/references/models.md +111 -0
- package/plugins/cursor/skills/funpixel-3d/references/painted-target.md +184 -0
- package/plugins/cursor/skills/funpixel-3d/references/reading.md +41 -0
- package/plugins/cursor/skills/funpixel-3d/references/skin.md +85 -0
- package/plugins/cursor/skills/funpixel-3d/references/skyboxes.md +65 -0
- package/plugins/cursor/skills/funpixel-3d/references/textures.md +71 -0
- package/plugins/cursor/skills/funpixel-3d/references/three-loading.md +199 -0
- package/plugins/cursor/skills/funpixel-3d/references/unity.md +78 -0
- package/plugins/cursor/skills/funpixel-art/SKILL.md +104 -0
- package/plugins/cursor/skills/funpixel-art/references/2d-assets.md +108 -0
- package/plugins/cursor/skills/funpixel-art/references/animation.md +126 -0
- package/plugins/cursor/skills/funpixel-art/references/cast.md +73 -0
- package/plugins/cursor/skills/funpixel-art/references/characters.md +49 -0
- package/plugins/cursor/skills/funpixel-art/references/cost.md +107 -0
- package/plugins/cursor/skills/funpixel-art/references/effects.md +85 -0
- package/plugins/cursor/skills/funpixel-art/references/frames.md +87 -0
- package/plugins/cursor/skills/funpixel-art/references/judging-frames.md +64 -0
- package/plugins/cursor/skills/funpixel-art/references/look.md +102 -0
- package/plugins/cursor/skills/funpixel-art/references/measure.md +119 -0
- package/plugins/cursor/skills/funpixel-art/references/pipeline.md +185 -0
- package/plugins/cursor/skills/funpixel-art/references/pixi.md +277 -0
- package/plugins/cursor/skills/funpixel-art/references/planes.md +27 -0
- package/plugins/cursor/skills/funpixel-art/references/prompts.md +171 -0
- package/plugins/cursor/skills/funpixel-art/references/sheets.md +141 -0
- package/plugins/cursor/skills/funpixel-art/references/style-file.md +39 -0
- package/plugins/cursor/skills/funpixel-art/references/three.md +232 -0
- package/plugins/cursor/skills/funpixel-art/references/ui.md +163 -0
- package/plugins/cursor/skills/funpixel-art/references/unity.md +78 -0
- package/plugins/cursor/skills/funpixel-art/references/wiring.md +41 -0
- package/plugins/cursor/skills/funpixel-audio/SKILL.md +92 -0
- package/plugins/cursor/skills/funpixel-audio/references/adaptive-music.md +204 -0
- package/plugins/cursor/skills/funpixel-audio/references/engine.md +78 -0
- package/plugins/cursor/skills/funpixel-audio/references/measure.md +101 -0
- package/plugins/cursor/skills/funpixel-audio/references/unity.md +74 -0
- package/plugins/cursor/skills/funpixel-feedback/SKILL.md +120 -0
- package/plugins/cursor/skills/funpixel-feedback/references/memory.md +99 -0
- package/plugins/cursor/skills/funpixel-game-feel/SKILL.md +104 -0
- package/plugins/cursor/skills/funpixel-game-feel/references/contact.md +110 -0
- package/plugins/cursor/skills/funpixel-game-feel/references/measure.md +125 -0
- package/plugins/cursor/skills/funpixel-game-feel/references/motion.md +134 -0
- package/plugins/cursor/skills/funpixel-game-feel/references/payoffs.md +35 -0
- package/plugins/cursor/skills/funpixel-game-feel/references/recipes.md +107 -0
- package/plugins/cursor/skills/funpixel-game-feel/references/unity.md +73 -0
- package/plugins/cursor/skills/funpixel-game-logic/SKILL.md +113 -0
- package/plugins/cursor/skills/funpixel-game-logic/references/balance.md +88 -0
- package/plugins/cursor/skills/funpixel-game-logic/references/content-at-scale.md +147 -0
- package/plugins/cursor/skills/funpixel-game-logic/references/depth.md +89 -0
- package/plugins/cursor/skills/funpixel-game-logic/references/escalation.md +41 -0
- package/plugins/cursor/skills/funpixel-game-logic/references/levels.md +61 -0
- package/plugins/cursor/skills/funpixel-game-logic/references/probes.md +122 -0
- package/plugins/cursor/skills/funpixel-game-logic/references/unity.md +108 -0
- package/plugins/cursor/skills/funpixel-game-spine/SKILL.md +118 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/camera.md +94 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/multiplayer.md +101 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/patterns.md +103 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/performance.md +96 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/pixi.md +26 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/replay.md +102 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/room-api.md +63 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/room-modes.md +40 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/sdk.md +114 -0
- package/plugins/cursor/skills/funpixel-game-spine/references/three.md +62 -0
- package/plugins/cursor/skills/funpixel-gdd/SKILL.md +116 -0
- package/plugins/cursor/skills/funpixel-gdd/references/as-built.md +40 -0
- package/plugins/cursor/skills/funpixel-gdd/references/design-measures.md +24 -0
- package/plugins/cursor/skills/funpixel-gdd/references/design-note.md +88 -0
- package/plugins/cursor/skills/funpixel-gdd/references/experience.md +92 -0
- package/plugins/cursor/skills/funpixel-gdd/references/first-look.md +226 -0
- package/plugins/cursor/skills/funpixel-gdd/references/floors.md +62 -0
- package/plugins/cursor/skills/funpixel-gdd/references/frame.md +75 -0
- package/plugins/cursor/skills/funpixel-gdd/references/gameplay-contract.md +81 -0
- package/plugins/cursor/skills/funpixel-gdd/references/gdd-template.md +417 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-card.md +109 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-platformer.md +159 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-puzzle.md +145 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-racing.md +137 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-rpg.md +125 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-shooter.md +128 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-simulation.md +112 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-strategy.md +116 -0
- package/plugins/cursor/skills/funpixel-gdd/references/genre-survival.md +122 -0
- package/plugins/cursor/skills/funpixel-gdd/references/in-the-loop.md +106 -0
- package/plugins/cursor/skills/funpixel-gdd/references/invent-first.md +131 -0
- package/plugins/cursor/skills/funpixel-gdd/references/level-and-fun.md +112 -0
- package/plugins/cursor/skills/funpixel-gdd/references/pages.md +47 -0
- package/plugins/cursor/skills/funpixel-gdd/references/plan-at-size.md +140 -0
- package/plugins/cursor/skills/funpixel-gdd/references/production-tiers.md +117 -0
- package/plugins/cursor/skills/funpixel-gdd/references/sections.md +148 -0
- package/plugins/cursor/skills/funpixel-gdd/references/spec-folder.md +131 -0
- package/plugins/cursor/skills/funpixel-gdd/references/start.md +110 -0
- package/plugins/cursor/skills/funpixel-gdd/references/starters.md +175 -0
- package/plugins/cursor/skills/funpixel-gdd/references/the-path.md +133 -0
- package/plugins/cursor/skills/funpixel-gdd/references/track.md +29 -0
- package/plugins/cursor/skills/funpixel-gdd/references/world-and-identity.md +165 -0
- package/plugins/cursor/skills/funpixel-gdd/references/worth.md +74 -0
- package/plugins/cursor/skills/funpixel-mobile-ui/SKILL.md +107 -0
- package/plugins/cursor/skills/funpixel-mobile-ui/references/contrast.md +123 -0
- package/plugins/cursor/skills/funpixel-mobile-ui/references/hud-and-title.md +108 -0
- package/plugins/cursor/skills/funpixel-mobile-ui/references/hud-genres.md +124 -0
- package/plugins/cursor/skills/funpixel-mobile-ui/references/phone-check.md +156 -0
- package/plugins/cursor/skills/funpixel-mobile-ui/references/recipes.md +279 -0
- package/plugins/cursor/skills/funpixel-mobile-ui/references/restyle-ui.md +229 -0
- package/plugins/cursor/skills/funpixel-mobile-ui/references/unity.md +61 -0
- package/plugins/cursor/skills/funpixel-publish/SKILL.md +109 -0
- package/plugins/cursor/skills/funpixel-publish/references/compose.md +113 -0
- package/plugins/cursor/skills/funpixel-publish/references/motion.md +120 -0
- package/plugins/cursor/skills/funpixel-publish/references/networks.md +75 -0
- package/plugins/cursor/skills/funpixel-publish/references/other-hosts.md +65 -0
- package/plugins/cursor/skills/funpixel-publish/references/playable-ad.md +90 -0
- package/plugins/cursor/skills/funpixel-publish/references/server-build.md +85 -0
- package/plugins/cursor/skills/funpixel-publish/references/store-shots.md +85 -0
- package/plugins/cursor/skills/funpixel-publish/references/trailer.md +55 -0
- package/plugins/cursor/skills/funpixel-publish/references/what-ships.md +30 -0
- package/plugins/cursor/skills/funpixel-store/SKILL.md +81 -0
- package/plugins/cursor/skills/funpixel-store/references/app-store.md +73 -0
- package/plugins/cursor/skills/funpixel-store/references/google-play.md +141 -0
- package/plugins/cursor/skills/funpixel-store/references/ios-release.md +63 -0
- package/plugins/cursor/skills/funpixel-store/references/money.md +66 -0
- package/plugins/cursor/skills/funpixel-store/references/purchases-and-review.md +74 -0
- package/plugins/cursor/skills/funpixel-store/references/readiness-page.md +24 -0
- package/plugins/cursor/skills/funpixel-store/references/readiness.md +107 -0
- package/plugins/cursor/skills/funpixel-store/references/steam.md +38 -0
- package/plugins/cursor/skills/funpixel-store/references/unity-store.md +55 -0
- package/plugins/cursor/skills/funpixel-store/references/web-portals.md +43 -0
- package/plugins/cursor/skills/funpixel-unity-game/SKILL.md +103 -0
- package/plugins/cursor/skills/funpixel-unity-game/references/agent-ops.md +54 -0
- package/plugins/cursor/skills/funpixel-unity-game/references/fixes.md +40 -0
- package/plugins/cursor/skills/funpixel-unity-game/references/from-a-web-game.md +108 -0
- package/plugins/cursor/skills/funpixel-unity-game/references/handing-off.md +42 -0
- package/plugins/cursor/skills/funpixel-unity-game/references/performance.md +59 -0
- package/plugins/cursor/skills/funpixel-unity-game/references/probe.md +80 -0
- package/plugins/cursor/skills/funpixel-unity-game/references/shared-mac.md +121 -0
- package/plugins/cursor/skills/funpixel-unity-game/references/traps.md +108 -0
- package/plugins/cursor/skills/funpixel-verify/SKILL.md +109 -0
- package/plugins/cursor/skills/funpixel-verify/references/actors.md +94 -0
- package/plugins/cursor/skills/funpixel-verify/references/bar.md +62 -0
- package/plugins/cursor/skills/funpixel-verify/references/checks.md +69 -0
- package/plugins/cursor/skills/funpixel-verify/references/experience.md +67 -0
- package/plugins/cursor/skills/funpixel-verify/references/eyes.md +54 -0
- package/plugins/cursor/skills/funpixel-verify/references/fidelity.md +126 -0
- package/plugins/cursor/skills/funpixel-verify/references/hit-bar.md +31 -0
- package/plugins/cursor/skills/funpixel-verify/references/journeys.md +77 -0
- package/plugins/cursor/skills/funpixel-verify/references/mobile-qa.md +123 -0
- package/plugins/cursor/skills/funpixel-verify/references/playtest.md +161 -0
- package/plugins/cursor/skills/funpixel-verify/references/review.md +105 -0
- package/plugins/cursor/skills/funpixel-verify/references/rubric.md +67 -0
- package/plugins/cursor/skills/funpixel-verify/references/scenes.md +49 -0
- package/plugins/cursor/skills/funpixel-verify/references/unity.md +60 -0
- package/plugins/cursor/skills/funpixel-world-and-story/SKILL.md +99 -0
- package/plugins/cursor/skills/funpixel-world-and-story/references/atmosphere.md +208 -0
- package/plugins/cursor/skills/funpixel-world-and-story/references/forged-world.md +79 -0
- package/plugins/cursor/skills/funpixel-world-and-story/references/living-world.md +237 -0
- package/plugins/cursor/skills/funpixel-world-and-story/references/opening-and-chapters.md +215 -0
- package/plugins/cursor/skills/funpixel-world-and-story/references/shelf.md +80 -0
- package/plugins/cursor/skills/funpixel-world-and-story/references/story-at-size.md +159 -0
- package/plugins/cursor/skills/funpixel-world-and-story/references/voice.md +175 -0
- package/plugins/cursor/skills/funpixel-world-and-story/references/world-kit.md +154 -0
- package/plugins/kiro/AGENTS.md +135 -0
- package/plugins/kiro/LICENSE +115 -0
- package/plugins/kiro/README.md +17 -0
- package/plugins/kiro/THIRD_PARTY_NOTICES.md +75 -0
- package/plugins/kiro/agent.template.json +45 -0
- package/plugins/kiro/hooks/brief.md +135 -0
- package/plugins/kiro/hooks/critic-receipts.mjs +86 -0
- package/plugins/kiro/hooks/durable.mjs +56 -0
- package/plugins/kiro/hooks/fence.mjs +30 -0
- package/plugins/kiro/hooks/floors.mjs +181 -0
- package/plugins/kiro/hooks/flow.mjs +154 -0
- package/plugins/kiro/hooks/front-door.mjs +68 -0
- package/plugins/kiro/hooks/guidance.json +3 -0
- package/plugins/kiro/hooks/hints.mjs +183 -0
- package/plugins/kiro/hooks/host.md +43 -0
- package/plugins/kiro/hooks/kiro-prompt.mjs +26 -0
- package/plugins/kiro/hooks/lib.mjs +362 -0
- package/plugins/kiro/hooks/memory.mjs +92 -0
- package/plugins/kiro/hooks/mobile-qa.mjs +43 -0
- package/plugins/kiro/hooks/note.mjs +63 -0
- package/plugins/kiro/hooks/nudge.mjs +98 -0
- package/plugins/kiro/hooks/pipeline.mjs +207 -0
- package/plugins/kiro/hooks/prompt.mjs +51 -0
- package/plugins/kiro/hooks/quality.mjs +310 -0
- package/plugins/kiro/hooks/reach.mjs +93 -0
- package/plugins/kiro/hooks/scope.mjs +44 -0
- package/plugins/kiro/hooks/session-log.mjs +101 -0
- package/plugins/kiro/hooks/session-start.mjs +194 -0
- package/plugins/kiro/hooks/stop-gate.mjs +303 -0
- package/plugins/kiro/hooks/vendor/direct/round.mjs +81 -0
- package/plugins/kiro/hooks/vendor/find/names.mjs +46 -0
- package/plugins/kiro/hooks/vendor/firstlook/set.mjs +219 -0
- package/plugins/kiro/hooks/vendor/flow/flow.mjs +456 -0
- package/plugins/kiro/hooks/vendor/flow/look.mjs +140 -0
- package/plugins/kiro/hooks/vendor/gdd/book.mjs +484 -0
- package/plugins/kiro/hooks/vendor/gdd/chapters.mjs +72 -0
- package/plugins/kiro/hooks/vendor/gdd/doc.mjs +33 -0
- package/plugins/kiro/hooks/vendor/gdd/levelmap.mjs +429 -0
- package/plugins/kiro/hooks/vendor/gdd/rubric.mjs +251 -0
- package/plugins/kiro/hooks/vendor/gdd/worth.mjs +508 -0
- package/plugins/kiro/hooks/vendor/lanes/fence.mjs +109 -0
- package/plugins/kiro/hooks/vendor/lanes/lanes.mjs +356 -0
- package/plugins/kiro/hooks/vendor/lanes/union.mjs +63 -0
- package/plugins/kiro/hooks/vendor/lessons/motifs.mjs +98 -0
- package/plugins/kiro/hooks/vendor/lessons/store.mjs +57 -0
- package/plugins/kiro/hooks/vendor/look/made-of.mjs +243 -0
- package/plugins/kiro/hooks/vendor/look/roles.mjs +110 -0
- package/plugins/kiro/hooks/vendor/memory/decisions.mjs +139 -0
- package/plugins/kiro/hooks/vendor/memory/journal.mjs +109 -0
- package/plugins/kiro/hooks/vendor/owner/bar.mjs +286 -0
- package/plugins/kiro/hooks/vendor/pipeline/pipeline.mjs +930 -0
- package/plugins/kiro/hooks/vendor/playtest/keep.mjs +111 -0
- package/plugins/kiro/hooks/vendor/playtest/stuck.mjs +48 -0
- package/plugins/kiro/hooks/vendor/progress/holds.mjs +107 -0
- package/plugins/kiro/hooks/vendor/progress/progress.mjs +301 -0
- package/plugins/kiro/hooks/vendor/sim/judge.mjs +241 -0
- package/plugins/kiro/hooks/vendor/spec/rooms.mjs +189 -0
- package/plugins/kiro/hooks/vendor/spec/tunables.mjs +75 -0
- package/plugins/kiro/hooks/vendor/stage/harnessignore.mjs +91 -0
- package/plugins/kiro/hooks/vendor/stage/stage.mjs +58 -0
- package/plugins/kiro/hooks/vendor/status/board.mjs +173 -0
- package/plugins/kiro/hooks/vendor/status/file.mjs +113 -0
- package/plugins/kiro/hooks/vendor/studio/forks.mjs +94 -0
- package/plugins/kiro/hooks/vendor/studio/pitch.mjs +295 -0
- package/plugins/kiro/hooks/vendor/verify/fingerprint.mjs +73 -0
- package/plugins/kiro/hooks/vendor/verify/reads.mjs +33 -0
- package/plugins/kiro/hooks/vendor/wow/picks.mjs +75 -0
- package/plugins/kiro/install.mjs +37 -0
- package/plugins/kiro/skills/fp-art-director/SKILL.md +58 -0
- package/plugins/kiro/skills/fp-art-director/references/kiro.md +43 -0
- package/plugins/kiro/skills/fp-audio-director/SKILL.md +55 -0
- package/plugins/kiro/skills/fp-audio-director/references/kiro.md +43 -0
- package/plugins/kiro/skills/fp-critic/SKILL.md +117 -0
- package/plugins/kiro/skills/fp-critic/references/kiro.md +43 -0
- package/plugins/kiro/skills/fp-first-look/SKILL.md +61 -0
- package/plugins/kiro/skills/fp-flow/SKILL.md +52 -0
- package/plugins/kiro/skills/fp-lane/SKILL.md +41 -0
- package/plugins/kiro/skills/fp-lane/references/kiro.md +43 -0
- package/plugins/kiro/skills/fp-lanes/SKILL.md +40 -0
- package/plugins/kiro/skills/fp-level-designer/SKILL.md +49 -0
- package/plugins/kiro/skills/fp-level-designer/references/kiro.md +43 -0
- package/plugins/kiro/skills/fp-mobile-qa/SKILL.md +30 -0
- package/plugins/kiro/skills/fp-mobile-qa-seat/SKILL.md +74 -0
- package/plugins/kiro/skills/fp-mobile-qa-seat/references/kiro.md +43 -0
- package/plugins/kiro/skills/fp-new/SKILL.md +96 -0
- package/plugins/kiro/skills/fp-player/SKILL.md +147 -0
- package/plugins/kiro/skills/fp-player/references/kiro.md +43 -0
- package/plugins/kiro/skills/fp-playtest/SKILL.md +68 -0
- package/plugins/kiro/skills/fp-publish/SKILL.md +25 -0
- package/plugins/kiro/skills/fp-qa-lead/SKILL.md +56 -0
- package/plugins/kiro/skills/fp-qa-lead/references/kiro.md +43 -0
- package/plugins/kiro/skills/fp-smoke-build/SKILL.md +27 -0
- package/plugins/kiro/skills/fp-studio/SKILL.md +48 -0
- package/plugins/kiro/skills/fp-verify/SKILL.md +22 -0
- package/plugins/kiro/skills/funpixel-3d/SKILL.md +89 -0
- package/plugins/kiro/skills/funpixel-3d/references/bake-off.md +48 -0
- package/plugins/kiro/skills/funpixel-3d/references/bench.md +103 -0
- package/plugins/kiro/skills/funpixel-3d/references/budgets.md +48 -0
- package/plugins/kiro/skills/funpixel-3d/references/characters.md +67 -0
- package/plugins/kiro/skills/funpixel-3d/references/concept-image.md +47 -0
- package/plugins/kiro/skills/funpixel-3d/references/engine-targets.md +31 -0
- package/plugins/kiro/skills/funpixel-3d/references/hero-route.md +104 -0
- package/plugins/kiro/skills/funpixel-3d/references/level-spec.md +109 -0
- package/plugins/kiro/skills/funpixel-3d/references/levels.md +84 -0
- package/plugins/kiro/skills/funpixel-3d/references/light-and-places.md +141 -0
- package/plugins/kiro/skills/funpixel-3d/references/models.md +111 -0
- package/plugins/kiro/skills/funpixel-3d/references/painted-target.md +184 -0
- package/plugins/kiro/skills/funpixel-3d/references/reading.md +41 -0
- package/plugins/kiro/skills/funpixel-3d/references/skin.md +85 -0
- package/plugins/kiro/skills/funpixel-3d/references/skyboxes.md +65 -0
- package/plugins/kiro/skills/funpixel-3d/references/textures.md +71 -0
- package/plugins/kiro/skills/funpixel-3d/references/three-loading.md +199 -0
- package/plugins/kiro/skills/funpixel-3d/references/unity.md +78 -0
- package/plugins/kiro/skills/funpixel-art/SKILL.md +104 -0
- package/plugins/kiro/skills/funpixel-art/references/2d-assets.md +108 -0
- package/plugins/kiro/skills/funpixel-art/references/animation.md +126 -0
- package/plugins/kiro/skills/funpixel-art/references/cast.md +73 -0
- package/plugins/kiro/skills/funpixel-art/references/characters.md +49 -0
- package/plugins/kiro/skills/funpixel-art/references/cost.md +107 -0
- package/plugins/kiro/skills/funpixel-art/references/effects.md +85 -0
- package/plugins/kiro/skills/funpixel-art/references/frames.md +87 -0
- package/plugins/kiro/skills/funpixel-art/references/judging-frames.md +64 -0
- package/plugins/kiro/skills/funpixel-art/references/look.md +102 -0
- package/plugins/kiro/skills/funpixel-art/references/measure.md +119 -0
- package/plugins/kiro/skills/funpixel-art/references/pipeline.md +185 -0
- package/plugins/kiro/skills/funpixel-art/references/pixi.md +277 -0
- package/plugins/kiro/skills/funpixel-art/references/planes.md +27 -0
- package/plugins/kiro/skills/funpixel-art/references/prompts.md +171 -0
- package/plugins/kiro/skills/funpixel-art/references/sheets.md +141 -0
- package/plugins/kiro/skills/funpixel-art/references/style-file.md +39 -0
- package/plugins/kiro/skills/funpixel-art/references/three.md +232 -0
- package/plugins/kiro/skills/funpixel-art/references/ui.md +163 -0
- package/plugins/kiro/skills/funpixel-art/references/unity.md +78 -0
- package/plugins/kiro/skills/funpixel-art/references/wiring.md +41 -0
- package/plugins/kiro/skills/funpixel-audio/SKILL.md +92 -0
- package/plugins/kiro/skills/funpixel-audio/references/adaptive-music.md +204 -0
- package/plugins/kiro/skills/funpixel-audio/references/engine.md +78 -0
- package/plugins/kiro/skills/funpixel-audio/references/measure.md +101 -0
- package/plugins/kiro/skills/funpixel-audio/references/unity.md +74 -0
- package/plugins/kiro/skills/funpixel-feedback/SKILL.md +120 -0
- package/plugins/kiro/skills/funpixel-feedback/references/memory.md +99 -0
- package/plugins/kiro/skills/funpixel-game-feel/SKILL.md +104 -0
- package/plugins/kiro/skills/funpixel-game-feel/references/contact.md +110 -0
- package/plugins/kiro/skills/funpixel-game-feel/references/measure.md +125 -0
- package/plugins/kiro/skills/funpixel-game-feel/references/motion.md +134 -0
- package/plugins/kiro/skills/funpixel-game-feel/references/payoffs.md +35 -0
- package/plugins/kiro/skills/funpixel-game-feel/references/recipes.md +107 -0
- package/plugins/kiro/skills/funpixel-game-feel/references/unity.md +73 -0
- package/plugins/kiro/skills/funpixel-game-logic/SKILL.md +113 -0
- package/plugins/kiro/skills/funpixel-game-logic/references/balance.md +88 -0
- package/plugins/kiro/skills/funpixel-game-logic/references/content-at-scale.md +147 -0
- package/plugins/kiro/skills/funpixel-game-logic/references/depth.md +89 -0
- package/plugins/kiro/skills/funpixel-game-logic/references/escalation.md +41 -0
- package/plugins/kiro/skills/funpixel-game-logic/references/levels.md +61 -0
- package/plugins/kiro/skills/funpixel-game-logic/references/probes.md +122 -0
- package/plugins/kiro/skills/funpixel-game-logic/references/unity.md +108 -0
- package/plugins/kiro/skills/funpixel-game-spine/SKILL.md +118 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/camera.md +94 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/multiplayer.md +101 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/patterns.md +103 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/performance.md +96 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/pixi.md +26 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/replay.md +102 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/room-api.md +63 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/room-modes.md +40 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/sdk.md +114 -0
- package/plugins/kiro/skills/funpixel-game-spine/references/three.md +62 -0
- package/plugins/kiro/skills/funpixel-gdd/SKILL.md +116 -0
- package/plugins/kiro/skills/funpixel-gdd/references/as-built.md +40 -0
- package/plugins/kiro/skills/funpixel-gdd/references/design-measures.md +24 -0
- package/plugins/kiro/skills/funpixel-gdd/references/design-note.md +88 -0
- package/plugins/kiro/skills/funpixel-gdd/references/experience.md +92 -0
- package/plugins/kiro/skills/funpixel-gdd/references/first-look.md +226 -0
- package/plugins/kiro/skills/funpixel-gdd/references/floors.md +62 -0
- package/plugins/kiro/skills/funpixel-gdd/references/frame.md +75 -0
- package/plugins/kiro/skills/funpixel-gdd/references/gameplay-contract.md +81 -0
- package/plugins/kiro/skills/funpixel-gdd/references/gdd-template.md +417 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-card.md +109 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-platformer.md +159 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-puzzle.md +145 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-racing.md +137 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-rpg.md +125 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-shooter.md +128 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-simulation.md +112 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-strategy.md +116 -0
- package/plugins/kiro/skills/funpixel-gdd/references/genre-survival.md +122 -0
- package/plugins/kiro/skills/funpixel-gdd/references/in-the-loop.md +106 -0
- package/plugins/kiro/skills/funpixel-gdd/references/invent-first.md +131 -0
- package/plugins/kiro/skills/funpixel-gdd/references/level-and-fun.md +112 -0
- package/plugins/kiro/skills/funpixel-gdd/references/pages.md +47 -0
- package/plugins/kiro/skills/funpixel-gdd/references/plan-at-size.md +140 -0
- package/plugins/kiro/skills/funpixel-gdd/references/production-tiers.md +117 -0
- package/plugins/kiro/skills/funpixel-gdd/references/sections.md +148 -0
- package/plugins/kiro/skills/funpixel-gdd/references/spec-folder.md +131 -0
- package/plugins/kiro/skills/funpixel-gdd/references/start.md +110 -0
- package/plugins/kiro/skills/funpixel-gdd/references/starters.md +175 -0
- package/plugins/kiro/skills/funpixel-gdd/references/the-path.md +133 -0
- package/plugins/kiro/skills/funpixel-gdd/references/track.md +29 -0
- package/plugins/kiro/skills/funpixel-gdd/references/world-and-identity.md +165 -0
- package/plugins/kiro/skills/funpixel-gdd/references/worth.md +74 -0
- package/plugins/kiro/skills/funpixel-mobile-ui/SKILL.md +107 -0
- package/plugins/kiro/skills/funpixel-mobile-ui/references/contrast.md +123 -0
- package/plugins/kiro/skills/funpixel-mobile-ui/references/hud-and-title.md +108 -0
- package/plugins/kiro/skills/funpixel-mobile-ui/references/hud-genres.md +124 -0
- package/plugins/kiro/skills/funpixel-mobile-ui/references/phone-check.md +156 -0
- package/plugins/kiro/skills/funpixel-mobile-ui/references/recipes.md +279 -0
- package/plugins/kiro/skills/funpixel-mobile-ui/references/restyle-ui.md +229 -0
- package/plugins/kiro/skills/funpixel-mobile-ui/references/unity.md +61 -0
- package/plugins/kiro/skills/funpixel-publish/SKILL.md +109 -0
- package/plugins/kiro/skills/funpixel-publish/references/compose.md +113 -0
- package/plugins/kiro/skills/funpixel-publish/references/motion.md +120 -0
- package/plugins/kiro/skills/funpixel-publish/references/networks.md +75 -0
- package/plugins/kiro/skills/funpixel-publish/references/other-hosts.md +65 -0
- package/plugins/kiro/skills/funpixel-publish/references/playable-ad.md +90 -0
- package/plugins/kiro/skills/funpixel-publish/references/server-build.md +85 -0
- package/plugins/kiro/skills/funpixel-publish/references/store-shots.md +85 -0
- package/plugins/kiro/skills/funpixel-publish/references/trailer.md +55 -0
- package/plugins/kiro/skills/funpixel-publish/references/what-ships.md +30 -0
- package/plugins/kiro/skills/funpixel-store/SKILL.md +81 -0
- package/plugins/kiro/skills/funpixel-store/references/app-store.md +73 -0
- package/plugins/kiro/skills/funpixel-store/references/google-play.md +141 -0
- package/plugins/kiro/skills/funpixel-store/references/ios-release.md +63 -0
- package/plugins/kiro/skills/funpixel-store/references/money.md +66 -0
- package/plugins/kiro/skills/funpixel-store/references/purchases-and-review.md +74 -0
- package/plugins/kiro/skills/funpixel-store/references/readiness-page.md +24 -0
- package/plugins/kiro/skills/funpixel-store/references/readiness.md +107 -0
- package/plugins/kiro/skills/funpixel-store/references/steam.md +38 -0
- package/plugins/kiro/skills/funpixel-store/references/unity-store.md +55 -0
- package/plugins/kiro/skills/funpixel-store/references/web-portals.md +43 -0
- package/plugins/kiro/skills/funpixel-unity-game/SKILL.md +103 -0
- package/plugins/kiro/skills/funpixel-unity-game/references/agent-ops.md +54 -0
- package/plugins/kiro/skills/funpixel-unity-game/references/fixes.md +40 -0
- package/plugins/kiro/skills/funpixel-unity-game/references/from-a-web-game.md +108 -0
- package/plugins/kiro/skills/funpixel-unity-game/references/handing-off.md +42 -0
- package/plugins/kiro/skills/funpixel-unity-game/references/performance.md +59 -0
- package/plugins/kiro/skills/funpixel-unity-game/references/probe.md +80 -0
- package/plugins/kiro/skills/funpixel-unity-game/references/shared-mac.md +121 -0
- package/plugins/kiro/skills/funpixel-unity-game/references/traps.md +108 -0
- package/plugins/kiro/skills/funpixel-verify/SKILL.md +109 -0
- package/plugins/kiro/skills/funpixel-verify/references/actors.md +94 -0
- package/plugins/kiro/skills/funpixel-verify/references/bar.md +62 -0
- package/plugins/kiro/skills/funpixel-verify/references/checks.md +69 -0
- package/plugins/kiro/skills/funpixel-verify/references/experience.md +67 -0
- package/plugins/kiro/skills/funpixel-verify/references/eyes.md +54 -0
- package/plugins/kiro/skills/funpixel-verify/references/fidelity.md +126 -0
- package/plugins/kiro/skills/funpixel-verify/references/hit-bar.md +31 -0
- package/plugins/kiro/skills/funpixel-verify/references/journeys.md +77 -0
- package/plugins/kiro/skills/funpixel-verify/references/mobile-qa.md +123 -0
- package/plugins/kiro/skills/funpixel-verify/references/playtest.md +161 -0
- package/plugins/kiro/skills/funpixel-verify/references/review.md +105 -0
- package/plugins/kiro/skills/funpixel-verify/references/rubric.md +67 -0
- package/plugins/kiro/skills/funpixel-verify/references/scenes.md +49 -0
- package/plugins/kiro/skills/funpixel-verify/references/unity.md +60 -0
- package/plugins/kiro/skills/funpixel-world-and-story/SKILL.md +99 -0
- package/plugins/kiro/skills/funpixel-world-and-story/references/atmosphere.md +208 -0
- package/plugins/kiro/skills/funpixel-world-and-story/references/forged-world.md +79 -0
- package/plugins/kiro/skills/funpixel-world-and-story/references/living-world.md +237 -0
- package/plugins/kiro/skills/funpixel-world-and-story/references/opening-and-chapters.md +215 -0
- package/plugins/kiro/skills/funpixel-world-and-story/references/shelf.md +80 -0
- package/plugins/kiro/skills/funpixel-world-and-story/references/story-at-size.md +159 -0
- package/plugins/kiro/skills/funpixel-world-and-story/references/voice.md +175 -0
- package/plugins/kiro/skills/funpixel-world-and-story/references/world-kit.md +154 -0
- package/plugins/robin/LICENSE +115 -0
- package/plugins/robin/README.md +27 -0
- package/plugins/robin/THIRD_PARTY_NOTICES.md +75 -0
- package/plugins/robin/claude/.claude-plugin/plugin.json +19 -0
- package/plugins/robin/claude/.mcp.json +10 -0
- package/plugins/robin/claude/LICENSE +115 -0
- package/plugins/robin/claude/README.md +14 -0
- package/plugins/robin/claude/THIRD_PARTY_NOTICES.md +75 -0
- package/plugins/robin/claude/agents/art-director.md +54 -0
- package/plugins/robin/claude/agents/audio-director.md +51 -0
- package/plugins/robin/claude/agents/critic.md +113 -0
- package/plugins/robin/claude/agents/lane.md +38 -0
- package/plugins/robin/claude/agents/level-designer.md +45 -0
- package/plugins/robin/claude/agents/mobile-qa.md +71 -0
- package/plugins/robin/claude/agents/player.md +144 -0
- package/plugins/robin/claude/agents/qa-lead.md +52 -0
- package/plugins/robin/claude/commands/first-look.md +59 -0
- package/plugins/robin/claude/commands/flow.md +50 -0
- package/plugins/robin/claude/commands/lanes.md +38 -0
- package/plugins/robin/claude/commands/mobile-qa.md +28 -0
- package/plugins/robin/claude/commands/new.md +94 -0
- package/plugins/robin/claude/commands/playtest.md +66 -0
- package/plugins/robin/claude/commands/publish.md +23 -0
- package/plugins/robin/claude/commands/smoke-build.md +25 -0
- package/plugins/robin/claude/commands/verify.md +20 -0
- package/plugins/robin/claude/hooks/brief.md +135 -0
- package/plugins/robin/claude/hooks/critic-receipts.mjs +86 -0
- package/plugins/robin/claude/hooks/durable.mjs +56 -0
- package/plugins/robin/claude/hooks/fence.mjs +30 -0
- package/plugins/robin/claude/hooks/floors.mjs +181 -0
- package/plugins/robin/claude/hooks/flow.mjs +154 -0
- package/plugins/robin/claude/hooks/front-door.mjs +68 -0
- package/plugins/robin/claude/hooks/guidance.json +3 -0
- package/plugins/robin/claude/hooks/hints.mjs +183 -0
- package/plugins/robin/claude/hooks/hooks.json +62 -0
- package/plugins/robin/claude/hooks/lib.mjs +362 -0
- package/plugins/robin/claude/hooks/memory.mjs +92 -0
- package/plugins/robin/claude/hooks/mobile-qa.mjs +43 -0
- package/plugins/robin/claude/hooks/note.mjs +63 -0
- package/plugins/robin/claude/hooks/nudge.mjs +98 -0
- package/plugins/robin/claude/hooks/pipeline.mjs +207 -0
- package/plugins/robin/claude/hooks/prompt.mjs +51 -0
- package/plugins/robin/claude/hooks/quality.mjs +310 -0
- package/plugins/robin/claude/hooks/reach.mjs +93 -0
- package/plugins/robin/claude/hooks/scope.mjs +44 -0
- package/plugins/robin/claude/hooks/session-log.mjs +101 -0
- package/plugins/robin/claude/hooks/session-start.mjs +194 -0
- package/plugins/robin/claude/hooks/skill-names.json +19 -0
- package/plugins/robin/claude/hooks/stop-gate.mjs +303 -0
- package/plugins/robin/claude/hooks/vendor/direct/round.mjs +81 -0
- package/plugins/robin/claude/hooks/vendor/find/names.mjs +46 -0
- package/plugins/robin/claude/hooks/vendor/firstlook/set.mjs +219 -0
- package/plugins/robin/claude/hooks/vendor/flow/flow.mjs +456 -0
- package/plugins/robin/claude/hooks/vendor/flow/look.mjs +140 -0
- package/plugins/robin/claude/hooks/vendor/gdd/book.mjs +484 -0
- package/plugins/robin/claude/hooks/vendor/gdd/chapters.mjs +72 -0
- package/plugins/robin/claude/hooks/vendor/gdd/doc.mjs +33 -0
- package/plugins/robin/claude/hooks/vendor/gdd/levelmap.mjs +429 -0
- package/plugins/robin/claude/hooks/vendor/gdd/rubric.mjs +251 -0
- package/plugins/robin/claude/hooks/vendor/gdd/worth.mjs +508 -0
- package/plugins/robin/claude/hooks/vendor/lanes/fence.mjs +109 -0
- package/plugins/robin/claude/hooks/vendor/lanes/lanes.mjs +356 -0
- package/plugins/robin/claude/hooks/vendor/lanes/union.mjs +63 -0
- package/plugins/robin/claude/hooks/vendor/lessons/motifs.mjs +98 -0
- package/plugins/robin/claude/hooks/vendor/lessons/store.mjs +57 -0
- package/plugins/robin/claude/hooks/vendor/look/made-of.mjs +243 -0
- package/plugins/robin/claude/hooks/vendor/look/roles.mjs +110 -0
- package/plugins/robin/claude/hooks/vendor/memory/decisions.mjs +139 -0
- package/plugins/robin/claude/hooks/vendor/memory/journal.mjs +109 -0
- package/plugins/robin/claude/hooks/vendor/owner/bar.mjs +286 -0
- package/plugins/robin/claude/hooks/vendor/pipeline/pipeline.mjs +930 -0
- package/plugins/robin/claude/hooks/vendor/playtest/keep.mjs +111 -0
- package/plugins/robin/claude/hooks/vendor/playtest/stuck.mjs +48 -0
- package/plugins/robin/claude/hooks/vendor/progress/holds.mjs +107 -0
- package/plugins/robin/claude/hooks/vendor/progress/progress.mjs +301 -0
- package/plugins/robin/claude/hooks/vendor/sim/judge.mjs +241 -0
- package/plugins/robin/claude/hooks/vendor/spec/rooms.mjs +189 -0
- package/plugins/robin/claude/hooks/vendor/spec/tunables.mjs +75 -0
- package/plugins/robin/claude/hooks/vendor/stage/harnessignore.mjs +91 -0
- package/plugins/robin/claude/hooks/vendor/stage/stage.mjs +58 -0
- package/plugins/robin/claude/hooks/vendor/status/board.mjs +173 -0
- package/plugins/robin/claude/hooks/vendor/status/file.mjs +113 -0
- package/plugins/robin/claude/hooks/vendor/studio/forks.mjs +94 -0
- package/plugins/robin/claude/hooks/vendor/studio/pitch.mjs +295 -0
- package/plugins/robin/claude/hooks/vendor/verify/fingerprint.mjs +73 -0
- package/plugins/robin/claude/hooks/vendor/verify/reads.mjs +33 -0
- package/plugins/robin/claude/hooks/vendor/wow/picks.mjs +75 -0
- package/plugins/robin/claude/skills/3d/SKILL.md +89 -0
- package/plugins/robin/claude/skills/3d/references/bake-off.md +48 -0
- package/plugins/robin/claude/skills/3d/references/bench.md +103 -0
- package/plugins/robin/claude/skills/3d/references/budgets.md +48 -0
- package/plugins/robin/claude/skills/3d/references/characters.md +67 -0
- package/plugins/robin/claude/skills/3d/references/concept-image.md +47 -0
- package/plugins/robin/claude/skills/3d/references/engine-targets.md +31 -0
- package/plugins/robin/claude/skills/3d/references/hero-route.md +104 -0
- package/plugins/robin/claude/skills/3d/references/level-spec.md +109 -0
- package/plugins/robin/claude/skills/3d/references/levels.md +84 -0
- package/plugins/robin/claude/skills/3d/references/light-and-places.md +141 -0
- package/plugins/robin/claude/skills/3d/references/models.md +111 -0
- package/plugins/robin/claude/skills/3d/references/painted-target.md +184 -0
- package/plugins/robin/claude/skills/3d/references/reading.md +41 -0
- package/plugins/robin/claude/skills/3d/references/skin.md +85 -0
- package/plugins/robin/claude/skills/3d/references/skyboxes.md +65 -0
- package/plugins/robin/claude/skills/3d/references/textures.md +71 -0
- package/plugins/robin/claude/skills/3d/references/three-loading.md +199 -0
- package/plugins/robin/claude/skills/3d/references/unity.md +78 -0
- package/plugins/robin/claude/skills/art/SKILL.md +104 -0
- package/plugins/robin/claude/skills/art/references/2d-assets.md +108 -0
- package/plugins/robin/claude/skills/art/references/animation.md +126 -0
- package/plugins/robin/claude/skills/art/references/cast.md +73 -0
- package/plugins/robin/claude/skills/art/references/characters.md +49 -0
- package/plugins/robin/claude/skills/art/references/cost.md +107 -0
- package/plugins/robin/claude/skills/art/references/effects.md +85 -0
- package/plugins/robin/claude/skills/art/references/frames.md +87 -0
- package/plugins/robin/claude/skills/art/references/judging-frames.md +64 -0
- package/plugins/robin/claude/skills/art/references/look.md +102 -0
- package/plugins/robin/claude/skills/art/references/measure.md +119 -0
- package/plugins/robin/claude/skills/art/references/pipeline.md +185 -0
- package/plugins/robin/claude/skills/art/references/pixi.md +277 -0
- package/plugins/robin/claude/skills/art/references/planes.md +27 -0
- package/plugins/robin/claude/skills/art/references/prompts.md +171 -0
- package/plugins/robin/claude/skills/art/references/sheets.md +141 -0
- package/plugins/robin/claude/skills/art/references/style-file.md +39 -0
- package/plugins/robin/claude/skills/art/references/three.md +232 -0
- package/plugins/robin/claude/skills/art/references/ui.md +163 -0
- package/plugins/robin/claude/skills/art/references/unity.md +78 -0
- package/plugins/robin/claude/skills/art/references/wiring.md +41 -0
- package/plugins/robin/claude/skills/audio/SKILL.md +92 -0
- package/plugins/robin/claude/skills/audio/references/adaptive-music.md +204 -0
- package/plugins/robin/claude/skills/audio/references/engine.md +78 -0
- package/plugins/robin/claude/skills/audio/references/measure.md +101 -0
- package/plugins/robin/claude/skills/audio/references/unity.md +74 -0
- package/plugins/robin/claude/skills/feedback/SKILL.md +120 -0
- package/plugins/robin/claude/skills/feedback/references/memory.md +99 -0
- package/plugins/robin/claude/skills/game-feel/SKILL.md +104 -0
- package/plugins/robin/claude/skills/game-feel/references/contact.md +110 -0
- package/plugins/robin/claude/skills/game-feel/references/measure.md +125 -0
- package/plugins/robin/claude/skills/game-feel/references/motion.md +134 -0
- package/plugins/robin/claude/skills/game-feel/references/payoffs.md +35 -0
- package/plugins/robin/claude/skills/game-feel/references/recipes.md +107 -0
- package/plugins/robin/claude/skills/game-feel/references/unity.md +73 -0
- package/plugins/robin/claude/skills/game-logic/SKILL.md +113 -0
- package/plugins/robin/claude/skills/game-logic/references/balance.md +88 -0
- package/plugins/robin/claude/skills/game-logic/references/content-at-scale.md +147 -0
- package/plugins/robin/claude/skills/game-logic/references/depth.md +89 -0
- package/plugins/robin/claude/skills/game-logic/references/escalation.md +41 -0
- package/plugins/robin/claude/skills/game-logic/references/levels.md +61 -0
- package/plugins/robin/claude/skills/game-logic/references/probes.md +122 -0
- package/plugins/robin/claude/skills/game-logic/references/unity.md +108 -0
- package/plugins/robin/claude/skills/game-spine/SKILL.md +118 -0
- package/plugins/robin/claude/skills/game-spine/references/camera.md +94 -0
- package/plugins/robin/claude/skills/game-spine/references/multiplayer.md +101 -0
- package/plugins/robin/claude/skills/game-spine/references/patterns.md +103 -0
- package/plugins/robin/claude/skills/game-spine/references/performance.md +96 -0
- package/plugins/robin/claude/skills/game-spine/references/pixi.md +26 -0
- package/plugins/robin/claude/skills/game-spine/references/replay.md +102 -0
- package/plugins/robin/claude/skills/game-spine/references/room-api.md +63 -0
- package/plugins/robin/claude/skills/game-spine/references/room-modes.md +40 -0
- package/plugins/robin/claude/skills/game-spine/references/sdk.md +114 -0
- package/plugins/robin/claude/skills/game-spine/references/three.md +62 -0
- package/plugins/robin/claude/skills/gdd/SKILL.md +116 -0
- package/plugins/robin/claude/skills/gdd/references/as-built.md +40 -0
- package/plugins/robin/claude/skills/gdd/references/design-measures.md +24 -0
- package/plugins/robin/claude/skills/gdd/references/design-note.md +88 -0
- package/plugins/robin/claude/skills/gdd/references/experience.md +92 -0
- package/plugins/robin/claude/skills/gdd/references/first-look.md +226 -0
- package/plugins/robin/claude/skills/gdd/references/floors.md +62 -0
- package/plugins/robin/claude/skills/gdd/references/frame.md +75 -0
- package/plugins/robin/claude/skills/gdd/references/gameplay-contract.md +81 -0
- package/plugins/robin/claude/skills/gdd/references/gdd-template.md +417 -0
- package/plugins/robin/claude/skills/gdd/references/genre-card.md +109 -0
- package/plugins/robin/claude/skills/gdd/references/genre-platformer.md +159 -0
- package/plugins/robin/claude/skills/gdd/references/genre-puzzle.md +145 -0
- package/plugins/robin/claude/skills/gdd/references/genre-racing.md +137 -0
- package/plugins/robin/claude/skills/gdd/references/genre-rpg.md +125 -0
- package/plugins/robin/claude/skills/gdd/references/genre-shooter.md +128 -0
- package/plugins/robin/claude/skills/gdd/references/genre-simulation.md +112 -0
- package/plugins/robin/claude/skills/gdd/references/genre-strategy.md +116 -0
- package/plugins/robin/claude/skills/gdd/references/genre-survival.md +122 -0
- package/plugins/robin/claude/skills/gdd/references/in-the-loop.md +106 -0
- package/plugins/robin/claude/skills/gdd/references/invent-first.md +131 -0
- package/plugins/robin/claude/skills/gdd/references/level-and-fun.md +112 -0
- package/plugins/robin/claude/skills/gdd/references/pages.md +47 -0
- package/plugins/robin/claude/skills/gdd/references/plan-at-size.md +140 -0
- package/plugins/robin/claude/skills/gdd/references/production-tiers.md +117 -0
- package/plugins/robin/claude/skills/gdd/references/sections.md +148 -0
- package/plugins/robin/claude/skills/gdd/references/spec-folder.md +131 -0
- package/plugins/robin/claude/skills/gdd/references/start.md +110 -0
- package/plugins/robin/claude/skills/gdd/references/starters.md +175 -0
- package/plugins/robin/claude/skills/gdd/references/the-path.md +133 -0
- package/plugins/robin/claude/skills/gdd/references/track.md +29 -0
- package/plugins/robin/claude/skills/gdd/references/world-and-identity.md +165 -0
- package/plugins/robin/claude/skills/gdd/references/worth.md +74 -0
- package/plugins/robin/claude/skills/mobile-ui/SKILL.md +107 -0
- package/plugins/robin/claude/skills/mobile-ui/references/contrast.md +123 -0
- package/plugins/robin/claude/skills/mobile-ui/references/hud-and-title.md +108 -0
- package/plugins/robin/claude/skills/mobile-ui/references/hud-genres.md +124 -0
- package/plugins/robin/claude/skills/mobile-ui/references/phone-check.md +156 -0
- package/plugins/robin/claude/skills/mobile-ui/references/recipes.md +279 -0
- package/plugins/robin/claude/skills/mobile-ui/references/restyle-ui.md +229 -0
- package/plugins/robin/claude/skills/mobile-ui/references/unity.md +61 -0
- package/plugins/robin/claude/skills/publishing/SKILL.md +109 -0
- package/plugins/robin/claude/skills/publishing/references/compose.md +113 -0
- package/plugins/robin/claude/skills/publishing/references/motion.md +120 -0
- package/plugins/robin/claude/skills/publishing/references/networks.md +75 -0
- package/plugins/robin/claude/skills/publishing/references/other-hosts.md +65 -0
- package/plugins/robin/claude/skills/publishing/references/playable-ad.md +90 -0
- package/plugins/robin/claude/skills/publishing/references/server-build.md +85 -0
- package/plugins/robin/claude/skills/publishing/references/store-shots.md +85 -0
- package/plugins/robin/claude/skills/publishing/references/trailer.md +55 -0
- package/plugins/robin/claude/skills/publishing/references/what-ships.md +30 -0
- package/plugins/robin/claude/skills/store/SKILL.md +81 -0
- package/plugins/robin/claude/skills/store/references/app-store.md +73 -0
- package/plugins/robin/claude/skills/store/references/google-play.md +141 -0
- package/plugins/robin/claude/skills/store/references/ios-release.md +63 -0
- package/plugins/robin/claude/skills/store/references/money.md +66 -0
- package/plugins/robin/claude/skills/store/references/purchases-and-review.md +74 -0
- package/plugins/robin/claude/skills/store/references/readiness-page.md +24 -0
- package/plugins/robin/claude/skills/store/references/readiness.md +107 -0
- package/plugins/robin/claude/skills/store/references/steam.md +38 -0
- package/plugins/robin/claude/skills/store/references/unity-store.md +55 -0
- package/plugins/robin/claude/skills/store/references/web-portals.md +43 -0
- package/plugins/robin/claude/skills/unity-game/SKILL.md +103 -0
- package/plugins/robin/claude/skills/unity-game/references/agent-ops.md +54 -0
- package/plugins/robin/claude/skills/unity-game/references/fixes.md +40 -0
- package/plugins/robin/claude/skills/unity-game/references/from-a-web-game.md +108 -0
- package/plugins/robin/claude/skills/unity-game/references/handing-off.md +42 -0
- package/plugins/robin/claude/skills/unity-game/references/performance.md +59 -0
- package/plugins/robin/claude/skills/unity-game/references/probe.md +80 -0
- package/plugins/robin/claude/skills/unity-game/references/shared-mac.md +121 -0
- package/plugins/robin/claude/skills/unity-game/references/traps.md +108 -0
- package/plugins/robin/claude/skills/verifying/SKILL.md +109 -0
- package/plugins/robin/claude/skills/verifying/references/actors.md +94 -0
- package/plugins/robin/claude/skills/verifying/references/bar.md +62 -0
- package/plugins/robin/claude/skills/verifying/references/checks.md +69 -0
- package/plugins/robin/claude/skills/verifying/references/experience.md +67 -0
- package/plugins/robin/claude/skills/verifying/references/eyes.md +54 -0
- package/plugins/robin/claude/skills/verifying/references/fidelity.md +126 -0
- package/plugins/robin/claude/skills/verifying/references/hit-bar.md +31 -0
- package/plugins/robin/claude/skills/verifying/references/journeys.md +77 -0
- package/plugins/robin/claude/skills/verifying/references/mobile-qa.md +123 -0
- package/plugins/robin/claude/skills/verifying/references/playtest.md +161 -0
- package/plugins/robin/claude/skills/verifying/references/review.md +105 -0
- package/plugins/robin/claude/skills/verifying/references/rubric.md +67 -0
- package/plugins/robin/claude/skills/verifying/references/scenes.md +49 -0
- package/plugins/robin/claude/skills/verifying/references/unity.md +60 -0
- package/plugins/robin/claude/skills/world-and-story/SKILL.md +99 -0
- package/plugins/robin/claude/skills/world-and-story/references/atmosphere.md +208 -0
- package/plugins/robin/claude/skills/world-and-story/references/forged-world.md +79 -0
- package/plugins/robin/claude/skills/world-and-story/references/living-world.md +237 -0
- package/plugins/robin/claude/skills/world-and-story/references/opening-and-chapters.md +215 -0
- package/plugins/robin/claude/skills/world-and-story/references/shelf.md +80 -0
- package/plugins/robin/claude/skills/world-and-story/references/story-at-size.md +159 -0
- package/plugins/robin/claude/skills/world-and-story/references/voice.md +175 -0
- package/plugins/robin/claude/skills/world-and-story/references/world-kit.md +154 -0
- package/plugins/robin/mcp-servers.json +25 -0
- package/plugins/robin/plugin.json +20 -0
- package/plugins/robin/skills/fp-first-look/SKILL.md +59 -0
- package/plugins/robin/skills/fp-flow/SKILL.md +50 -0
- package/plugins/robin/skills/fp-lanes/SKILL.md +38 -0
- package/plugins/robin/skills/fp-mobile-qa/SKILL.md +28 -0
- package/plugins/robin/skills/fp-new/SKILL.md +94 -0
- package/plugins/robin/skills/fp-playtest/SKILL.md +66 -0
- package/plugins/robin/skills/fp-publish/SKILL.md +23 -0
- package/plugins/robin/skills/fp-smoke-build/SKILL.md +25 -0
- package/plugins/robin/skills/fp-verify/SKILL.md +20 -0
- package/plugins/robin/skills/funpixel-3d/SKILL.md +89 -0
- package/plugins/robin/skills/funpixel-3d/references/bake-off.md +48 -0
- package/plugins/robin/skills/funpixel-3d/references/bench.md +103 -0
- package/plugins/robin/skills/funpixel-3d/references/budgets.md +48 -0
- package/plugins/robin/skills/funpixel-3d/references/characters.md +67 -0
- package/plugins/robin/skills/funpixel-3d/references/concept-image.md +47 -0
- package/plugins/robin/skills/funpixel-3d/references/engine-targets.md +31 -0
- package/plugins/robin/skills/funpixel-3d/references/hero-route.md +104 -0
- package/plugins/robin/skills/funpixel-3d/references/level-spec.md +109 -0
- package/plugins/robin/skills/funpixel-3d/references/levels.md +84 -0
- package/plugins/robin/skills/funpixel-3d/references/light-and-places.md +141 -0
- package/plugins/robin/skills/funpixel-3d/references/models.md +111 -0
- package/plugins/robin/skills/funpixel-3d/references/painted-target.md +184 -0
- package/plugins/robin/skills/funpixel-3d/references/reading.md +41 -0
- package/plugins/robin/skills/funpixel-3d/references/skin.md +85 -0
- package/plugins/robin/skills/funpixel-3d/references/skyboxes.md +65 -0
- package/plugins/robin/skills/funpixel-3d/references/textures.md +71 -0
- package/plugins/robin/skills/funpixel-3d/references/three-loading.md +199 -0
- package/plugins/robin/skills/funpixel-3d/references/unity.md +78 -0
- package/plugins/robin/skills/funpixel-art/SKILL.md +104 -0
- package/plugins/robin/skills/funpixel-art/references/2d-assets.md +108 -0
- package/plugins/robin/skills/funpixel-art/references/animation.md +126 -0
- package/plugins/robin/skills/funpixel-art/references/cast.md +73 -0
- package/plugins/robin/skills/funpixel-art/references/characters.md +49 -0
- package/plugins/robin/skills/funpixel-art/references/cost.md +107 -0
- package/plugins/robin/skills/funpixel-art/references/effects.md +85 -0
- package/plugins/robin/skills/funpixel-art/references/frames.md +87 -0
- package/plugins/robin/skills/funpixel-art/references/judging-frames.md +64 -0
- package/plugins/robin/skills/funpixel-art/references/look.md +102 -0
- package/plugins/robin/skills/funpixel-art/references/measure.md +119 -0
- package/plugins/robin/skills/funpixel-art/references/pipeline.md +185 -0
- package/plugins/robin/skills/funpixel-art/references/pixi.md +277 -0
- package/plugins/robin/skills/funpixel-art/references/planes.md +27 -0
- package/plugins/robin/skills/funpixel-art/references/prompts.md +171 -0
- package/plugins/robin/skills/funpixel-art/references/sheets.md +141 -0
- package/plugins/robin/skills/funpixel-art/references/style-file.md +39 -0
- package/plugins/robin/skills/funpixel-art/references/three.md +232 -0
- package/plugins/robin/skills/funpixel-art/references/ui.md +163 -0
- package/plugins/robin/skills/funpixel-art/references/unity.md +78 -0
- package/plugins/robin/skills/funpixel-art/references/wiring.md +41 -0
- package/plugins/robin/skills/funpixel-audio/SKILL.md +92 -0
- package/plugins/robin/skills/funpixel-audio/references/adaptive-music.md +204 -0
- package/plugins/robin/skills/funpixel-audio/references/engine.md +78 -0
- package/plugins/robin/skills/funpixel-audio/references/measure.md +101 -0
- package/plugins/robin/skills/funpixel-audio/references/unity.md +74 -0
- package/plugins/robin/skills/funpixel-brief/SKILL.md +163 -0
- package/plugins/robin/skills/funpixel-feedback/SKILL.md +120 -0
- package/plugins/robin/skills/funpixel-feedback/references/memory.md +99 -0
- package/plugins/robin/skills/funpixel-game-feel/SKILL.md +104 -0
- package/plugins/robin/skills/funpixel-game-feel/references/contact.md +110 -0
- package/plugins/robin/skills/funpixel-game-feel/references/measure.md +125 -0
- package/plugins/robin/skills/funpixel-game-feel/references/motion.md +134 -0
- package/plugins/robin/skills/funpixel-game-feel/references/payoffs.md +35 -0
- package/plugins/robin/skills/funpixel-game-feel/references/recipes.md +107 -0
- package/plugins/robin/skills/funpixel-game-feel/references/unity.md +73 -0
- package/plugins/robin/skills/funpixel-game-logic/SKILL.md +113 -0
- package/plugins/robin/skills/funpixel-game-logic/references/balance.md +88 -0
- package/plugins/robin/skills/funpixel-game-logic/references/content-at-scale.md +147 -0
- package/plugins/robin/skills/funpixel-game-logic/references/depth.md +89 -0
- package/plugins/robin/skills/funpixel-game-logic/references/escalation.md +41 -0
- package/plugins/robin/skills/funpixel-game-logic/references/levels.md +61 -0
- package/plugins/robin/skills/funpixel-game-logic/references/probes.md +122 -0
- package/plugins/robin/skills/funpixel-game-logic/references/unity.md +108 -0
- package/plugins/robin/skills/funpixel-game-spine/SKILL.md +118 -0
- package/plugins/robin/skills/funpixel-game-spine/references/camera.md +94 -0
- package/plugins/robin/skills/funpixel-game-spine/references/multiplayer.md +101 -0
- package/plugins/robin/skills/funpixel-game-spine/references/patterns.md +103 -0
- package/plugins/robin/skills/funpixel-game-spine/references/performance.md +96 -0
- package/plugins/robin/skills/funpixel-game-spine/references/pixi.md +26 -0
- package/plugins/robin/skills/funpixel-game-spine/references/replay.md +102 -0
- package/plugins/robin/skills/funpixel-game-spine/references/room-api.md +63 -0
- package/plugins/robin/skills/funpixel-game-spine/references/room-modes.md +40 -0
- package/plugins/robin/skills/funpixel-game-spine/references/sdk.md +114 -0
- package/plugins/robin/skills/funpixel-game-spine/references/three.md +62 -0
- package/plugins/robin/skills/funpixel-gdd/SKILL.md +116 -0
- package/plugins/robin/skills/funpixel-gdd/references/as-built.md +40 -0
- package/plugins/robin/skills/funpixel-gdd/references/design-measures.md +24 -0
- package/plugins/robin/skills/funpixel-gdd/references/design-note.md +88 -0
- package/plugins/robin/skills/funpixel-gdd/references/experience.md +92 -0
- package/plugins/robin/skills/funpixel-gdd/references/first-look.md +226 -0
- package/plugins/robin/skills/funpixel-gdd/references/floors.md +62 -0
- package/plugins/robin/skills/funpixel-gdd/references/frame.md +75 -0
- package/plugins/robin/skills/funpixel-gdd/references/gameplay-contract.md +81 -0
- package/plugins/robin/skills/funpixel-gdd/references/gdd-template.md +417 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-card.md +109 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-platformer.md +159 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-puzzle.md +145 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-racing.md +137 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-rpg.md +125 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-shooter.md +128 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-simulation.md +112 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-strategy.md +116 -0
- package/plugins/robin/skills/funpixel-gdd/references/genre-survival.md +122 -0
- package/plugins/robin/skills/funpixel-gdd/references/in-the-loop.md +106 -0
- package/plugins/robin/skills/funpixel-gdd/references/invent-first.md +131 -0
- package/plugins/robin/skills/funpixel-gdd/references/level-and-fun.md +112 -0
- package/plugins/robin/skills/funpixel-gdd/references/pages.md +47 -0
- package/plugins/robin/skills/funpixel-gdd/references/plan-at-size.md +140 -0
- package/plugins/robin/skills/funpixel-gdd/references/production-tiers.md +117 -0
- package/plugins/robin/skills/funpixel-gdd/references/sections.md +148 -0
- package/plugins/robin/skills/funpixel-gdd/references/spec-folder.md +131 -0
- package/plugins/robin/skills/funpixel-gdd/references/start.md +110 -0
- package/plugins/robin/skills/funpixel-gdd/references/starters.md +175 -0
- package/plugins/robin/skills/funpixel-gdd/references/the-path.md +133 -0
- package/plugins/robin/skills/funpixel-gdd/references/track.md +29 -0
- package/plugins/robin/skills/funpixel-gdd/references/world-and-identity.md +165 -0
- package/plugins/robin/skills/funpixel-gdd/references/worth.md +74 -0
- package/plugins/robin/skills/funpixel-mobile-ui/SKILL.md +107 -0
- package/plugins/robin/skills/funpixel-mobile-ui/references/contrast.md +123 -0
- package/plugins/robin/skills/funpixel-mobile-ui/references/hud-and-title.md +108 -0
- package/plugins/robin/skills/funpixel-mobile-ui/references/hud-genres.md +124 -0
- package/plugins/robin/skills/funpixel-mobile-ui/references/phone-check.md +156 -0
- package/plugins/robin/skills/funpixel-mobile-ui/references/recipes.md +279 -0
- package/plugins/robin/skills/funpixel-mobile-ui/references/restyle-ui.md +229 -0
- package/plugins/robin/skills/funpixel-mobile-ui/references/unity.md +61 -0
- package/plugins/robin/skills/funpixel-publish/SKILL.md +109 -0
- package/plugins/robin/skills/funpixel-publish/references/compose.md +113 -0
- package/plugins/robin/skills/funpixel-publish/references/motion.md +120 -0
- package/plugins/robin/skills/funpixel-publish/references/networks.md +75 -0
- package/plugins/robin/skills/funpixel-publish/references/other-hosts.md +65 -0
- package/plugins/robin/skills/funpixel-publish/references/playable-ad.md +90 -0
- package/plugins/robin/skills/funpixel-publish/references/server-build.md +85 -0
- package/plugins/robin/skills/funpixel-publish/references/store-shots.md +85 -0
- package/plugins/robin/skills/funpixel-publish/references/trailer.md +55 -0
- package/plugins/robin/skills/funpixel-publish/references/what-ships.md +30 -0
- package/plugins/robin/skills/funpixel-store/SKILL.md +81 -0
- package/plugins/robin/skills/funpixel-store/references/app-store.md +73 -0
- package/plugins/robin/skills/funpixel-store/references/google-play.md +141 -0
- package/plugins/robin/skills/funpixel-store/references/ios-release.md +63 -0
- package/plugins/robin/skills/funpixel-store/references/money.md +66 -0
- package/plugins/robin/skills/funpixel-store/references/purchases-and-review.md +74 -0
- package/plugins/robin/skills/funpixel-store/references/readiness-page.md +24 -0
- package/plugins/robin/skills/funpixel-store/references/readiness.md +107 -0
- package/plugins/robin/skills/funpixel-store/references/steam.md +38 -0
- package/plugins/robin/skills/funpixel-store/references/unity-store.md +55 -0
- package/plugins/robin/skills/funpixel-store/references/web-portals.md +43 -0
- package/plugins/robin/skills/funpixel-unity-game/SKILL.md +103 -0
- package/plugins/robin/skills/funpixel-unity-game/references/agent-ops.md +54 -0
- package/plugins/robin/skills/funpixel-unity-game/references/fixes.md +40 -0
- package/plugins/robin/skills/funpixel-unity-game/references/from-a-web-game.md +108 -0
- package/plugins/robin/skills/funpixel-unity-game/references/handing-off.md +42 -0
- package/plugins/robin/skills/funpixel-unity-game/references/performance.md +59 -0
- package/plugins/robin/skills/funpixel-unity-game/references/probe.md +80 -0
- package/plugins/robin/skills/funpixel-unity-game/references/shared-mac.md +121 -0
- package/plugins/robin/skills/funpixel-unity-game/references/traps.md +108 -0
- package/plugins/robin/skills/funpixel-verify/SKILL.md +109 -0
- package/plugins/robin/skills/funpixel-verify/references/actors.md +94 -0
- package/plugins/robin/skills/funpixel-verify/references/bar.md +62 -0
- package/plugins/robin/skills/funpixel-verify/references/checks.md +69 -0
- package/plugins/robin/skills/funpixel-verify/references/experience.md +67 -0
- package/plugins/robin/skills/funpixel-verify/references/eyes.md +54 -0
- package/plugins/robin/skills/funpixel-verify/references/fidelity.md +126 -0
- package/plugins/robin/skills/funpixel-verify/references/hit-bar.md +31 -0
- package/plugins/robin/skills/funpixel-verify/references/journeys.md +77 -0
- package/plugins/robin/skills/funpixel-verify/references/mobile-qa.md +123 -0
- package/plugins/robin/skills/funpixel-verify/references/playtest.md +161 -0
- package/plugins/robin/skills/funpixel-verify/references/review.md +105 -0
- package/plugins/robin/skills/funpixel-verify/references/rubric.md +67 -0
- package/plugins/robin/skills/funpixel-verify/references/scenes.md +49 -0
- package/plugins/robin/skills/funpixel-verify/references/unity.md +60 -0
- package/plugins/robin/skills/funpixel-world-and-story/SKILL.md +99 -0
- package/plugins/robin/skills/funpixel-world-and-story/references/atmosphere.md +208 -0
- package/plugins/robin/skills/funpixel-world-and-story/references/forged-world.md +79 -0
- package/plugins/robin/skills/funpixel-world-and-story/references/living-world.md +237 -0
- package/plugins/robin/skills/funpixel-world-and-story/references/opening-and-chapters.md +215 -0
- package/plugins/robin/skills/funpixel-world-and-story/references/shelf.md +80 -0
- package/plugins/robin/skills/funpixel-world-and-story/references/story-at-size.md +159 -0
- package/plugins/robin/skills/funpixel-world-and-story/references/voice.md +175 -0
- package/plugins/robin/skills/funpixel-world-and-story/references/world-kit.md +154 -0
- package/templates/common/.agents/skills/funpixel-3d/SKILL.md +89 -0
- package/templates/common/.agents/skills/funpixel-3d/references/bake-off.md +48 -0
- package/templates/common/.agents/skills/funpixel-3d/references/bench.md +103 -0
- package/templates/common/.agents/skills/funpixel-3d/references/budgets.md +48 -0
- package/templates/common/.agents/skills/funpixel-3d/references/characters.md +67 -0
- package/templates/common/.agents/skills/funpixel-3d/references/concept-image.md +47 -0
- package/templates/common/.agents/skills/funpixel-3d/references/engine-targets.md +31 -0
- package/templates/common/.agents/skills/funpixel-3d/references/hero-route.md +104 -0
- package/templates/common/.agents/skills/funpixel-3d/references/level-spec.md +109 -0
- package/templates/common/.agents/skills/funpixel-3d/references/levels.md +84 -0
- package/templates/common/.agents/skills/funpixel-3d/references/light-and-places.md +141 -0
- package/templates/common/.agents/skills/funpixel-3d/references/models.md +111 -0
- package/templates/common/.agents/skills/funpixel-3d/references/painted-target.md +184 -0
- package/templates/common/.agents/skills/funpixel-3d/references/reading.md +41 -0
- package/templates/common/.agents/skills/funpixel-3d/references/skin.md +85 -0
- package/templates/common/.agents/skills/funpixel-3d/references/skyboxes.md +65 -0
- package/templates/common/.agents/skills/funpixel-3d/references/textures.md +71 -0
- package/templates/common/.agents/skills/funpixel-3d/references/three-loading.md +199 -0
- package/templates/common/.agents/skills/funpixel-3d/references/unity.md +78 -0
- package/templates/common/.agents/skills/funpixel-art/SKILL.md +104 -0
- package/templates/common/.agents/skills/funpixel-art/references/2d-assets.md +108 -0
- package/templates/common/.agents/skills/funpixel-art/references/animation.md +126 -0
- package/templates/common/.agents/skills/funpixel-art/references/cast.md +73 -0
- package/templates/common/.agents/skills/funpixel-art/references/characters.md +49 -0
- package/templates/common/.agents/skills/funpixel-art/references/cost.md +107 -0
- package/templates/common/.agents/skills/funpixel-art/references/effects.md +85 -0
- package/templates/common/.agents/skills/funpixel-art/references/frames.md +87 -0
- package/templates/common/.agents/skills/funpixel-art/references/judging-frames.md +64 -0
- package/templates/common/.agents/skills/funpixel-art/references/look.md +102 -0
- package/templates/common/.agents/skills/funpixel-art/references/measure.md +119 -0
- package/templates/common/.agents/skills/funpixel-art/references/pipeline.md +185 -0
- package/templates/common/.agents/skills/funpixel-art/references/pixi.md +277 -0
- package/templates/common/.agents/skills/funpixel-art/references/planes.md +27 -0
- package/templates/common/.agents/skills/funpixel-art/references/prompts.md +171 -0
- package/templates/common/.agents/skills/funpixel-art/references/sheets.md +141 -0
- package/templates/common/.agents/skills/funpixel-art/references/style-file.md +39 -0
- package/templates/common/.agents/skills/funpixel-art/references/three.md +232 -0
- package/templates/common/.agents/skills/funpixel-art/references/ui.md +163 -0
- package/templates/common/.agents/skills/funpixel-art/references/unity.md +78 -0
- package/templates/common/.agents/skills/funpixel-art/references/wiring.md +41 -0
- package/templates/common/.agents/skills/funpixel-audio/SKILL.md +92 -0
- package/templates/common/.agents/skills/funpixel-audio/references/adaptive-music.md +204 -0
- package/templates/common/.agents/skills/funpixel-audio/references/engine.md +78 -0
- package/templates/common/.agents/skills/funpixel-audio/references/measure.md +101 -0
- package/templates/common/.agents/skills/funpixel-audio/references/unity.md +74 -0
- package/templates/common/.agents/skills/funpixel-feedback/SKILL.md +120 -0
- package/templates/common/.agents/skills/funpixel-feedback/references/memory.md +99 -0
- package/templates/common/.agents/skills/funpixel-game-feel/SKILL.md +104 -0
- package/templates/common/.agents/skills/funpixel-game-feel/references/contact.md +110 -0
- package/templates/common/.agents/skills/funpixel-game-feel/references/measure.md +125 -0
- package/templates/common/.agents/skills/funpixel-game-feel/references/motion.md +134 -0
- package/templates/common/.agents/skills/funpixel-game-feel/references/payoffs.md +35 -0
- package/templates/common/.agents/skills/funpixel-game-feel/references/recipes.md +107 -0
- package/templates/common/.agents/skills/funpixel-game-feel/references/unity.md +73 -0
- package/templates/common/.agents/skills/funpixel-game-logic/SKILL.md +113 -0
- package/templates/common/.agents/skills/funpixel-game-logic/references/balance.md +88 -0
- package/templates/common/.agents/skills/funpixel-game-logic/references/content-at-scale.md +147 -0
- package/templates/common/.agents/skills/funpixel-game-logic/references/depth.md +89 -0
- package/templates/common/.agents/skills/funpixel-game-logic/references/escalation.md +41 -0
- package/templates/common/.agents/skills/funpixel-game-logic/references/levels.md +61 -0
- package/templates/common/.agents/skills/funpixel-game-logic/references/probes.md +122 -0
- package/templates/common/.agents/skills/funpixel-game-logic/references/unity.md +108 -0
- package/templates/common/.agents/skills/funpixel-game-spine/SKILL.md +118 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/camera.md +94 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/multiplayer.md +101 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/patterns.md +103 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/performance.md +96 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/pixi.md +26 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/replay.md +102 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/room-api.md +63 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/room-modes.md +40 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/sdk.md +114 -0
- package/templates/common/.agents/skills/funpixel-game-spine/references/three.md +62 -0
- package/templates/common/.agents/skills/funpixel-gdd/SKILL.md +116 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/as-built.md +40 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/design-measures.md +24 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/design-note.md +88 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/experience.md +92 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/first-look.md +226 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/floors.md +62 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/frame.md +75 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/gameplay-contract.md +81 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/gdd-template.md +417 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-card.md +109 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-platformer.md +159 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-puzzle.md +145 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-racing.md +137 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-rpg.md +125 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-shooter.md +128 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-simulation.md +112 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-strategy.md +116 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/genre-survival.md +122 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/in-the-loop.md +106 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/invent-first.md +131 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/level-and-fun.md +112 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/pages.md +47 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/plan-at-size.md +140 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/production-tiers.md +117 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/sections.md +148 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/spec-folder.md +131 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/start.md +110 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/starters.md +175 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/the-path.md +133 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/track.md +29 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/world-and-identity.md +165 -0
- package/templates/common/.agents/skills/funpixel-gdd/references/worth.md +74 -0
- package/templates/common/.agents/skills/funpixel-mobile-ui/SKILL.md +107 -0
- package/templates/common/.agents/skills/funpixel-mobile-ui/references/contrast.md +123 -0
- package/templates/common/.agents/skills/funpixel-mobile-ui/references/hud-and-title.md +108 -0
- package/templates/common/.agents/skills/funpixel-mobile-ui/references/hud-genres.md +124 -0
- package/templates/common/.agents/skills/funpixel-mobile-ui/references/phone-check.md +156 -0
- package/templates/common/.agents/skills/funpixel-mobile-ui/references/recipes.md +279 -0
- package/templates/common/.agents/skills/funpixel-mobile-ui/references/restyle-ui.md +229 -0
- package/templates/common/.agents/skills/funpixel-mobile-ui/references/unity.md +61 -0
- package/templates/common/.agents/skills/funpixel-publish/SKILL.md +109 -0
- package/templates/common/.agents/skills/funpixel-publish/references/compose.md +113 -0
- package/templates/common/.agents/skills/funpixel-publish/references/motion.md +120 -0
- package/templates/common/.agents/skills/funpixel-publish/references/networks.md +75 -0
- package/templates/common/.agents/skills/funpixel-publish/references/other-hosts.md +65 -0
- package/templates/common/.agents/skills/funpixel-publish/references/playable-ad.md +90 -0
- package/templates/common/.agents/skills/funpixel-publish/references/server-build.md +85 -0
- package/templates/common/.agents/skills/funpixel-publish/references/store-shots.md +85 -0
- package/templates/common/.agents/skills/funpixel-publish/references/trailer.md +55 -0
- package/templates/common/.agents/skills/funpixel-publish/references/what-ships.md +30 -0
- package/templates/common/.agents/skills/funpixel-store/SKILL.md +81 -0
- package/templates/common/.agents/skills/funpixel-store/references/app-store.md +73 -0
- package/templates/common/.agents/skills/funpixel-store/references/google-play.md +141 -0
- package/templates/common/.agents/skills/funpixel-store/references/ios-release.md +63 -0
- package/templates/common/.agents/skills/funpixel-store/references/money.md +66 -0
- package/templates/common/.agents/skills/funpixel-store/references/purchases-and-review.md +74 -0
- package/templates/common/.agents/skills/funpixel-store/references/readiness-page.md +24 -0
- package/templates/common/.agents/skills/funpixel-store/references/readiness.md +107 -0
- package/templates/common/.agents/skills/funpixel-store/references/steam.md +38 -0
- package/templates/common/.agents/skills/funpixel-store/references/unity-store.md +55 -0
- package/templates/common/.agents/skills/funpixel-store/references/web-portals.md +43 -0
- package/templates/common/.agents/skills/funpixel-unity-game/SKILL.md +103 -0
- package/templates/common/.agents/skills/funpixel-unity-game/references/agent-ops.md +54 -0
- package/templates/common/.agents/skills/funpixel-unity-game/references/fixes.md +40 -0
- package/templates/common/.agents/skills/funpixel-unity-game/references/from-a-web-game.md +108 -0
- package/templates/common/.agents/skills/funpixel-unity-game/references/handing-off.md +42 -0
- package/templates/common/.agents/skills/funpixel-unity-game/references/performance.md +59 -0
- package/templates/common/.agents/skills/funpixel-unity-game/references/probe.md +80 -0
- package/templates/common/.agents/skills/funpixel-unity-game/references/shared-mac.md +121 -0
- package/templates/common/.agents/skills/funpixel-unity-game/references/traps.md +108 -0
- package/templates/common/.agents/skills/funpixel-verify/SKILL.md +109 -0
- package/templates/common/.agents/skills/funpixel-verify/references/actors.md +94 -0
- package/templates/common/.agents/skills/funpixel-verify/references/bar.md +62 -0
- package/templates/common/.agents/skills/funpixel-verify/references/checks.md +69 -0
- package/templates/common/.agents/skills/funpixel-verify/references/experience.md +67 -0
- package/templates/common/.agents/skills/funpixel-verify/references/eyes.md +54 -0
- package/templates/common/.agents/skills/funpixel-verify/references/fidelity.md +126 -0
- package/templates/common/.agents/skills/funpixel-verify/references/hit-bar.md +31 -0
- package/templates/common/.agents/skills/funpixel-verify/references/journeys.md +77 -0
- package/templates/common/.agents/skills/funpixel-verify/references/mobile-qa.md +123 -0
- package/templates/common/.agents/skills/funpixel-verify/references/playtest.md +161 -0
- package/templates/common/.agents/skills/funpixel-verify/references/review.md +105 -0
- package/templates/common/.agents/skills/funpixel-verify/references/rubric.md +67 -0
- package/templates/common/.agents/skills/funpixel-verify/references/scenes.md +49 -0
- package/templates/common/.agents/skills/funpixel-verify/references/unity.md +60 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/SKILL.md +99 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/references/atmosphere.md +208 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/references/forged-world.md +79 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/references/living-world.md +237 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/references/opening-and-chapters.md +215 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/references/shelf.md +80 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/references/story-at-size.md +159 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/references/voice.md +175 -0
- package/templates/common/.agents/skills/funpixel-world-and-story/references/world-kit.md +154 -0
- package/templates/common/.claude/settings.json +3 -0
- package/templates/common/.harnessignore +28 -0
- package/templates/common/AGENTS.md +135 -0
- package/templates/common/CLAUDE.md +1 -0
- package/templates/common/assets/assets.example.json +9 -0
- package/templates/common/index.html +13 -0
- package/templates/common/src/art/files.mjs +27 -0
- package/templates/common/src/assets.ts +62 -0
- package/templates/common/src/beat.ts +50 -0
- package/templates/common/src/characters.ts +54 -0
- package/templates/common/src/expose.ts +63 -0
- package/templates/common/src/feel.ts +78 -0
- package/templates/common/src/fpx-hooks.ts +46 -0
- package/templates/common/src/frame.ts +63 -0
- package/templates/common/src/grade.ts +47 -0
- package/templates/common/src/hud-kit.css +29 -0
- package/templates/common/src/hud-kit.tsx +85 -0
- package/templates/common/src/hud.tsx +55 -0
- package/templates/common/src/icons.tsx +35 -0
- package/templates/common/src/input.ts +70 -0
- package/templates/common/src/juice.ts +92 -0
- package/templates/common/src/levels.ts +43 -0
- package/templates/common/src/living.ts +91 -0
- package/templates/common/src/look.json +19 -0
- package/templates/common/src/look.ts +54 -0
- package/templates/common/src/main.tsx +31 -0
- package/templates/common/src/markers.ts +60 -0
- package/templates/common/src/motion-sample.ts +71 -0
- package/templates/common/src/motion.ts +92 -0
- package/templates/common/src/pin.ts +32 -0
- package/templates/common/src/platform.ts +67 -0
- package/templates/common/src/pose.ts +22 -0
- package/templates/common/src/probe-human.ts +29 -0
- package/templates/common/src/probe-kit.ts +99 -0
- package/templates/common/src/rules.ts +99 -0
- package/templates/common/src/save.ts +21 -0
- package/templates/common/src/screens.css +34 -0
- package/templates/common/src/screens.tsx +95 -0
- package/templates/common/src/selftests.ts +22 -0
- package/templates/common/src/session.ts +99 -0
- package/templates/common/src/sound.ts +85 -0
- package/templates/common/src/splash-funpixel/OFL.txt +94 -0
- package/templates/common/src/splash-funpixel/card.css +18 -0
- package/templates/common/src/splash-funpixel/card.tsx +22 -0
- package/templates/common/src/splash.css +15 -0
- package/templates/common/src/splash.tsx +86 -0
- package/templates/common/src/store.ts +68 -0
- package/templates/common/src/strike.ts +82 -0
- package/templates/common/src/styles.css +81 -0
- package/templates/common/src/toasts.ts +75 -0
- package/templates/common/src/world.ts +91 -0
- package/templates/common/test/feel.json +36 -0
- package/templates/common/test/platform.test.ts +42 -0
- package/templates/common/test/probes.ts +72 -0
- package/templates/common/test/rules.test.ts +88 -0
- package/templates/common/tsconfig.json +16 -0
- package/templates/common/vite.config.ts +6 -0
- package/templates/pixi/src/character.ts +63 -0
- package/templates/pixi/src/game.ts +99 -0
- package/templates/pixi/src/world-hud.ts +16 -0
- package/templates/spec/common/src/chapters.ts +97 -0
- package/templates/spec/common/src/levels.ts +68 -0
- package/templates/spec/common/src/probe-rooms.ts +63 -0
- package/templates/spec/common/src/room-map.tsx +30 -0
- package/templates/spec/common/src/tune.ts +93 -0
- package/templates/spec/common/test/rooms.test.ts +59 -0
- package/templates/spec/common/test/rooms.ts +53 -0
- package/templates/spec/three-world/test/rooms.ts +54 -0
- package/templates/three/src/character.ts +65 -0
- package/templates/three/src/game.ts +99 -0
- package/templates/three/src/world-hud.ts +22 -0
- package/templates/three-world/src/bot.ts +43 -0
- package/templates/three-world/src/budget.ts +73 -0
- package/templates/three-world/src/camera-rig.ts +99 -0
- package/templates/three-world/src/controls.tsx +49 -0
- package/templates/three-world/src/cutout-atlas.ts +26 -0
- package/templates/three-world/src/cutout-math.ts +47 -0
- package/templates/three-world/src/cutouts.ts +99 -0
- package/templates/three-world/src/dressing-math.ts +98 -0
- package/templates/three-world/src/dressing.ts +84 -0
- package/templates/three-world/src/expose.ts +82 -0
- package/templates/three-world/src/feel.ts +79 -0
- package/templates/three-world/src/game.ts +99 -0
- package/templates/three-world/src/hud.tsx +44 -0
- package/templates/three-world/src/icons.tsx +36 -0
- package/templates/three-world/src/input.ts +73 -0
- package/templates/three-world/src/juice.ts +91 -0
- package/templates/three-world/src/layout.ts +73 -0
- package/templates/three-world/src/light-math.ts +78 -0
- package/templates/three-world/src/light.ts +77 -0
- package/templates/three-world/src/look.json +30 -0
- package/templates/three-world/src/main.tsx +38 -0
- package/templates/three-world/src/models.ts +62 -0
- package/templates/three-world/src/palette.ts +21 -0
- package/templates/three-world/src/places.json +50 -0
- package/templates/three-world/src/places.ts +56 -0
- package/templates/three-world/src/pose.ts +22 -0
- package/templates/three-world/src/post.ts +47 -0
- package/templates/three-world/src/rest-math.ts +29 -0
- package/templates/three-world/src/rules.ts +89 -0
- package/templates/three-world/src/screens.css +45 -0
- package/templates/three-world/src/screens.tsx +96 -0
- package/templates/three-world/src/selftests.ts +25 -0
- package/templates/three-world/src/session.ts +99 -0
- package/templates/three-world/src/shots.ts +59 -0
- package/templates/three-world/src/sky.ts +48 -0
- package/templates/three-world/src/stage.ts +83 -0
- package/templates/three-world/src/styles.css +95 -0
- package/templates/three-world/src/surfaces.ts +55 -0
- package/templates/three-world/src/world.ts +70 -0
- package/templates/three-world/test/feel.json +29 -0
- package/templates/three-world/test/probes.ts +65 -0
- package/templates/three-world/test/resolve.mjs +13 -0
- package/templates/three-world/test/rules.test.ts +81 -0
- package/unity/com.funpixel.probe/Editor/Funpixel.Probe.Editor.asmdef +16 -0
- package/unity/com.funpixel.probe/Editor/Funpixel.Probe.Editor.asmdef.meta +7 -0
- package/unity/com.funpixel.probe/Editor/ProbeBuild.cs +97 -0
- package/unity/com.funpixel.probe/Editor/ProbeBuild.cs.meta +11 -0
- package/unity/com.funpixel.probe/Editor/ReleaseGuard.cs +23 -0
- package/unity/com.funpixel.probe/Editor/ReleaseGuard.cs.meta +11 -0
- package/unity/com.funpixel.probe/Editor.meta +8 -0
- package/unity/com.funpixel.probe/Runtime/Api/Funpixel.Probe.asmdef +14 -0
- package/unity/com.funpixel.probe/Runtime/Api/Funpixel.Probe.asmdef.meta +7 -0
- package/unity/com.funpixel.probe/Runtime/Api/FunpixelProbe.cs +146 -0
- package/unity/com.funpixel.probe/Runtime/Api/FunpixelProbe.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Api.meta +8 -0
- package/unity/com.funpixel.probe/Runtime/Player/Args.cs +87 -0
- package/unity/com.funpixel.probe/Runtime/Player/Args.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player/Boot.cs +67 -0
- package/unity/com.funpixel.probe/Runtime/Player/Boot.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player/Bridge.cs +559 -0
- package/unity/com.funpixel.probe/Runtime/Player/Bridge.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player/Capture.cs +145 -0
- package/unity/com.funpixel.probe/Runtime/Player/Capture.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player/Funpixel.Probe.Player.asmdef +32 -0
- package/unity/com.funpixel.probe/Runtime/Player/Funpixel.Probe.Player.asmdef.meta +7 -0
- package/unity/com.funpixel.probe/Runtime/Player/Inject.cs +127 -0
- package/unity/com.funpixel.probe/Runtime/Player/Inject.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player/Json.cs +246 -0
- package/unity/com.funpixel.probe/Runtime/Player/Json.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player/Probe.cs +194 -0
- package/unity/com.funpixel.probe/Runtime/Player/Probe.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player/Stats.cs +266 -0
- package/unity/com.funpixel.probe/Runtime/Player/Stats.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player/UiTargets.cs +134 -0
- package/unity/com.funpixel.probe/Runtime/Player/UiTargets.cs.meta +11 -0
- package/unity/com.funpixel.probe/Runtime/Player.meta +8 -0
- package/unity/com.funpixel.probe/Runtime/link.xml +7 -0
- package/unity/com.funpixel.probe/Runtime/link.xml.meta +7 -0
- package/unity/com.funpixel.probe/Runtime.meta +8 -0
- package/unity/com.funpixel.probe/Tests/Editor/Funpixel.Probe.Tests.asmdef +25 -0
- package/unity/com.funpixel.probe/Tests/Editor/Funpixel.Probe.Tests.asmdef.meta +7 -0
- package/unity/com.funpixel.probe/Tests/Editor/StatsTests.cs +147 -0
- package/unity/com.funpixel.probe/Tests/Editor/StatsTests.cs.meta +11 -0
- package/unity/com.funpixel.probe/Tests/Editor/WireTests.cs +86 -0
- package/unity/com.funpixel.probe/Tests/Editor/WireTests.cs.meta +11 -0
- package/unity/com.funpixel.probe/Tests/Editor.meta +8 -0
- package/unity/com.funpixel.probe/Tests.meta +8 -0
- package/unity/com.funpixel.probe/package.json +14 -0
- package/unity/com.funpixel.probe/package.json.meta +7 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var FunpixelKapture=function(t){"use strict";function e(t){const e=Object.create(null);try{if(!t||"object"!=typeof t)return e;for(const[n,r]of Object.entries(t)){if(!n)continue;if(!r||"object"!=typeof r)continue;const t=r;"function"==typeof t.enter&&(e[n]={enter:t.enter,after:"string"==typeof t.after?t.after:void 0,motion:!0===t.motion})}}catch{}return e}function n(t){return Object.entries(t).map(([t,e])=>({id:t,after:e.after,motion:!0===e.motion}))}let r=0,o=!1;function i(){if(o)return;o=!0;const t=()=>{try{r=performance.now()}catch{}try{requestAnimationFrame(t)}catch{}};try{requestAnimationFrame(t)}catch{o=!1}}function c(){try{let t=0;const e=document.images;for(let n=0;n<e.length;n++)e[n].complete||t++;return t}catch{return 0}}function s(){try{const t=document.fonts;return t&&"loading"===t.status?1:0}catch{return 0}}function a(t){try{const e=t??performance.now();return r>0&&e-r<500}catch{return!1}}function u(t){const e=c(),n=s(),r=a();return{ok:0===e&&0===n&&r,pendingImages:e,pendingFonts:n,rafAlive:r,errors:t}}function f(t=5e3){return new Promise(e=>{const n=Date.now();let r=0;const o=()=>{try{if(0===c()&&0===s()?r++:r=0,r>=2)return e(!0);if(Date.now()-n>t)return e(!1);requestAnimationFrame(o)}catch{e(!1)}};try{requestAnimationFrame(o)}catch{e(!1)}})}const d=new Map;let l="__boot__",w=!1;function _(t){try{let e=d.get(l);if(e||(e=[],d.set(l,e)),e.length>=8)return;e.includes(t)||e.push(t)}catch{}}function h(){if(!w){w=!0;try{window.addEventListener("error",t=>{const e=t.error;_(e?.stack?String(e.stack).split("\n")[0]:String(t.message))},!0),window.addEventListener("unhandledrejection",t=>{const e=t.reason;_("Unhandled rejection: "+(e&&e.message?e.message:String(t.reason)))},!0);const t=console.error.bind(console);console.error=(...e)=>{try{_(e.map(t=>String(t)).join(" "))}catch{}t(...e)}}catch{w=!1}}}function g(t){l=t,d.set(t,[])}function y(t){return(d.get(t)??[]).slice()}function p(){return y(l)}function m(){return e(window.__FPX_VIEWS__)}function v(t,e){const n=[],r=new Set;let o=e;for(;o&&t[o]&&!r.has(o)&&n.length<4;)r.add(o),n.unshift(o),o=t[o].after;return n}async function A(t){try{const e=m();if(!e[t])return{ok:!1,view:t,settle:u([]),error:"not declared"};g(t);for(const n of v(e,t))try{await e[n].enter()}catch(e){return{ok:!1,view:t,settle:u(y(t)),error:"enter("+n+") threw: "+String(e)}}const n=await f(),r=u(y(t));return n?{ok:!0,view:t,settle:r}:{ok:!1,view:t,settle:r,error:"settle timeout"}}catch(e){return{ok:!1,view:t,settle:u([]),error:String(e)}}}function E(){try{if(window.__FPX_KAPTURE__&&1===window.__FPX_KAPTURE__.v)return;window.__FPX_KAPTURE__={v:1,list:()=>{try{return n(m())}catch{return[]}},goto:t=>A(t),settled:()=>u(p())}}catch{}}const F="funpixel-kapture";function P(t){return{source:F,type:"KAPTURE_VIEWS",v:1,views:t}}function b(t,e){return{source:F,type:"KAPTURE_GOTO_ACK",corrId:t,ok:e.ok,settle:e.settle}}function k(t){if(!t||"object"!=typeof t)return null;const e=t;return"KAPTURE_GOTO"!==e.type||"string"!=typeof e.id||0===e.id.length||e.id.length>64||"string"!=typeof e.corrId||0===e.corrId.length||e.corrId.length>64?null:{type:"KAPTURE_GOTO",id:e.id,corrId:e.corrId}}function I(t){try{window.parent.postMessage(t,"*")}catch{}}function S(){try{if(window.__FPX_KAPTURE__)return;h(),g("__boot__"),i(),E(),function(){let t=0;const r=()=>{try{const o=n(e(window.__FPX_VIEWS__));if(o.length>0||t>=40)return void I(P(o));t++,setTimeout(r,250)}catch{}};r()}(),function(){try{window.addEventListener("message",t=>{try{if(t.source!==window.parent)return;const e=k(t.data);if(!e)return;A(e.id).then(t=>I(b(e.corrId,t)))}catch{}})}catch{}}()}catch{}}return S(),t.SOURCE=F,t.beginView=g,t.boot=S,t.currentErrors=p,t.errorsFor=y,t.gotoAck=b,t.gotoView=A,t.install=h,t.installDriver=E,t.parseGoto=k,t.pendingFonts=s,t.pendingImages=c,t.rafAlive=a,t.readViews=e,t.resolveChain=v,t.snapshot=u,t.startHeartbeat=i,t.toMeta=n,t.viewsMessage=P,t.waitForSettle=f,t}({});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var FunpixelProfiler=function(e){"use strict";const t="🎬",i="🎨",s="💾",r="🖥️",n="✨";const a={sampleInterval:1e3,bufferSize:3e4,thresholds:{fps:{green:55,yellow:30},frameTime:{green:18,yellow:33},drawCalls:{green:200,yellow:1e3},triangles:{green:2e5,yellow:1e6},textureMemoryMB:{green:100,yellow:500},geometryMemoryMB:{green:50,yellow:200}},debug:!1};class o{buf;head=0;size=0;capacity;constructor(e){if(e<1)throw new Error("TimeWindowedRingBuffer capacity must be >= 1");this.capacity=e,this.buf=new Array(e)}push(e){this.buf[this.head]=e,this.head=(this.head+1)%this.capacity,this.size<this.capacity&&(this.size+=1)}sliceSince(e){if(0===this.size)return[];const t=[],i=(this.head-this.size+this.capacity)%this.capacity;for(let s=0;s<this.size;s++){const r=(i+s)%this.capacity,n=this.buf[r];n&&n.timestamp>=e&&t.push(n)}return t}clear(){this.head=0,this.size=0}get length(){return this.size}}function l(e,t){if(0===e.length)return 0;if(1===e.length)return e[0];const i=[...e].sort((e,t)=>e-t),s=t/100*(i.length-1),r=Math.floor(s),n=Math.ceil(s);if(r===n)return i[r];const a=s-r;return i[r]*(1-a)+i[n]*a}class g{engine;handlers=new Map;isListening=!1;boundHandleMessage;constructor(e){this.engine=e,this.boundHandleMessage=this.handleMessage.bind(this)}send(e){const t={...e,engine:this.engine,source:"funpixel-profiler"};try{window.parent.postMessage(t,"*")}catch{}}on(e,t){const i=this.handlers.get(e)||[];i.push(t),this.handlers.set(e,i),this.isListening||this.startListening()}off(e,t){const i=this.handlers.get(e)||[],s=i.indexOf(t);s>-1&&i.splice(s,1)}startListening(){this.isListening||(this.isListening=!0,window.addEventListener("message",this.boundHandleMessage))}handleMessage(e){const t=e.data;if(!t?.type)return;const i=this.normalizeMessageType(t.type);if(!i)return;const s=this.handlers.get(i);if(s){const e={type:i,config:t.config};for(const t of s)t(e)}}normalizeMessageType(e){switch(e){case"PROFILER_START":case"START_PROFILER":return"PROFILER_START";case"PROFILER_STOP":case"STOP_PROFILER":return"PROFILER_STOP";case"PROFILER_REQUEST_SNAPSHOT":case"REQUEST_PROFILER_SNAPSHOT":return"PROFILER_REQUEST_SNAPSHOT";case"PROFILER_SET_CONFIG":case"SET_PROFILER_CONFIG":return"PROFILER_SET_CONFIG";default:return null}}destroy(){this.isListening&&(window.removeEventListener("message",this.boundHandleMessage),this.isListening=!1),this.handlers.clear()}}class h{gl=null;ext=null;isWebGL2=!1;_available=!1;currentQuery=null;pendingQuery=null;lastResult=null;frameActive=!1;constructor(e){e&&(this.gl=e,this.isWebGL2="createQuery"in e,this.initExtension())}initExtension(){if(this.gl)try{this.isWebGL2&&(this.ext=this.gl.getExtension("EXT_disjoint_timer_query_webgl2")),this.ext||(this.ext=this.gl.getExtension("EXT_disjoint_timer_query")),this.ext&&(this._available=!0)}catch{this._available=!1}}get available(){return this._available}beginFrame(){if(this._available&&this.gl&&this.ext&&!this.frameActive){this.resolvePendingQuery(),this.currentQuery&&(this.pendingQuery=this.currentQuery);try{this.isWebGL2?(this.currentQuery=this.gl.createQuery(),this.currentQuery&&(this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT,this.currentQuery),this.frameActive=!0)):(this.currentQuery=this.ext.createQueryEXT(),this.currentQuery&&(this.ext.beginQueryEXT(this.ext.TIME_ELAPSED_EXT,this.currentQuery),this.frameActive=!0))}catch{this._available=!1}}}endFrame(){if(this._available&&this.gl&&this.ext&&this.frameActive){try{this.isWebGL2?this.gl.endQuery(this.ext.TIME_ELAPSED_EXT):this.ext.endQueryEXT(this.ext.TIME_ELAPSED_EXT)}catch{this._available=!1}this.frameActive=!1}}getResult(){return this.resolvePendingQuery(),this.lastResult}resolvePendingQuery(){if(this.pendingQuery&&this.gl&&this.ext)try{if(this.gl.getParameter(this.ext.GPU_DISJOINT_EXT))return this.cleanupQuery(this.pendingQuery),this.pendingQuery=null,void(this.lastResult=null);let e,t;if(this.isWebGL2){const i=this.gl;e=i.getQueryParameter(this.pendingQuery,i.QUERY_RESULT_AVAILABLE),e&&(t=i.getQueryParameter(this.pendingQuery,i.QUERY_RESULT))}else e=this.ext.getQueryObjectEXT(this.pendingQuery,this.ext.QUERY_RESULT_AVAILABLE_EXT),e&&(t=this.ext.getQueryObjectEXT(this.pendingQuery,this.ext.QUERY_RESULT_EXT));e&&"number"==typeof t&&(this.lastResult=t/1e6,this.cleanupQuery(this.pendingQuery),this.pendingQuery=null)}catch{this.pendingQuery&&this.cleanupQuery(this.pendingQuery),this.pendingQuery=null,this.lastResult=null}}cleanupQuery(e){try{this.isWebGL2?this.gl.deleteQuery(e):this.ext&&this.ext.deleteQueryEXT(e)}catch{}}destroy(){this.currentQuery&&(this.frameActive&&this.endFrame(),this.cleanupQuery(this.currentQuery),this.currentQuery=null),this.pendingQuery&&(this.cleanupQuery(this.pendingQuery),this.pendingQuery=null),this._available=!1}}class c{messages;ringBuffer;gpuTimer=null;config;isRunning=!1;profilingStartTime=0;lastSampleSentTime=0;lastFrameTimestamp=0;accumulatedCpuTime=0;sampleAccumulator=[];warnings=[];warningHashes=new Set;sceneStatsCache=null;sceneStatsCacheTime=0;SCENE_STATS_CACHE_MS=200;pendingFrameEmit=!1;frameRenderStats={};stateChangeCounters={programSwitches:0,textureSwitches:0,fboSwitches:0};lastFrameStateChanges={programSwitches:0,textureSwitches:0,fboSwitches:0};originalUseProgram=null;originalBindTexture=null;originalBindFramebuffer=null;lastComputedScore=-1;loafObserver=null;loafEntries=[];constructor(e={}){this.config={...a,...e},this.ringBuffer=new o(this.config.bufferSize)}init(){this.messages=new g(this.engineType),this.setupMessageHandlers(),this.waitForEngine(),this.exposeGlobalAPI(),this.log("Profiler initialized")}waitForEngine(){const e=Date.now();let t=!1;const i=()=>{this.isEngineReady()?this.onEngineReady():(!t&&Date.now()-e>15e3&&(t=!0,this.log("Engine not detected yet — continuing to poll slowly (menu-first game?)","warn")),setTimeout(i,t?2e3:100))};setTimeout(i,100)}onEngineReady(){this.log("Engine detected");const e=this.getGLContext();e&&(this.gpuTimer=new h(e),this.gpuTimer.available&&this.log("GPU timer query available")),this.messages.send({type:"PROFILER_READY"}),this.messages.send({type:"PROFILER_ENGINE_DETECTED",engine:this.engineType}),this.start()}setupMessageHandlers(){this.messages.on("PROFILER_START",e=>{e.config&&this.updateConfig(e.config),this.start()}),this.messages.on("PROFILER_STOP",()=>{this.stop()}),this.messages.on("PROFILER_REQUEST_SNAPSHOT",()=>{const e=this.buildSnapshot();this.messages.send({type:"PROFILER_SNAPSHOT",snapshot:e})}),this.messages.on("PROFILER_SET_CONFIG",e=>{e.config&&this.updateConfig(e.config)})}start(){this.isRunning||(this.isRunning=!0,this.profilingStartTime=performance.now(),this.lastSampleSentTime=performance.now(),this.lastFrameTimestamp=0,this.accumulatedCpuTime=0,this.frameRenderStats={},this.pendingFrameEmit=!1,this.sampleAccumulator=[],this.warnings=[],this.warningHashes.clear(),this.hookRenderLoop(),this.hookStateChangeTracking(),this.startLoafObserver(),this.log("Profiling started"))}stop(){this.isRunning&&(this.isRunning=!1,this.unhookRenderLoop(),this.unhookStateChangeTracking(),this.stopLoafObserver(),this.log("Profiling stopped"))}onFrameEnd(e){if(!this.isRunning)return;let t;this.accumulatedCpuTime+=e;try{t=this.collectRenderStats()}catch{t={}}const i=this.frameRenderStats;i.drawCalls=(i.drawCalls||0)+(t.drawCalls||0),i.triangles=(i.triangles||0)+(t.triangles||0),i.points=(i.points||0)+(t.points||0),i.lines=(i.lines||0)+(t.lines||0),void 0!==t.textureCount&&(i.textureCount=t.textureCount),void 0!==t.textureBytes&&(i.textureBytes=t.textureBytes),void 0!==t.geometryCount&&(i.geometryCount=t.geometryCount),void 0!==t.geometryBytes&&(i.geometryBytes=t.geometryBytes),void 0!==t.programCount&&(i.programCount=t.programCount),this.pendingFrameEmit||(this.pendingFrameEmit=!0,queueMicrotask(()=>this.emitFrameSample()))}emitFrameSample(){if(this.pendingFrameEmit=!1,!this.isRunning)return;const e=performance.now(),t=this.lastFrameTimestamp>0?e-this.lastFrameTimestamp:16.67;this.lastFrameTimestamp=e,this.lastFrameStateChanges={...this.stateChangeCounters},this.stateChangeCounters.programSwitches=0,this.stateChangeCounters.textureSwitches=0,this.stateChangeCounters.fboSwitches=0;const i=this.buildFrameSample(t,this.accumulatedCpuTime,this.frameRenderStats);if(this.accumulatedCpuTime=0,this.frameRenderStats={},this.ringBuffer.push(i),this.sampleAccumulator.push(i),e-this.lastSampleSentTime>=this.config.sampleInterval){const t=this.aggregateStats(this.sampleAccumulator),i=this.detectWarnings(t);this.messages.send({type:"PROFILER_SAMPLE",stats:t,warnings:i});for(const e of i)this.messages.send({type:"PROFILER_WARNING",warning:e});this.sampleAccumulator=[],this.lastSampleSentTime=e}}buildFrameSample(e,t,i){const s=this.getSceneStatsCached(),r=this.gpuTimer?.getResult()??null;let n=null,a=null;return performance.memory&&(n=performance.memory.usedJSHeapSize,a=performance.memory.totalJSHeapSize),{timestamp:performance.now(),frameTime:e,fps:e>0?1e3/e:0,cpuTime:t,drawCalls:i.drawCalls||0,triangles:i.triangles||0,points:i.points||0,lines:i.lines||0,textureCount:i.textureCount||0,textureBytes:i.textureBytes||0,geometryCount:i.geometryCount||0,geometryBytes:i.geometryBytes||0,programCount:i.programCount||0,programSwitches:this.lastFrameStateChanges.programSwitches,textureSwitches:this.lastFrameStateChanges.textureSwitches,fboSwitches:this.lastFrameStateChanges.fboSwitches,totalObjects:s.totalObjects,visibleObjects:s.visibleObjects,lightsCount:s.lightsCount,camerasCount:s.camerasCount,gpuTime:r,jsHeapUsed:n,jsHeapTotal:a}}getSceneStatsCached(){const e=performance.now();if(!this.sceneStatsCache||e-this.sceneStatsCacheTime>this.SCENE_STATS_CACHE_MS){try{this.sceneStatsCache=this.collectSceneStats()}catch{this.sceneStatsCache={totalObjects:0,visibleObjects:0,lightsCount:0,camerasCount:0}}this.sceneStatsCacheTime=e}return this.sceneStatsCache}aggregateStats(e){if(0===e.length)return this.emptyStats();const t=e[e.length-1],i=e.map(e=>e.fps),s=e.map(e=>e.frameTime),r=e.map(e=>e.cpuTime),n=this.computeMinMaxAvg(r),a={fps:this.computeMinMaxAvg(i),frameTime:this.computeMinMaxAvg(s),cpuTime:n,drawCalls:t.drawCalls,triangles:t.triangles,points:t.points,lines:t.lines,textureCount:t.textureCount,textureMemoryMB:t.textureBytes/1024/1024,geometryCount:t.geometryCount,geometryMemoryMB:t.geometryBytes/1024/1024,programCount:t.programCount,programSwitches:t.programSwitches,textureSwitches:t.textureSwitches,fboSwitches:t.fboSwitches,totalObjects:t.totalObjects,visibleObjects:t.visibleObjects,lightsCount:t.lightsCount,camerasCount:t.camerasCount,gpuTime:t.gpuTime,jsHeapUsedMB:null!==t.jsHeapUsed?t.jsHeapUsed/1024/1024:null,framePacing:this.computeFramePacing(e),bottleneck:this.classifyBottleneck(n.avg,t.gpuTime,this.computeMinMaxAvg(s).avg,t.drawCalls),sampleCount:e.length};return a.performanceScore=this.computePerformanceScore(a),a}computeMinMaxAvg(e){let t=1/0,i=-1/0,s=0;for(const r of e)r<t&&(t=r),r>i&&(i=r),s+=r;return{current:e[e.length-1],min:t,max:i,avg:s/e.length}}emptyStats(){return{fps:{current:0,min:0,max:0,avg:0},frameTime:{current:0,min:0,max:0,avg:0},cpuTime:{current:0,min:0,max:0,avg:0},drawCalls:0,triangles:0,points:0,lines:0,textureCount:0,textureMemoryMB:0,geometryCount:0,geometryMemoryMB:0,programCount:0,programSwitches:0,textureSwitches:0,fboSwitches:0,totalObjects:0,visibleObjects:0,lightsCount:0,camerasCount:0,gpuTime:null,jsHeapUsedMB:null,framePacing:this.emptyFramePacing(),bottleneck:{type:"unknown",description:"Insufficient data",confidence:0,suggestion:""},sampleCount:0}}detectWarnings(e){const t=[],i=performance.now(),s=this.config.thresholds;return e.fps.avg>0&&e.fps.avg<s.fps.yellow&&this.addWarning(t,"fps",e.fps.avg<s.fps.yellow/2?"critical":"warning",`Average FPS is ${e.fps.avg.toFixed(1)} (below ${s.fps.yellow})`,e.fps.avg,s.fps.yellow,"Consider reducing draw calls, lowering resolution, or simplifying geometry. Use LOD (Level of Detail) for distant objects.",i),e.frameTime.avg>s.frameTime.yellow&&this.addWarning(t,"frame_time",e.frameTime.avg>2*s.frameTime.yellow?"critical":"warning",`Average frame time is ${e.frameTime.avg.toFixed(1)}ms (above ${s.frameTime.yellow}ms)`,e.frameTime.avg,s.frameTime.yellow,"Profile individual systems. Common causes: expensive shaders, too many lights with shadows, unoptimized physics, GC pauses.",i),e.drawCalls>s.drawCalls.yellow&&this.addWarning(t,"draw_calls",e.drawCalls>3*s.drawCalls.yellow?"critical":"warning",`Draw calls: ${e.drawCalls.toLocaleString()} (above ${s.drawCalls.yellow})`,e.drawCalls,s.drawCalls.yellow,"Batch similar materials, use instanced rendering (InstancedMesh/InstancedBufferGeometry), merge static geometry, use texture atlases.",i),e.triangles>s.triangles.yellow&&this.addWarning(t,"triangles",e.triangles>3*s.triangles.yellow?"critical":"warning",`Triangle count: ${e.triangles.toLocaleString()} (above ${s.triangles.yellow.toLocaleString()})`,e.triangles,s.triangles.yellow,"Use LOD, reduce polygon count on distant/small objects, enable frustum culling, consider simpler geometry for non-hero assets.",i),e.textureMemoryMB>s.textureMemoryMB.yellow&&this.addWarning(t,"texture_memory",e.textureMemoryMB>2*s.textureMemoryMB.yellow?"critical":"warning",`Texture memory: ${e.textureMemoryMB.toFixed(1)}MB (above ${s.textureMemoryMB.yellow}MB)`,e.textureMemoryMB,s.textureMemoryMB.yellow,"Use compressed textures (KTX2/Basis), reduce texture resolution, use power-of-2 sizes, share textures via atlases, dispose unused textures.",i),e.geometryMemoryMB>s.geometryMemoryMB.yellow&&this.addWarning(t,"geometry_memory",e.geometryMemoryMB>2*s.geometryMemoryMB.yellow?"critical":"warning",`Geometry memory: ${e.geometryMemoryMB.toFixed(1)}MB (above ${s.geometryMemoryMB.yellow}MB)`,e.geometryMemoryMB,s.geometryMemoryMB.yellow,"Share geometry between meshes, use BufferGeometry instead of Geometry, dispose unused geometries, use instancing for repeated shapes.",i),e.programCount>50&&this.addWarning(t,"shader_count","warning",`Shader programs: ${e.programCount} (many unique materials)`,e.programCount,50,"Reduce material variations, share materials between objects, consider using a single uber-shader with defines.",i),null!==e.gpuTime&&e.gpuTime>16&&this.addWarning(t,"gpu_time",e.gpuTime>33?"critical":"warning",`GPU time: ${e.gpuTime.toFixed(1)}ms (above 16ms budget)`,e.gpuTime,16,"Simplify shaders, reduce overdraw, lower shadow map resolution, use fewer real-time lights, consider baked lighting.",i),t}addWarning(e,t,i,s,r,n,a,o){const l=`${t}-${i}`;if(this.warningHashes.has(l))return;this.warningHashes.add(l);const g={id:`${t}-${Date.now()}`,severity:i,category:t,message:s,value:r,threshold:n,timestamp:o,suggestion:a};e.push(g),this.warnings.push(g)}computeFramePacing(e){if(e.length<2)return this.emptyFramePacing();const t=e.map(e=>e.frameTime),i=t.reduce((e,t)=>e+t,0)/t.length,s=t.reduce((e,t)=>e+(t-i)**2,0)/t.length,r=Math.sqrt(s),n=16.67*.1,a=t.filter(e=>Math.abs(e-16.67)<=n).length/t.length*100,o=2*i,l=t.filter(e=>e>o).length,g=e.length>0?(e[e.length-1].timestamp-e[0].timestamp)/1e3:1,h=g>0?l/g*60:0,c=1.5*i;let u=0,m=0;for(const e of t)e<=c?(m++,m>u&&(u=m)):m=0;const d=[0,0,0,0,0];for(const e of t)e<8?d[0]++:e<16?d[1]++:e<33?d[2]++:e<50?d[3]++:d[4]++;let p="stable";if(t.length>=120){const e=this.config.thresholds.frameTime.green,i=Math.floor(t.length/2),s=t.slice(0,i).sort((e,t)=>e-t),r=t.slice(i).sort((e,t)=>e-t),n=s[Math.floor(.99*s.length)]??0,a=r[Math.floor(.99*r.length)]??0;a>1.2*n&&a>e?p="degrading":a<.83*n&&n>e&&(p="improving")}return{frameTimeStdDev:r,consistencyPercent:a,janksPerMinute:h,longestSmoothStreak:u,histogram:d,varianceTrend:p}}emptyFramePacing(){return{frameTimeStdDev:0,consistencyPercent:0,janksPerMinute:0,longestSmoothStreak:0,histogram:[0,0,0,0,0],varianceTrend:"stable"}}classifyBottleneck(e,t,i,s){if(i<=0)return{type:"unknown",description:"Insufficient data",confidence:0,suggestion:""};if(i<=17.5&&e<12&&(null===t||t<12))return{type:"vsync-limited",description:"Running at vsync cap with headroom available",confidence:.9,suggestion:"Performance is good. Add more visual quality or increase simulation complexity."};const r=null!==t&&t>0;if(s>500&&e>10)return{type:"draw-call-bound",description:`${s} draw calls causing ${e.toFixed(1)}ms CPU overhead`,confidence:.85,suggestion:"Use InstancedMesh for repeated geometry, merge static meshes, share materials, use texture atlases."};if(r){const i=e/t;if(i>2)return{type:"cpu-bound",description:`CPU render time (${e.toFixed(1)}ms) is ${i.toFixed(1)}x GPU time (${t.toFixed(1)}ms)`,confidence:Math.min(.95,.6+.1*i),suggestion:"Reduce draw call count, simplify scene graph, optimize JavaScript logic, use web workers for heavy computation."};if(i<.5)return{type:"gpu-bound",description:`GPU time (${t.toFixed(1)}ms) is ${(1/i).toFixed(1)}x CPU time (${e.toFixed(1)}ms)`,confidence:Math.min(.95,.6+1/i*.1),suggestion:"Simplify shaders, reduce overdraw, lower shadow/texture resolution, use LOD, reduce post-processing passes."}}const n=r?Math.max(e,t):e;return i>2*n&&n>0?{type:"main-thread",description:`Frame time (${i.toFixed(1)}ms) is ${(i/n).toFixed(1)}x render time (${n.toFixed(1)}ms) — non-render work blocking`,confidence:.75,suggestion:"Profile JavaScript execution. Check for GC pauses, expensive physics, or layout thrashing between frames."}:{type:"balanced",description:"No single bottleneck detected — CPU and GPU load are balanced",confidence:.5,suggestion:"For further optimization, reduce scene complexity across the board or enable LOD."}}computePerformanceScore(e){const t=this.config.thresholds,i=e.fps.avg>=60?100:e.fps.avg>=30?50+(e.fps.avg-30)/30*50:Math.max(0,e.fps.avg/30*50),s=e.framePacing,r=Math.max(0,Math.min(100,.4*s.consistencyPercent+.3*Math.max(0,100-5*s.janksPerMinute)+.3*Math.max(0,100-10*s.frameTimeStdDev))),n=e.textureMemoryMB+e.geometryMemoryMB,a=t.textureMemoryMB.green,o=t.textureMemoryMB.yellow,l=n<=a?100:n<=o?50+50*(1-(n-a)/(o-a)):Math.max(0,50-(n-o)/o*50),g=((e.drawCalls<=t.drawCalls.green?100:e.drawCalls<=t.drawCalls.yellow?50+50*(1-(e.drawCalls-t.drawCalls.green)/(t.drawCalls.yellow-t.drawCalls.green)):Math.max(0,50-(e.drawCalls-t.drawCalls.yellow)/t.drawCalls.yellow*50))+(e.triangles<=t.triangles.green?100:e.triangles<=t.triangles.yellow?50+50*(1-(e.triangles-t.triangles.green)/(t.triangles.yellow-t.triangles.green)):Math.max(0,50-(e.triangles-t.triangles.yellow)/t.triangles.yellow*50)))/2,h=null===e.gpuTime||e.gpuTime<=8?100:e.gpuTime<=16?50+50*(1-(e.gpuTime-8)/8):Math.max(0,50-(e.gpuTime-16)/16*50);let c=Math.round(.4*i+.2*r+.15*l+.15*g+.1*h);c=Math.max(0,Math.min(100,c));const u=this.lastComputedScore<0?c:Math.round(.3*c+.7*this.lastComputedScore);this.lastComputedScore=u;const{grade:m,label:d}=function(e){return e>=90?{grade:"excellent",label:"Excellent"}:e>=70?{grade:"good",label:"Good"}:e>=50?{grade:"needs-work",label:"Needs Work"}:e>=30?{grade:"poor",label:"Poor"}:{grade:"critical",label:"Critical"}}(u);return{score:u,grade:m,gradeLabel:d,categories:{performance:Math.round(Math.max(0,Math.min(100,i))),smoothness:Math.round(Math.max(0,Math.min(100,r))),memory:Math.round(Math.max(0,Math.min(100,l))),rendering:Math.round(Math.max(0,Math.min(100,g))),gpu:Math.round(Math.max(0,Math.min(100,h)))},issues:this.generateIssues(e)}}generateIssues(e){const a=[],o=this.config.thresholds;e.fps.avg>0&&e.fps.avg<o.fps.yellow&&a.push({id:"fps-low",severity:e.fps.avg<o.fps.yellow/2?"critical":"warning",title:"Game is running slowly",description:e.fps.avg<20?"Your game is very slow. Try reducing the number of objects or simplifying visual effects.":"Your game could be smoother. Consider simplifying busy scenes.",category:"performance",icon:t}),e.drawCalls>o.drawCalls.yellow&&a.push({id:"draw-calls-high",severity:e.drawCalls>3*o.drawCalls.yellow?"critical":"warning",title:"Too many objects drawing separately",description:"Group similar objects together so the game does less work each frame. Objects with the same look can often be merged.",category:"rendering",icon:i}),e.triangles>o.triangles.yellow&&a.push({id:"triangles-high",severity:e.triangles>3*o.triangles.yellow?"critical":"warning",title:"Too much geometry detail",description:"Some models have more detail than needed. Use simpler models for background objects or things far from the camera.",category:"rendering",icon:i}),e.textureMemoryMB>o.textureMemoryMB.yellow&&a.push({id:"texture-memory-high",severity:e.textureMemoryMB>2*o.textureMemoryMB.yellow?"critical":"warning",title:"Large images using lots of memory",description:"Your textures are using a lot of GPU memory. Try compressing images, using smaller sizes, or sharing textures between objects.",category:"memory",icon:s}),e.geometryMemoryMB>o.geometryMemoryMB.yellow&&a.push({id:"geometry-memory-high",severity:e.geometryMemoryMB>2*o.geometryMemoryMB.yellow?"critical":"warning",title:"Too much 3D data in memory",description:"Your models are using lots of memory. Share shapes between similar objects and remove unused geometry.",category:"memory",icon:s}),null!==e.gpuTime&&e.gpuTime>16&&a.push({id:"gpu-time-high",severity:e.gpuTime>33?"critical":"warning",title:"GPU is working too hard",description:"Your graphics card is struggling. Simplify visual effects, reduce shadow quality, or lower the resolution.",category:"gpu",icon:r}),e.framePacing.janksPerMinute>10&&a.push({id:"jank-detected",severity:e.framePacing.janksPerMinute>30?"critical":"warning",title:"Game stutters occasionally",description:"Your game has noticeable hiccups. This can be caused by loading assets during gameplay or doing too much work at once.",category:"smoothness",icon:n});const l=this.config.thresholds.frameTime.green,g=this.getBurnRate(1e4,l),h=this.getBurnRate(6e4,l),c=this.getBurnRate(3e5,l);return g>=10&&h>=10?a.push({id:"performance-degrading",severity:"critical",title:"Game is stuttering right now",description:"Frames are missing the target budget at 10× the rate the SLO allows, both in the last 10 seconds and the last minute. Something is actively wrong — recent code changes or an expensive scene transition.",category:"smoothness",icon:n}):c>=3&&h>=3&&a.push({id:"performance-degrading",severity:"warning",title:"Performance getting worse over time",description:"Frames have been missing the target budget at 3× the rate the SLO allows, sustained over the last few minutes. Common causes: objects accumulating without cleanup, growing particle pool, forgotten event listeners.",category:"smoothness",icon:n}),a}hookStateChangeTracking(){const e=this.getGLContext();if(!e)return;const t=this.stateChangeCounters;this.originalUseProgram=e.useProgram.bind(e),e.useProgram=e=>(t.programSwitches++,this.originalUseProgram(e)),this.originalBindTexture=e.bindTexture.bind(e),e.bindTexture=(e,i)=>(t.textureSwitches++,this.originalBindTexture(e,i)),this.originalBindFramebuffer=e.bindFramebuffer.bind(e),e.bindFramebuffer=(e,i)=>(t.fboSwitches++,this.originalBindFramebuffer(e,i)),this.log("WebGL state change tracking active")}unhookStateChangeTracking(){const e=this.getGLContext();e&&(this.originalUseProgram&&(e.useProgram=this.originalUseProgram,this.originalUseProgram=null),this.originalBindTexture&&(e.bindTexture=this.originalBindTexture,this.originalBindTexture=null),this.originalBindFramebuffer&&(e.bindFramebuffer=this.originalBindFramebuffer,this.originalBindFramebuffer=null))}startLoafObserver(){try{if("undefined"==typeof PerformanceObserver)return;const e=PerformanceObserver.supportedEntryTypes;if(!e?.includes("long-animation-frame"))return;this.loafObserver=new PerformanceObserver(e=>{for(const t of e.getEntries()){const e=t;this.loafEntries.push({duration:e.duration,renderStart:e.renderStart??0,styleAndLayoutStart:e.styleAndLayoutStart??0,scripts:(e.scripts??[]).map(e=>({sourceURL:e.sourceURL||"unknown",invoker:e.invoker||"unknown",duration:e.duration})),timestamp:e.startTime}),this.loafEntries.length>50&&this.loafEntries.shift()}}),this.loafObserver.observe({type:"long-animation-frame",buffered:!1}),this.log("Long Animation Frame (LoAF) observer active")}catch{}}stopLoafObserver(){this.loafObserver&&(this.loafObserver.disconnect(),this.loafObserver=null)}getWindowedStats(e){const t=performance.now()-e,i=this.ringBuffer.sliceSince(t),s=i.length;if(0===s)return{windowMs:e,sampleCount:0,fps:{p50:0,p95:0,p99:0,min:0,max:0,avg:0},frameTime:{p50:0,p95:0,p99:0,max:0,avg:0},heap:{start:0,end:0,min:0,max:0,deltaPerMin:0}};const r=i.map(e=>e.fps),n=i.map(e=>e.frameTime),a=i.map(e=>(e.jsHeapUsed??0)/1048576),o=a[a.length-1]-a[0],g=(i[i.length-1].timestamp-i[0].timestamp)/6e4,h=(e,t)=>e+t;return{windowMs:e,sampleCount:s,fps:{p50:l(r,50),p95:l(r,95),p99:l(r,99),min:Math.min(...r),max:Math.max(...r),avg:r.reduce(h,0)/s},frameTime:{p50:l(n,50),p95:l(n,95),p99:l(n,99),max:Math.max(...n),avg:n.reduce(h,0)/s},heap:{start:a[0],end:a[a.length-1],min:Math.min(...a),max:Math.max(...a),deltaPerMin:g>0?o/g:0}}}getBurnRate(e,t,i=30){const s=performance.now()-e;return function(e,t,i=30){if(e.length<i)return 0;let s=0;for(const i of e)i.frameTime>t&&(s+=1);return s/e.length/.01}(this.ringBuffer.sliceSince(s),t,i)}buildSnapshot(){const e=this.ringBuffer.sliceSince(0),t=e.length>0?this.aggregateStats(e):this.emptyStats();this.warningHashes.clear(),this.warnings=[],this.detectWarnings(t);let i=this.getHotObjects()??void 0;if(i&&i.length>0){const e=t.triangles||1,s=t.drawCalls||1;i=i.map(t=>({...t,triangleBudgetPercent:t.triangles/e*100,drawCallBudgetPercent:t.drawCalls/s*100}))}return{engine:this.engineType,timestamp:Date.now(),profilingDuration:performance.now()-this.profilingStartTime,stats:t,recentSamples:e.slice(-30),warnings:[...this.warnings],engineInfo:this.getEngineInfo(),hotObjects:i,loafEntries:this.loafEntries.length>0?[...this.loafEntries]:void 0}}getReport(){return function(e){const{stats:t,warnings:i,engineInfo:s,hotObjects:r}=e,n=["## Performance Profile","",`**Engine:** ${s.name} ${s.version} | **Renderer:** ${s.renderer}`,`**Canvas:** ${s.canvasWidth}x${s.canvasHeight} @ ${s.pixelRatio}x DPR`,`**Profiling Duration:** ${(e.profilingDuration/1e3).toFixed(1)}s | **Samples:** ${e.recentSamples.length}`,"","### Frame Performance","| Metric | Current | Min | Max | Avg |","|--------|---------|-----|-----|-----|",`| FPS | ${t.fps.current.toFixed(1)} | ${t.fps.min.toFixed(1)} | ${t.fps.max.toFixed(1)} | ${t.fps.avg.toFixed(1)} |`,`| Frame Time (ms) | ${t.frameTime.current.toFixed(2)} | ${t.frameTime.min.toFixed(2)} | ${t.frameTime.max.toFixed(2)} | ${t.frameTime.avg.toFixed(2)} |`,`| CPU Render (ms) | ${t.cpuTime.current.toFixed(2)} | ${t.cpuTime.min.toFixed(2)} | ${t.cpuTime.max.toFixed(2)} | ${t.cpuTime.avg.toFixed(2)} |`,null!==t.gpuTime?`| GPU Time (ms) | ${t.gpuTime.toFixed(2)} | - | - | - |`:"","","### Render Pipeline","| Metric | Value |","|--------|-------|",`| Draw Calls | ${t.drawCalls.toLocaleString()} |`,`| Triangles | ${t.triangles.toLocaleString()} |`,`| Points | ${t.points.toLocaleString()} |`,`| Lines | ${t.lines.toLocaleString()} |`,`| Shader Programs | ${t.programCount} |`,"","### Memory","| Metric | Value |","|--------|-------|",`| Textures | ${t.textureCount} (${t.textureMemoryMB.toFixed(1)} MB) |`,`| Geometries | ${t.geometryCount} (${t.geometryMemoryMB.toFixed(1)} MB) |`,null!==t.jsHeapUsedMB?`| JS Heap | ${t.jsHeapUsedMB.toFixed(1)} MB |`:"","","### Scene Graph","| Metric | Value |","|--------|-------|",`| Total Objects | ${t.totalObjects.toLocaleString()} |`,`| Visible Objects | ${t.visibleObjects.toLocaleString()} |`,`| Lights | ${t.lightsCount} |`,`| Cameras | ${t.camerasCount} |`],a=t.framePacing;a&&n.push("### Frame Pacing (Smoothness)","| Metric | Value |","|--------|-------|",`| Consistency | ${a.consistencyPercent.toFixed(1)}% of frames on-target |`,`| Std Deviation | ${a.frameTimeStdDev.toFixed(2)}ms |`,`| Janks/min | ${a.janksPerMinute.toFixed(1)} |`,`| Longest Smooth Streak | ${a.longestSmoothStreak} frames |`,`| Variance Trend | ${a.varianceTrend} |`,`| Histogram (0-8/8-16/16-33/33-50/50+ms) | ${a.histogram.join(" / ")} |`,"");const o=t.bottleneck;if(o&&"unknown"!==o.type&&n.push("### Bottleneck Analysis",`- **Type:** ${o.type} (${(100*o.confidence).toFixed(0)}% confidence)`,`- **Analysis:** ${o.description}`,`- **Suggestion:** ${o.suggestion}`,""),(t.programSwitches>0||t.textureSwitches>0||t.fboSwitches>0)&&n.push("### WebGL State Changes (per frame)","| Metric | Value |","|--------|-------|",`| Program Switches | ${t.programSwitches} |`,`| Texture Binds | ${t.textureSwitches} |`,`| FBO Switches | ${t.fboSwitches} |`,""),(void 0!==s.antialias||s.shadows||s.toneMapping)&&(n.push("","### Renderer Settings"),void 0!==s.antialias&&n.push("- Antialiasing: "+(s.antialias?"ON":"OFF")),s.shadows&&n.push("- Shadows: "+(s.shadows.enabled?`ON (${s.shadows.type||"default"})`:"OFF")),s.toneMapping&&n.push(`- Tone Mapping: ${s.toneMapping}`),s.maxTextureSize&&n.push(`- Max Texture Size: ${s.maxTextureSize}`)),i.length>0){n.push("","### Performance Warnings");for(const e of i){const t="critical"===e.severity?"CRITICAL":"warning"===e.severity?"WARNING":"INFO";n.push(`- **[${t}]** ${e.message} (${e.value} > threshold ${e.threshold})`),n.push(` Suggestion: ${e.suggestion}`)}}if(r&&r.length>0){n.push("","### Top Objects by Cost"),n.push("| Object | Type | Triangles | Tri% | Draw Calls | DC% | Tex MB |"),n.push("|--------|------|-----------|------|------------|-----|--------|");for(const e of r.slice(0,10)){const t=void 0!==e.triangleBudgetPercent?`${e.triangleBudgetPercent.toFixed(1)}%`:"-",i=void 0!==e.drawCallBudgetPercent?`${e.drawCallBudgetPercent.toFixed(1)}%`:"-";n.push(`| ${e.name} | ${e.type} | ${e.triangles.toLocaleString()} | ${t} | ${e.drawCalls} | ${i} | ${(e.textureBytes/1024/1024).toFixed(1)} |`)}}if(e.loafEntries&&e.loafEntries.length>0){n.push("","### Long Animation Frames (Browser Jank)"),n.push("| Duration | Render Start | Scripts |"),n.push("|----------|-------------|---------|");for(const t of e.loafEntries.slice(-5)){const e=t.scripts.map(e=>`${e.invoker}(${e.duration.toFixed(0)}ms)`).join(", ")||"none";n.push(`| ${t.duration.toFixed(0)}ms | ${t.renderStart.toFixed(0)}ms | ${e} |`)}}if(e.recentSamples.length>0){const t=e.recentSamples.slice(-10);n.push("",`### Recent Frame Times (last ${t.length} samples)`),n.push(`\`${t.map(e=>e.frameTime.toFixed(1)).join(" → ")} ms\``);const i=t.reduce((e,t)=>e+t.frameTime,0)/t.length,s=t.filter(e=>e.frameTime>2*i);s.length>0&&n.push(`⚠ ${s.length} frame time spike(s) detected (>2x average)`)}return n.filter(e=>""!==e).join("\n")}(this.buildSnapshot())}updateConfig(e){this.config={...this.config,...e},e.bufferSize&&e.bufferSize!==this.ringBuffer.capacity&&(this.ringBuffer=new o(e.bufferSize))}exposeGlobalAPI(){window.__funpixelProfiler={start:()=>this.start(),stop:()=>this.stop(),isRunning:()=>this.isRunning,getSnapshot:()=>this.buildSnapshot(),getReport:()=>this.getReport()}}log(e,t="log"){(this.config.debug||"log"!==t)&&console[t](`[Funpixel Profiler] ${e}`)}destroy(){this.stop(),this.gpuTimer?.destroy(),this.messages.destroy(),delete window.__funpixelProfiler}}class u extends c{engineType="pixi";app=null;gl=null;tickerCallback=null;originalDrawElements=null;originalDrawArrays=null;originalDrawElementsInstanced=null;originalDrawArraysInstanced=null;counters={drawCalls:0,triangles:0,points:0,lines:0};lastFrameCounters={drawCalls:0,triangles:0,points:0,lines:0};constructor(e){super(e),this.init()}collectRenderStats(){const e=this.lastFrameCounters;let t=0;this.app?.renderer?.texture?.managedTextures&&(t=this.app.renderer.texture.managedTextures.length);const i=262144*t;return{drawCalls:e.drawCalls,triangles:e.triangles,points:e.points,lines:e.lines,textureCount:t,textureBytes:i,geometryCount:0,geometryBytes:0,programCount:0}}collectSceneStats(){if(!this.app?.stage)return{totalObjects:0,visibleObjects:0,lightsCount:0,camerasCount:0};let e=0,t=0;const i=[this.app.stage];for(;i.length>0;){const s=i.pop();if(e++,s.visible&&t++,s.children)for(let e=s.children.length-1;e>=0;e--)i.push(s.children[e])}return{totalObjects:e,visibleObjects:t,lightsCount:0,camerasCount:0}}hookRenderLoop(){this.app&&!this.tickerCallback&&(this.hookWebGLCalls(),this.tickerCallback=()=>{this.lastFrameCounters={...this.counters},this.counters.drawCalls=0,this.counters.triangles=0,this.counters.points=0,this.counters.lines=0,this.gpuTimer?.beginFrame(),this.gpuTimer?.endFrame();const e=this.app?.ticker?.deltaMS??16.67;this.onFrameEnd(e)},this.app.ticker.add(this.tickerCallback),this.log("Hooked PixiJS ticker for frame timing"))}unhookRenderLoop(){this.app&&this.tickerCallback&&(this.app.ticker.remove(this.tickerCallback),this.tickerCallback=null),this.unhookWebGLCalls(),this.log("Unhooked PixiJS ticker")}isEngineReady(){const e=this.findPixiApp();return!!(e?.stage&&e?.renderer&&e?.ticker)}getGLContext(){if(this.gl)return this.gl;if(this.app?.renderer?.gl)return this.gl=this.app.renderer.gl,this.gl;const e=this.getCanvas();return e?(this.gl=e.getContext("webgl2",{failIfMajorPerformanceCaveat:!1})||e.getContext("webgl",{failIfMajorPerformanceCaveat:!1}),this.gl):null}getCanvas(){return this.app?.canvas||this.app?.view||this.findGameCanvas()}getEngineInfo(){const e=this.app?.renderer,t=this.getCanvas(),i=this.getGLContext(),s=i instanceof WebGL2RenderingContext;return{name:"PixiJS",version:window.PIXI?.VERSION?String(window.PIXI.VERSION):"unknown",renderer:2===e?.type?"Canvas2D":s?"WebGL2":"WebGL",canvasWidth:t?.width??e?.width??0,canvasHeight:t?.height??e?.height??0,pixelRatio:e?.resolution??(window.devicePixelRatio||1),maxTextureSize:i?i.getParameter(i.MAX_TEXTURE_SIZE):void 0,antialias:i?!!i.getContextAttributes()?.antialias:void 0}}getHotObjects(){if(!this.app?.stage)return null;const e=[],t=[this.app.stage];for(;t.length>0;){const i=t.pop(),s=i.constructor?.name??"Unknown";if(("Container"!==s||i.label||i.name)&&i!==this.app.stage&&e.push({name:i.label||i.name||s,type:s,triangles:"Sprite"===s?2:"Graphics"===s?10:0,drawCalls:1,textureBytes:0,visible:i.visible,position:{x:i.position?.x??0,y:i.position?.y??0}}),i.children)for(let e=i.children.length-1;e>=0;e--)t.push(i.children[e])}return e.slice(0,20)}onEngineReady(){this.app=this.findPixiApp(),this.app&&(this.log(`PixiJS ${window.PIXI?.VERSION??""} detected`),this.log(`Stage: ${this.app.stage.children.length} top-level objects`)),super.onEngineReady()}hookWebGLCalls(){const e=this.getGLContext();if(!e)return void this.log("No WebGL context — draw call counting unavailable","warn");const t=this.counters,i=(e,i)=>{switch(t.drawCalls++,e){case 4:t.triangles+=i/3;break;case 5:case 6:t.triangles+=Math.max(0,i-2);break;case 1:t.lines+=i/2;break;case 2:t.lines+=i;break;case 3:t.lines+=Math.max(0,i-1);break;case 0:t.points+=i}};if(this.originalDrawElements=e.drawElements.bind(e),e.drawElements=(e,t,s,r)=>(i(e,t),this.originalDrawElements(e,t,s,r)),this.originalDrawArrays=e.drawArrays.bind(e),e.drawArrays=(e,t,s)=>(i(e,s),this.originalDrawArrays(e,t,s)),"drawElementsInstanced"in e){const t=e;this.originalDrawElementsInstanced=t.drawElementsInstanced.bind(t),t.drawElementsInstanced=(e,t,s,r,n)=>(i(e,t*n),this.originalDrawElementsInstanced(e,t,s,r,n))}if("drawArraysInstanced"in e){const t=e;this.originalDrawArraysInstanced=t.drawArraysInstanced.bind(t),t.drawArraysInstanced=(e,t,s,r)=>(i(e,s*r),this.originalDrawArraysInstanced(e,t,s,r))}this.log("WebGL draw call interception active")}unhookWebGLCalls(){const e=this.gl;e&&(this.originalDrawElements&&(e.drawElements=this.originalDrawElements,this.originalDrawElements=null),this.originalDrawArrays&&(e.drawArrays=this.originalDrawArrays,this.originalDrawArrays=null),this.originalDrawElementsInstanced&&"drawElementsInstanced"in e&&(e.drawElementsInstanced=this.originalDrawElementsInstanced,this.originalDrawElementsInstanced=null),this.originalDrawArraysInstanced&&"drawArraysInstanced"in e&&(e.drawArraysInstanced=this.originalDrawArraysInstanced,this.originalDrawArraysInstanced=null),this.log("WebGL draw call interception removed"))}findPixiApp(){if(window.__PIXI_APP__)return window.__PIXI_APP__;const e=window;if(e.app&&this.isPixiApp(e.app))return e.app;if(e.game&&this.isPixiApp(e.game))return e.game;if(e.pixiApp&&this.isPixiApp(e.pixiApp))return e.pixiApp;if(window.PIXI){const e=window.PIXI;if(e.app&&this.isPixiApp(e.app))return e.app}for(const t in window)try{const i=e[t];if(i&&this.isPixiApp(i))return i}catch{}return null}isPixiApp(e){if(!e||"object"!=typeof e)return!1;const t=e;return!!(t.stage&&t.renderer&&t.ticker)}findGameCanvas(){const e=document.querySelectorAll("canvas");for(const t of e){const e=t;if(e.__pixi_app||e.__PIXI_APP__||t.getAttribute("data-pixi"))return t}return e[0]||null}}function m(){new u({debug:!0})}return"loading"===document.readyState?document.addEventListener("DOMContentLoaded",m):m(),e.PixiProfiler=u,e}({});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var FunpixelProfiler=function(e){"use strict";const t="🎬",i="🎨",s="💾",r="🖥️",n="✨";const a={sampleInterval:1e3,bufferSize:3e4,thresholds:{fps:{green:55,yellow:30},frameTime:{green:18,yellow:33},drawCalls:{green:200,yellow:1e3},triangles:{green:2e5,yellow:1e6},textureMemoryMB:{green:100,yellow:500},geometryMemoryMB:{green:50,yellow:200}},debug:!1};class o{buf;head=0;size=0;capacity;constructor(e){if(e<1)throw new Error("TimeWindowedRingBuffer capacity must be >= 1");this.capacity=e,this.buf=new Array(e)}push(e){this.buf[this.head]=e,this.head=(this.head+1)%this.capacity,this.size<this.capacity&&(this.size+=1)}sliceSince(e){if(0===this.size)return[];const t=[],i=(this.head-this.size+this.capacity)%this.capacity;for(let s=0;s<this.size;s++){const r=(i+s)%this.capacity,n=this.buf[r];n&&n.timestamp>=e&&t.push(n)}return t}clear(){this.head=0,this.size=0}get length(){return this.size}}function l(e,t){if(0===e.length)return 0;if(1===e.length)return e[0];const i=[...e].sort((e,t)=>e-t),s=t/100*(i.length-1),r=Math.floor(s),n=Math.ceil(s);if(r===n)return i[r];const a=s-r;return i[r]*(1-a)+i[n]*a}class h{engine;handlers=new Map;isListening=!1;boundHandleMessage;constructor(e){this.engine=e,this.boundHandleMessage=this.handleMessage.bind(this)}send(e){const t={...e,engine:this.engine,source:"funpixel-profiler"};try{window.parent.postMessage(t,"*")}catch{}}on(e,t){const i=this.handlers.get(e)||[];i.push(t),this.handlers.set(e,i),this.isListening||this.startListening()}off(e,t){const i=this.handlers.get(e)||[],s=i.indexOf(t);s>-1&&i.splice(s,1)}startListening(){this.isListening||(this.isListening=!0,window.addEventListener("message",this.boundHandleMessage))}handleMessage(e){const t=e.data;if(!t?.type)return;const i=this.normalizeMessageType(t.type);if(!i)return;const s=this.handlers.get(i);if(s){const e={type:i,config:t.config};for(const t of s)t(e)}}normalizeMessageType(e){switch(e){case"PROFILER_START":case"START_PROFILER":return"PROFILER_START";case"PROFILER_STOP":case"STOP_PROFILER":return"PROFILER_STOP";case"PROFILER_REQUEST_SNAPSHOT":case"REQUEST_PROFILER_SNAPSHOT":return"PROFILER_REQUEST_SNAPSHOT";case"PROFILER_SET_CONFIG":case"SET_PROFILER_CONFIG":return"PROFILER_SET_CONFIG";default:return null}}destroy(){this.isListening&&(window.removeEventListener("message",this.boundHandleMessage),this.isListening=!1),this.handlers.clear()}}class g{gl=null;ext=null;isWebGL2=!1;_available=!1;currentQuery=null;pendingQuery=null;lastResult=null;frameActive=!1;constructor(e){e&&(this.gl=e,this.isWebGL2="createQuery"in e,this.initExtension())}initExtension(){if(this.gl)try{this.isWebGL2&&(this.ext=this.gl.getExtension("EXT_disjoint_timer_query_webgl2")),this.ext||(this.ext=this.gl.getExtension("EXT_disjoint_timer_query")),this.ext&&(this._available=!0)}catch{this._available=!1}}get available(){return this._available}beginFrame(){if(this._available&&this.gl&&this.ext&&!this.frameActive){this.resolvePendingQuery(),this.currentQuery&&(this.pendingQuery=this.currentQuery);try{this.isWebGL2?(this.currentQuery=this.gl.createQuery(),this.currentQuery&&(this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT,this.currentQuery),this.frameActive=!0)):(this.currentQuery=this.ext.createQueryEXT(),this.currentQuery&&(this.ext.beginQueryEXT(this.ext.TIME_ELAPSED_EXT,this.currentQuery),this.frameActive=!0))}catch{this._available=!1}}}endFrame(){if(this._available&&this.gl&&this.ext&&this.frameActive){try{this.isWebGL2?this.gl.endQuery(this.ext.TIME_ELAPSED_EXT):this.ext.endQueryEXT(this.ext.TIME_ELAPSED_EXT)}catch{this._available=!1}this.frameActive=!1}}getResult(){return this.resolvePendingQuery(),this.lastResult}resolvePendingQuery(){if(this.pendingQuery&&this.gl&&this.ext)try{if(this.gl.getParameter(this.ext.GPU_DISJOINT_EXT))return this.cleanupQuery(this.pendingQuery),this.pendingQuery=null,void(this.lastResult=null);let e,t;if(this.isWebGL2){const i=this.gl;e=i.getQueryParameter(this.pendingQuery,i.QUERY_RESULT_AVAILABLE),e&&(t=i.getQueryParameter(this.pendingQuery,i.QUERY_RESULT))}else e=this.ext.getQueryObjectEXT(this.pendingQuery,this.ext.QUERY_RESULT_AVAILABLE_EXT),e&&(t=this.ext.getQueryObjectEXT(this.pendingQuery,this.ext.QUERY_RESULT_EXT));e&&"number"==typeof t&&(this.lastResult=t/1e6,this.cleanupQuery(this.pendingQuery),this.pendingQuery=null)}catch{this.pendingQuery&&this.cleanupQuery(this.pendingQuery),this.pendingQuery=null,this.lastResult=null}}cleanupQuery(e){try{this.isWebGL2?this.gl.deleteQuery(e):this.ext&&this.ext.deleteQueryEXT(e)}catch{}}destroy(){this.currentQuery&&(this.frameActive&&this.endFrame(),this.cleanupQuery(this.currentQuery),this.currentQuery=null),this.pendingQuery&&(this.cleanupQuery(this.pendingQuery),this.pendingQuery=null),this._available=!1}}class c{messages;ringBuffer;gpuTimer=null;config;isRunning=!1;profilingStartTime=0;lastSampleSentTime=0;lastFrameTimestamp=0;accumulatedCpuTime=0;sampleAccumulator=[];warnings=[];warningHashes=new Set;sceneStatsCache=null;sceneStatsCacheTime=0;SCENE_STATS_CACHE_MS=200;pendingFrameEmit=!1;frameRenderStats={};stateChangeCounters={programSwitches:0,textureSwitches:0,fboSwitches:0};lastFrameStateChanges={programSwitches:0,textureSwitches:0,fboSwitches:0};originalUseProgram=null;originalBindTexture=null;originalBindFramebuffer=null;lastComputedScore=-1;loafObserver=null;loafEntries=[];constructor(e={}){this.config={...a,...e},this.ringBuffer=new o(this.config.bufferSize)}init(){this.messages=new h(this.engineType),this.setupMessageHandlers(),this.waitForEngine(),this.exposeGlobalAPI(),this.log("Profiler initialized")}waitForEngine(){const e=Date.now();let t=!1;const i=()=>{this.isEngineReady()?this.onEngineReady():(!t&&Date.now()-e>15e3&&(t=!0,this.log("Engine not detected yet — continuing to poll slowly (menu-first game?)","warn")),setTimeout(i,t?2e3:100))};setTimeout(i,100)}onEngineReady(){this.log("Engine detected");const e=this.getGLContext();e&&(this.gpuTimer=new g(e),this.gpuTimer.available&&this.log("GPU timer query available")),this.messages.send({type:"PROFILER_READY"}),this.messages.send({type:"PROFILER_ENGINE_DETECTED",engine:this.engineType}),this.start()}setupMessageHandlers(){this.messages.on("PROFILER_START",e=>{e.config&&this.updateConfig(e.config),this.start()}),this.messages.on("PROFILER_STOP",()=>{this.stop()}),this.messages.on("PROFILER_REQUEST_SNAPSHOT",()=>{const e=this.buildSnapshot();this.messages.send({type:"PROFILER_SNAPSHOT",snapshot:e})}),this.messages.on("PROFILER_SET_CONFIG",e=>{e.config&&this.updateConfig(e.config)})}start(){this.isRunning||(this.isRunning=!0,this.profilingStartTime=performance.now(),this.lastSampleSentTime=performance.now(),this.lastFrameTimestamp=0,this.accumulatedCpuTime=0,this.frameRenderStats={},this.pendingFrameEmit=!1,this.sampleAccumulator=[],this.warnings=[],this.warningHashes.clear(),this.hookRenderLoop(),this.hookStateChangeTracking(),this.startLoafObserver(),this.log("Profiling started"))}stop(){this.isRunning&&(this.isRunning=!1,this.unhookRenderLoop(),this.unhookStateChangeTracking(),this.stopLoafObserver(),this.log("Profiling stopped"))}onFrameEnd(e){if(!this.isRunning)return;let t;this.accumulatedCpuTime+=e;try{t=this.collectRenderStats()}catch{t={}}const i=this.frameRenderStats;i.drawCalls=(i.drawCalls||0)+(t.drawCalls||0),i.triangles=(i.triangles||0)+(t.triangles||0),i.points=(i.points||0)+(t.points||0),i.lines=(i.lines||0)+(t.lines||0),void 0!==t.textureCount&&(i.textureCount=t.textureCount),void 0!==t.textureBytes&&(i.textureBytes=t.textureBytes),void 0!==t.geometryCount&&(i.geometryCount=t.geometryCount),void 0!==t.geometryBytes&&(i.geometryBytes=t.geometryBytes),void 0!==t.programCount&&(i.programCount=t.programCount),this.pendingFrameEmit||(this.pendingFrameEmit=!0,queueMicrotask(()=>this.emitFrameSample()))}emitFrameSample(){if(this.pendingFrameEmit=!1,!this.isRunning)return;const e=performance.now(),t=this.lastFrameTimestamp>0?e-this.lastFrameTimestamp:16.67;this.lastFrameTimestamp=e,this.lastFrameStateChanges={...this.stateChangeCounters},this.stateChangeCounters.programSwitches=0,this.stateChangeCounters.textureSwitches=0,this.stateChangeCounters.fboSwitches=0;const i=this.buildFrameSample(t,this.accumulatedCpuTime,this.frameRenderStats);if(this.accumulatedCpuTime=0,this.frameRenderStats={},this.ringBuffer.push(i),this.sampleAccumulator.push(i),e-this.lastSampleSentTime>=this.config.sampleInterval){const t=this.aggregateStats(this.sampleAccumulator),i=this.detectWarnings(t);this.messages.send({type:"PROFILER_SAMPLE",stats:t,warnings:i});for(const e of i)this.messages.send({type:"PROFILER_WARNING",warning:e});this.sampleAccumulator=[],this.lastSampleSentTime=e}}buildFrameSample(e,t,i){const s=this.getSceneStatsCached(),r=this.gpuTimer?.getResult()??null;let n=null,a=null;return performance.memory&&(n=performance.memory.usedJSHeapSize,a=performance.memory.totalJSHeapSize),{timestamp:performance.now(),frameTime:e,fps:e>0?1e3/e:0,cpuTime:t,drawCalls:i.drawCalls||0,triangles:i.triangles||0,points:i.points||0,lines:i.lines||0,textureCount:i.textureCount||0,textureBytes:i.textureBytes||0,geometryCount:i.geometryCount||0,geometryBytes:i.geometryBytes||0,programCount:i.programCount||0,programSwitches:this.lastFrameStateChanges.programSwitches,textureSwitches:this.lastFrameStateChanges.textureSwitches,fboSwitches:this.lastFrameStateChanges.fboSwitches,totalObjects:s.totalObjects,visibleObjects:s.visibleObjects,lightsCount:s.lightsCount,camerasCount:s.camerasCount,gpuTime:r,jsHeapUsed:n,jsHeapTotal:a}}getSceneStatsCached(){const e=performance.now();if(!this.sceneStatsCache||e-this.sceneStatsCacheTime>this.SCENE_STATS_CACHE_MS){try{this.sceneStatsCache=this.collectSceneStats()}catch{this.sceneStatsCache={totalObjects:0,visibleObjects:0,lightsCount:0,camerasCount:0}}this.sceneStatsCacheTime=e}return this.sceneStatsCache}aggregateStats(e){if(0===e.length)return this.emptyStats();const t=e[e.length-1],i=e.map(e=>e.fps),s=e.map(e=>e.frameTime),r=e.map(e=>e.cpuTime),n=this.computeMinMaxAvg(r),a={fps:this.computeMinMaxAvg(i),frameTime:this.computeMinMaxAvg(s),cpuTime:n,drawCalls:t.drawCalls,triangles:t.triangles,points:t.points,lines:t.lines,textureCount:t.textureCount,textureMemoryMB:t.textureBytes/1024/1024,geometryCount:t.geometryCount,geometryMemoryMB:t.geometryBytes/1024/1024,programCount:t.programCount,programSwitches:t.programSwitches,textureSwitches:t.textureSwitches,fboSwitches:t.fboSwitches,totalObjects:t.totalObjects,visibleObjects:t.visibleObjects,lightsCount:t.lightsCount,camerasCount:t.camerasCount,gpuTime:t.gpuTime,jsHeapUsedMB:null!==t.jsHeapUsed?t.jsHeapUsed/1024/1024:null,framePacing:this.computeFramePacing(e),bottleneck:this.classifyBottleneck(n.avg,t.gpuTime,this.computeMinMaxAvg(s).avg,t.drawCalls),sampleCount:e.length};return a.performanceScore=this.computePerformanceScore(a),a}computeMinMaxAvg(e){let t=1/0,i=-1/0,s=0;for(const r of e)r<t&&(t=r),r>i&&(i=r),s+=r;return{current:e[e.length-1],min:t,max:i,avg:s/e.length}}emptyStats(){return{fps:{current:0,min:0,max:0,avg:0},frameTime:{current:0,min:0,max:0,avg:0},cpuTime:{current:0,min:0,max:0,avg:0},drawCalls:0,triangles:0,points:0,lines:0,textureCount:0,textureMemoryMB:0,geometryCount:0,geometryMemoryMB:0,programCount:0,programSwitches:0,textureSwitches:0,fboSwitches:0,totalObjects:0,visibleObjects:0,lightsCount:0,camerasCount:0,gpuTime:null,jsHeapUsedMB:null,framePacing:this.emptyFramePacing(),bottleneck:{type:"unknown",description:"Insufficient data",confidence:0,suggestion:""},sampleCount:0}}detectWarnings(e){const t=[],i=performance.now(),s=this.config.thresholds;return e.fps.avg>0&&e.fps.avg<s.fps.yellow&&this.addWarning(t,"fps",e.fps.avg<s.fps.yellow/2?"critical":"warning",`Average FPS is ${e.fps.avg.toFixed(1)} (below ${s.fps.yellow})`,e.fps.avg,s.fps.yellow,"Consider reducing draw calls, lowering resolution, or simplifying geometry. Use LOD (Level of Detail) for distant objects.",i),e.frameTime.avg>s.frameTime.yellow&&this.addWarning(t,"frame_time",e.frameTime.avg>2*s.frameTime.yellow?"critical":"warning",`Average frame time is ${e.frameTime.avg.toFixed(1)}ms (above ${s.frameTime.yellow}ms)`,e.frameTime.avg,s.frameTime.yellow,"Profile individual systems. Common causes: expensive shaders, too many lights with shadows, unoptimized physics, GC pauses.",i),e.drawCalls>s.drawCalls.yellow&&this.addWarning(t,"draw_calls",e.drawCalls>3*s.drawCalls.yellow?"critical":"warning",`Draw calls: ${e.drawCalls.toLocaleString()} (above ${s.drawCalls.yellow})`,e.drawCalls,s.drawCalls.yellow,"Batch similar materials, use instanced rendering (InstancedMesh/InstancedBufferGeometry), merge static geometry, use texture atlases.",i),e.triangles>s.triangles.yellow&&this.addWarning(t,"triangles",e.triangles>3*s.triangles.yellow?"critical":"warning",`Triangle count: ${e.triangles.toLocaleString()} (above ${s.triangles.yellow.toLocaleString()})`,e.triangles,s.triangles.yellow,"Use LOD, reduce polygon count on distant/small objects, enable frustum culling, consider simpler geometry for non-hero assets.",i),e.textureMemoryMB>s.textureMemoryMB.yellow&&this.addWarning(t,"texture_memory",e.textureMemoryMB>2*s.textureMemoryMB.yellow?"critical":"warning",`Texture memory: ${e.textureMemoryMB.toFixed(1)}MB (above ${s.textureMemoryMB.yellow}MB)`,e.textureMemoryMB,s.textureMemoryMB.yellow,"Use compressed textures (KTX2/Basis), reduce texture resolution, use power-of-2 sizes, share textures via atlases, dispose unused textures.",i),e.geometryMemoryMB>s.geometryMemoryMB.yellow&&this.addWarning(t,"geometry_memory",e.geometryMemoryMB>2*s.geometryMemoryMB.yellow?"critical":"warning",`Geometry memory: ${e.geometryMemoryMB.toFixed(1)}MB (above ${s.geometryMemoryMB.yellow}MB)`,e.geometryMemoryMB,s.geometryMemoryMB.yellow,"Share geometry between meshes, use BufferGeometry instead of Geometry, dispose unused geometries, use instancing for repeated shapes.",i),e.programCount>50&&this.addWarning(t,"shader_count","warning",`Shader programs: ${e.programCount} (many unique materials)`,e.programCount,50,"Reduce material variations, share materials between objects, consider using a single uber-shader with defines.",i),null!==e.gpuTime&&e.gpuTime>16&&this.addWarning(t,"gpu_time",e.gpuTime>33?"critical":"warning",`GPU time: ${e.gpuTime.toFixed(1)}ms (above 16ms budget)`,e.gpuTime,16,"Simplify shaders, reduce overdraw, lower shadow map resolution, use fewer real-time lights, consider baked lighting.",i),t}addWarning(e,t,i,s,r,n,a,o){const l=`${t}-${i}`;if(this.warningHashes.has(l))return;this.warningHashes.add(l);const h={id:`${t}-${Date.now()}`,severity:i,category:t,message:s,value:r,threshold:n,timestamp:o,suggestion:a};e.push(h),this.warnings.push(h)}computeFramePacing(e){if(e.length<2)return this.emptyFramePacing();const t=e.map(e=>e.frameTime),i=t.reduce((e,t)=>e+t,0)/t.length,s=t.reduce((e,t)=>e+(t-i)**2,0)/t.length,r=Math.sqrt(s),n=16.67*.1,a=t.filter(e=>Math.abs(e-16.67)<=n).length/t.length*100,o=2*i,l=t.filter(e=>e>o).length,h=e.length>0?(e[e.length-1].timestamp-e[0].timestamp)/1e3:1,g=h>0?l/h*60:0,c=1.5*i;let m=0,u=0;for(const e of t)e<=c?(u++,u>m&&(m=u)):u=0;const d=[0,0,0,0,0];for(const e of t)e<8?d[0]++:e<16?d[1]++:e<33?d[2]++:e<50?d[3]++:d[4]++;let p="stable";if(t.length>=120){const e=this.config.thresholds.frameTime.green,i=Math.floor(t.length/2),s=t.slice(0,i).sort((e,t)=>e-t),r=t.slice(i).sort((e,t)=>e-t),n=s[Math.floor(.99*s.length)]??0,a=r[Math.floor(.99*r.length)]??0;a>1.2*n&&a>e?p="degrading":a<.83*n&&n>e&&(p="improving")}return{frameTimeStdDev:r,consistencyPercent:a,janksPerMinute:g,longestSmoothStreak:m,histogram:d,varianceTrend:p}}emptyFramePacing(){return{frameTimeStdDev:0,consistencyPercent:0,janksPerMinute:0,longestSmoothStreak:0,histogram:[0,0,0,0,0],varianceTrend:"stable"}}classifyBottleneck(e,t,i,s){if(i<=0)return{type:"unknown",description:"Insufficient data",confidence:0,suggestion:""};if(i<=17.5&&e<12&&(null===t||t<12))return{type:"vsync-limited",description:"Running at vsync cap with headroom available",confidence:.9,suggestion:"Performance is good. Add more visual quality or increase simulation complexity."};const r=null!==t&&t>0;if(s>500&&e>10)return{type:"draw-call-bound",description:`${s} draw calls causing ${e.toFixed(1)}ms CPU overhead`,confidence:.85,suggestion:"Use InstancedMesh for repeated geometry, merge static meshes, share materials, use texture atlases."};if(r){const i=e/t;if(i>2)return{type:"cpu-bound",description:`CPU render time (${e.toFixed(1)}ms) is ${i.toFixed(1)}x GPU time (${t.toFixed(1)}ms)`,confidence:Math.min(.95,.6+.1*i),suggestion:"Reduce draw call count, simplify scene graph, optimize JavaScript logic, use web workers for heavy computation."};if(i<.5)return{type:"gpu-bound",description:`GPU time (${t.toFixed(1)}ms) is ${(1/i).toFixed(1)}x CPU time (${e.toFixed(1)}ms)`,confidence:Math.min(.95,.6+1/i*.1),suggestion:"Simplify shaders, reduce overdraw, lower shadow/texture resolution, use LOD, reduce post-processing passes."}}const n=r?Math.max(e,t):e;return i>2*n&&n>0?{type:"main-thread",description:`Frame time (${i.toFixed(1)}ms) is ${(i/n).toFixed(1)}x render time (${n.toFixed(1)}ms) — non-render work blocking`,confidence:.75,suggestion:"Profile JavaScript execution. Check for GC pauses, expensive physics, or layout thrashing between frames."}:{type:"balanced",description:"No single bottleneck detected — CPU and GPU load are balanced",confidence:.5,suggestion:"For further optimization, reduce scene complexity across the board or enable LOD."}}computePerformanceScore(e){const t=this.config.thresholds,i=e.fps.avg>=60?100:e.fps.avg>=30?50+(e.fps.avg-30)/30*50:Math.max(0,e.fps.avg/30*50),s=e.framePacing,r=Math.max(0,Math.min(100,.4*s.consistencyPercent+.3*Math.max(0,100-5*s.janksPerMinute)+.3*Math.max(0,100-10*s.frameTimeStdDev))),n=e.textureMemoryMB+e.geometryMemoryMB,a=t.textureMemoryMB.green,o=t.textureMemoryMB.yellow,l=n<=a?100:n<=o?50+50*(1-(n-a)/(o-a)):Math.max(0,50-(n-o)/o*50),h=((e.drawCalls<=t.drawCalls.green?100:e.drawCalls<=t.drawCalls.yellow?50+50*(1-(e.drawCalls-t.drawCalls.green)/(t.drawCalls.yellow-t.drawCalls.green)):Math.max(0,50-(e.drawCalls-t.drawCalls.yellow)/t.drawCalls.yellow*50))+(e.triangles<=t.triangles.green?100:e.triangles<=t.triangles.yellow?50+50*(1-(e.triangles-t.triangles.green)/(t.triangles.yellow-t.triangles.green)):Math.max(0,50-(e.triangles-t.triangles.yellow)/t.triangles.yellow*50)))/2,g=null===e.gpuTime||e.gpuTime<=8?100:e.gpuTime<=16?50+50*(1-(e.gpuTime-8)/8):Math.max(0,50-(e.gpuTime-16)/16*50);let c=Math.round(.4*i+.2*r+.15*l+.15*h+.1*g);c=Math.max(0,Math.min(100,c));const m=this.lastComputedScore<0?c:Math.round(.3*c+.7*this.lastComputedScore);this.lastComputedScore=m;const{grade:u,label:d}=function(e){return e>=90?{grade:"excellent",label:"Excellent"}:e>=70?{grade:"good",label:"Good"}:e>=50?{grade:"needs-work",label:"Needs Work"}:e>=30?{grade:"poor",label:"Poor"}:{grade:"critical",label:"Critical"}}(m);return{score:m,grade:u,gradeLabel:d,categories:{performance:Math.round(Math.max(0,Math.min(100,i))),smoothness:Math.round(Math.max(0,Math.min(100,r))),memory:Math.round(Math.max(0,Math.min(100,l))),rendering:Math.round(Math.max(0,Math.min(100,h))),gpu:Math.round(Math.max(0,Math.min(100,g)))},issues:this.generateIssues(e)}}generateIssues(e){const a=[],o=this.config.thresholds;e.fps.avg>0&&e.fps.avg<o.fps.yellow&&a.push({id:"fps-low",severity:e.fps.avg<o.fps.yellow/2?"critical":"warning",title:"Game is running slowly",description:e.fps.avg<20?"Your game is very slow. Try reducing the number of objects or simplifying visual effects.":"Your game could be smoother. Consider simplifying busy scenes.",category:"performance",icon:t}),e.drawCalls>o.drawCalls.yellow&&a.push({id:"draw-calls-high",severity:e.drawCalls>3*o.drawCalls.yellow?"critical":"warning",title:"Too many objects drawing separately",description:"Group similar objects together so the game does less work each frame. Objects with the same look can often be merged.",category:"rendering",icon:i}),e.triangles>o.triangles.yellow&&a.push({id:"triangles-high",severity:e.triangles>3*o.triangles.yellow?"critical":"warning",title:"Too much geometry detail",description:"Some models have more detail than needed. Use simpler models for background objects or things far from the camera.",category:"rendering",icon:i}),e.textureMemoryMB>o.textureMemoryMB.yellow&&a.push({id:"texture-memory-high",severity:e.textureMemoryMB>2*o.textureMemoryMB.yellow?"critical":"warning",title:"Large images using lots of memory",description:"Your textures are using a lot of GPU memory. Try compressing images, using smaller sizes, or sharing textures between objects.",category:"memory",icon:s}),e.geometryMemoryMB>o.geometryMemoryMB.yellow&&a.push({id:"geometry-memory-high",severity:e.geometryMemoryMB>2*o.geometryMemoryMB.yellow?"critical":"warning",title:"Too much 3D data in memory",description:"Your models are using lots of memory. Share shapes between similar objects and remove unused geometry.",category:"memory",icon:s}),null!==e.gpuTime&&e.gpuTime>16&&a.push({id:"gpu-time-high",severity:e.gpuTime>33?"critical":"warning",title:"GPU is working too hard",description:"Your graphics card is struggling. Simplify visual effects, reduce shadow quality, or lower the resolution.",category:"gpu",icon:r}),e.framePacing.janksPerMinute>10&&a.push({id:"jank-detected",severity:e.framePacing.janksPerMinute>30?"critical":"warning",title:"Game stutters occasionally",description:"Your game has noticeable hiccups. This can be caused by loading assets during gameplay or doing too much work at once.",category:"smoothness",icon:n});const l=this.config.thresholds.frameTime.green,h=this.getBurnRate(1e4,l),g=this.getBurnRate(6e4,l),c=this.getBurnRate(3e5,l);return h>=10&&g>=10?a.push({id:"performance-degrading",severity:"critical",title:"Game is stuttering right now",description:"Frames are missing the target budget at 10× the rate the SLO allows, both in the last 10 seconds and the last minute. Something is actively wrong — recent code changes or an expensive scene transition.",category:"smoothness",icon:n}):c>=3&&g>=3&&a.push({id:"performance-degrading",severity:"warning",title:"Performance getting worse over time",description:"Frames have been missing the target budget at 3× the rate the SLO allows, sustained over the last few minutes. Common causes: objects accumulating without cleanup, growing particle pool, forgotten event listeners.",category:"smoothness",icon:n}),a}hookStateChangeTracking(){const e=this.getGLContext();if(!e)return;const t=this.stateChangeCounters;this.originalUseProgram=e.useProgram.bind(e),e.useProgram=e=>(t.programSwitches++,this.originalUseProgram(e)),this.originalBindTexture=e.bindTexture.bind(e),e.bindTexture=(e,i)=>(t.textureSwitches++,this.originalBindTexture(e,i)),this.originalBindFramebuffer=e.bindFramebuffer.bind(e),e.bindFramebuffer=(e,i)=>(t.fboSwitches++,this.originalBindFramebuffer(e,i)),this.log("WebGL state change tracking active")}unhookStateChangeTracking(){const e=this.getGLContext();e&&(this.originalUseProgram&&(e.useProgram=this.originalUseProgram,this.originalUseProgram=null),this.originalBindTexture&&(e.bindTexture=this.originalBindTexture,this.originalBindTexture=null),this.originalBindFramebuffer&&(e.bindFramebuffer=this.originalBindFramebuffer,this.originalBindFramebuffer=null))}startLoafObserver(){try{if("undefined"==typeof PerformanceObserver)return;const e=PerformanceObserver.supportedEntryTypes;if(!e?.includes("long-animation-frame"))return;this.loafObserver=new PerformanceObserver(e=>{for(const t of e.getEntries()){const e=t;this.loafEntries.push({duration:e.duration,renderStart:e.renderStart??0,styleAndLayoutStart:e.styleAndLayoutStart??0,scripts:(e.scripts??[]).map(e=>({sourceURL:e.sourceURL||"unknown",invoker:e.invoker||"unknown",duration:e.duration})),timestamp:e.startTime}),this.loafEntries.length>50&&this.loafEntries.shift()}}),this.loafObserver.observe({type:"long-animation-frame",buffered:!1}),this.log("Long Animation Frame (LoAF) observer active")}catch{}}stopLoafObserver(){this.loafObserver&&(this.loafObserver.disconnect(),this.loafObserver=null)}getWindowedStats(e){const t=performance.now()-e,i=this.ringBuffer.sliceSince(t),s=i.length;if(0===s)return{windowMs:e,sampleCount:0,fps:{p50:0,p95:0,p99:0,min:0,max:0,avg:0},frameTime:{p50:0,p95:0,p99:0,max:0,avg:0},heap:{start:0,end:0,min:0,max:0,deltaPerMin:0}};const r=i.map(e=>e.fps),n=i.map(e=>e.frameTime),a=i.map(e=>(e.jsHeapUsed??0)/1048576),o=a[a.length-1]-a[0],h=(i[i.length-1].timestamp-i[0].timestamp)/6e4,g=(e,t)=>e+t;return{windowMs:e,sampleCount:s,fps:{p50:l(r,50),p95:l(r,95),p99:l(r,99),min:Math.min(...r),max:Math.max(...r),avg:r.reduce(g,0)/s},frameTime:{p50:l(n,50),p95:l(n,95),p99:l(n,99),max:Math.max(...n),avg:n.reduce(g,0)/s},heap:{start:a[0],end:a[a.length-1],min:Math.min(...a),max:Math.max(...a),deltaPerMin:h>0?o/h:0}}}getBurnRate(e,t,i=30){const s=performance.now()-e;return function(e,t,i=30){if(e.length<i)return 0;let s=0;for(const i of e)i.frameTime>t&&(s+=1);return s/e.length/.01}(this.ringBuffer.sliceSince(s),t,i)}buildSnapshot(){const e=this.ringBuffer.sliceSince(0),t=e.length>0?this.aggregateStats(e):this.emptyStats();this.warningHashes.clear(),this.warnings=[],this.detectWarnings(t);let i=this.getHotObjects()??void 0;if(i&&i.length>0){const e=t.triangles||1,s=t.drawCalls||1;i=i.map(t=>({...t,triangleBudgetPercent:t.triangles/e*100,drawCallBudgetPercent:t.drawCalls/s*100}))}return{engine:this.engineType,timestamp:Date.now(),profilingDuration:performance.now()-this.profilingStartTime,stats:t,recentSamples:e.slice(-30),warnings:[...this.warnings],engineInfo:this.getEngineInfo(),hotObjects:i,loafEntries:this.loafEntries.length>0?[...this.loafEntries]:void 0}}getReport(){return function(e){const{stats:t,warnings:i,engineInfo:s,hotObjects:r}=e,n=["## Performance Profile","",`**Engine:** ${s.name} ${s.version} | **Renderer:** ${s.renderer}`,`**Canvas:** ${s.canvasWidth}x${s.canvasHeight} @ ${s.pixelRatio}x DPR`,`**Profiling Duration:** ${(e.profilingDuration/1e3).toFixed(1)}s | **Samples:** ${e.recentSamples.length}`,"","### Frame Performance","| Metric | Current | Min | Max | Avg |","|--------|---------|-----|-----|-----|",`| FPS | ${t.fps.current.toFixed(1)} | ${t.fps.min.toFixed(1)} | ${t.fps.max.toFixed(1)} | ${t.fps.avg.toFixed(1)} |`,`| Frame Time (ms) | ${t.frameTime.current.toFixed(2)} | ${t.frameTime.min.toFixed(2)} | ${t.frameTime.max.toFixed(2)} | ${t.frameTime.avg.toFixed(2)} |`,`| CPU Render (ms) | ${t.cpuTime.current.toFixed(2)} | ${t.cpuTime.min.toFixed(2)} | ${t.cpuTime.max.toFixed(2)} | ${t.cpuTime.avg.toFixed(2)} |`,null!==t.gpuTime?`| GPU Time (ms) | ${t.gpuTime.toFixed(2)} | - | - | - |`:"","","### Render Pipeline","| Metric | Value |","|--------|-------|",`| Draw Calls | ${t.drawCalls.toLocaleString()} |`,`| Triangles | ${t.triangles.toLocaleString()} |`,`| Points | ${t.points.toLocaleString()} |`,`| Lines | ${t.lines.toLocaleString()} |`,`| Shader Programs | ${t.programCount} |`,"","### Memory","| Metric | Value |","|--------|-------|",`| Textures | ${t.textureCount} (${t.textureMemoryMB.toFixed(1)} MB) |`,`| Geometries | ${t.geometryCount} (${t.geometryMemoryMB.toFixed(1)} MB) |`,null!==t.jsHeapUsedMB?`| JS Heap | ${t.jsHeapUsedMB.toFixed(1)} MB |`:"","","### Scene Graph","| Metric | Value |","|--------|-------|",`| Total Objects | ${t.totalObjects.toLocaleString()} |`,`| Visible Objects | ${t.visibleObjects.toLocaleString()} |`,`| Lights | ${t.lightsCount} |`,`| Cameras | ${t.camerasCount} |`],a=t.framePacing;a&&n.push("### Frame Pacing (Smoothness)","| Metric | Value |","|--------|-------|",`| Consistency | ${a.consistencyPercent.toFixed(1)}% of frames on-target |`,`| Std Deviation | ${a.frameTimeStdDev.toFixed(2)}ms |`,`| Janks/min | ${a.janksPerMinute.toFixed(1)} |`,`| Longest Smooth Streak | ${a.longestSmoothStreak} frames |`,`| Variance Trend | ${a.varianceTrend} |`,`| Histogram (0-8/8-16/16-33/33-50/50+ms) | ${a.histogram.join(" / ")} |`,"");const o=t.bottleneck;if(o&&"unknown"!==o.type&&n.push("### Bottleneck Analysis",`- **Type:** ${o.type} (${(100*o.confidence).toFixed(0)}% confidence)`,`- **Analysis:** ${o.description}`,`- **Suggestion:** ${o.suggestion}`,""),(t.programSwitches>0||t.textureSwitches>0||t.fboSwitches>0)&&n.push("### WebGL State Changes (per frame)","| Metric | Value |","|--------|-------|",`| Program Switches | ${t.programSwitches} |`,`| Texture Binds | ${t.textureSwitches} |`,`| FBO Switches | ${t.fboSwitches} |`,""),(void 0!==s.antialias||s.shadows||s.toneMapping)&&(n.push("","### Renderer Settings"),void 0!==s.antialias&&n.push("- Antialiasing: "+(s.antialias?"ON":"OFF")),s.shadows&&n.push("- Shadows: "+(s.shadows.enabled?`ON (${s.shadows.type||"default"})`:"OFF")),s.toneMapping&&n.push(`- Tone Mapping: ${s.toneMapping}`),s.maxTextureSize&&n.push(`- Max Texture Size: ${s.maxTextureSize}`)),i.length>0){n.push("","### Performance Warnings");for(const e of i){const t="critical"===e.severity?"CRITICAL":"warning"===e.severity?"WARNING":"INFO";n.push(`- **[${t}]** ${e.message} (${e.value} > threshold ${e.threshold})`),n.push(` Suggestion: ${e.suggestion}`)}}if(r&&r.length>0){n.push("","### Top Objects by Cost"),n.push("| Object | Type | Triangles | Tri% | Draw Calls | DC% | Tex MB |"),n.push("|--------|------|-----------|------|------------|-----|--------|");for(const e of r.slice(0,10)){const t=void 0!==e.triangleBudgetPercent?`${e.triangleBudgetPercent.toFixed(1)}%`:"-",i=void 0!==e.drawCallBudgetPercent?`${e.drawCallBudgetPercent.toFixed(1)}%`:"-";n.push(`| ${e.name} | ${e.type} | ${e.triangles.toLocaleString()} | ${t} | ${e.drawCalls} | ${i} | ${(e.textureBytes/1024/1024).toFixed(1)} |`)}}if(e.loafEntries&&e.loafEntries.length>0){n.push("","### Long Animation Frames (Browser Jank)"),n.push("| Duration | Render Start | Scripts |"),n.push("|----------|-------------|---------|");for(const t of e.loafEntries.slice(-5)){const e=t.scripts.map(e=>`${e.invoker}(${e.duration.toFixed(0)}ms)`).join(", ")||"none";n.push(`| ${t.duration.toFixed(0)}ms | ${t.renderStart.toFixed(0)}ms | ${e} |`)}}if(e.recentSamples.length>0){const t=e.recentSamples.slice(-10);n.push("",`### Recent Frame Times (last ${t.length} samples)`),n.push(`\`${t.map(e=>e.frameTime.toFixed(1)).join(" → ")} ms\``);const i=t.reduce((e,t)=>e+t.frameTime,0)/t.length,s=t.filter(e=>e.frameTime>2*i);s.length>0&&n.push(`⚠ ${s.length} frame time spike(s) detected (>2x average)`)}return n.filter(e=>""!==e).join("\n")}(this.buildSnapshot())}updateConfig(e){this.config={...this.config,...e},e.bufferSize&&e.bufferSize!==this.ringBuffer.capacity&&(this.ringBuffer=new o(e.bufferSize))}exposeGlobalAPI(){window.__funpixelProfiler={start:()=>this.start(),stop:()=>this.stop(),isRunning:()=>this.isRunning,getSnapshot:()=>this.buildSnapshot(),getReport:()=>this.getReport()}}log(e,t="log"){(this.config.debug||"log"!==t)&&console[t](`[Funpixel Profiler] ${e}`)}destroy(){this.stop(),this.gpuTimer?.destroy(),this.messages.destroy(),delete window.__funpixelProfiler}}const m={0:"BasicShadowMap",1:"PCFShadowMap",2:"PCFSoftShadowMap",3:"VSMShadowMap"},u={0:"NoToneMapping",1:"LinearToneMapping",2:"ReinhardToneMapping",3:"CineonToneMapping",4:"ACESFilmicToneMapping",5:"CustomToneMapping",6:"AgXToneMapping",7:"NeutralToneMapping"};class d extends c{engineType="threejs";scene=null;renderer=null;camera=null;originalRender=null;cachedTextureBytes=0;cachedGeometryBytes=0;constructor(e){super(e),this.init()}collectRenderStats(){if(!this.renderer)return{};const e=this.renderer.info,t=e.render,i=e.memory,s=e.programs,r=this.cachedTextureBytes&&isFinite(this.cachedTextureBytes)?this.cachedTextureBytes:512*i.textures*512*4,n=this.cachedGeometryBytes&&isFinite(this.cachedGeometryBytes)?this.cachedGeometryBytes:50*i.geometries*1024;return{drawCalls:t.calls,triangles:t.triangles,points:t.points,lines:t.lines,textureCount:i.textures,textureBytes:r,geometryCount:i.geometries,geometryBytes:n,programCount:s?.length??0}}collectSceneStats(){if(!this.scene)return{totalObjects:0,visibleObjects:0,lightsCount:0,camerasCount:0};let e=0,t=0,i=0,s=0,r=!1;const n=new Set,a=new Set;let o=0,l=0;const h=[this.scene];for(;h.length>0;){const g=h.pop();e++,g.visible&&t++,g.isLight&&i++,g.isCamera&&(s++,g===this.camera&&(r=!0)),g.geometry&&!n.has(g.geometry)&&(n.add(g.geometry),o+=this.computeGeometryBytes(g.geometry));const c=Array.isArray(g.material)?g.material:g.material?[g.material]:[];for(const e of c){const t=[e.map,e.normalMap,e.roughnessMap,e.metalnessMap,e.emissiveMap,e.aoMap,e.envMap];for(const e of t)e&&!a.has(e)&&(a.add(e),l+=this.computeTextureBytes(e))}for(let e=g.children.length-1;e>=0;e--)h.push(g.children[e])}return this.camera&&!r&&s++,this.cachedTextureBytes=l,this.cachedGeometryBytes=o,{totalObjects:e,visibleObjects:t,lightsCount:i,camerasCount:s}}computeGeometryBytes(e){let t=0;if(e.attributes)for(const i of Object.values(e.attributes))i.array&&"byteLength"in i.array?t+=i.array.byteLength||0:i.count&&i.itemSize&&(t+=i.count*i.itemSize*4);return e.index?.array&&"byteLength"in e.index.array?t+=e.index.array.byteLength||0:e.index?.count&&(t+=4*e.index.count),t||0}computeTextureBytes(e){const t=e.image||e.source?.data;if(t?.width&&t?.height){return t.width*t.height*4||0}return 1048576}hookRenderLoop(){if(!this.renderer||this.originalRender)return;this.originalRender=this.renderer.render.bind(this.renderer);const e=this;this.renderer.render=(t,i)=>{e.gpuTimer?.beginFrame();const s=performance.now();e.originalRender(t,i);const r=performance.now()-s;e.gpuTimer?.endFrame(),e.onFrameEnd(r)},this.log("Hooked renderer.render() for frame timing")}unhookRenderLoop(){this.renderer&&this.originalRender&&(this.renderer.render=this.originalRender,this.originalRender=null,this.log("Unhooked renderer.render()"))}isEngineReady(){return!(!window.__THREEJS_RENDERER__||!window.__THREEJS_SCENE__||!window.__THREEJS_CAMERA__&&!this.findCamera(window.__THREEJS_SCENE__))}getGLContext(){if(!this.renderer)return null;if(this.renderer.getContext)try{return this.renderer.getContext()}catch{}const e=this.renderer.domElement;return e.getContext("webgl2",{failIfMajorPerformanceCaveat:!1})||e.getContext("webgl",{failIfMajorPerformanceCaveat:!1})}getCanvas(){return this.renderer?.domElement??null}getEngineInfo(){const e=this.renderer,t=e?.capabilities,i=e?.domElement,s=this.getGLContext(),r=t?.isWebGL2??s instanceof WebGL2RenderingContext,n=[];if(s){const e=s.getSupportedExtensions();if(e){const t=["EXT_disjoint_timer_query","EXT_disjoint_timer_query_webgl2","OES_texture_float","OES_texture_half_float","WEBGL_compressed_texture_s3tc","WEBGL_compressed_texture_astc","EXT_texture_filter_anisotropic","WEBGL_draw_buffers","OES_element_index_uint"];for(const i of t)e.includes(i)&&n.push(i)}}return{name:"Three.js",version:window.THREE?.REVISION?`r${window.THREE.REVISION}`:"unknown",renderer:r?"WebGL2":"WebGL",canvasWidth:i?.width??0,canvasHeight:i?.height??0,pixelRatio:e?.getPixelRatio()??1,extensions:n,maxTextureSize:t?.maxTextureSize??(s?s.getParameter(s.MAX_TEXTURE_SIZE):void 0),antialias:s?!!s.getContextAttributes()?.antialias:void 0,shadows:e?.shadowMap?{enabled:e.shadowMap.enabled,type:void 0!==e.shadowMap.type?m[e.shadowMap.type]:void 0}:void 0,toneMapping:void 0!==e?.toneMapping?u[e.toneMapping]:void 0}}getHotObjects(){if(!this.scene)return null;const e=[],t=[this.scene];for(;t.length>0;){const i=t.pop();if(i.isMesh||i.isSkinnedMesh||i.isInstancedMesh||i.isSprite||i.isPoints||i.isLine){const t=i.geometry;let s=0;t&&(t.index?s=(t.index.count??0)/3:t.attributes?.position&&(s=(t.attributes.position.count??0)/3),i.isInstancedMesh&&i.count&&(s*=i.count));let r=0;const n=Array.isArray(i.material)?i.material:i.material?[i.material]:[];for(const e of n){const t=[e.map,e.normalMap,e.roughnessMap,e.metalnessMap,e.emissiveMap,e.aoMap,e.envMap];for(const e of t)if(e){const t=e.image||e.source?.data;t?.width&&t?.height&&(r+=t.width*t.height*4)}}e.push({name:i.name||i.type,type:i.type,triangles:s,drawCalls:i.isInstancedMesh?1:n.length||1,textureBytes:r,visible:i.visible,position:{x:i.position.x,y:i.position.y,z:i.position.z}})}for(let e=i.children.length-1;e>=0;e--)t.push(i.children[e])}return e.sort((e,t)=>t.triangles-e.triangles),e.slice(0,20)}onEngineReady(){this.renderer=window.__THREEJS_RENDERER__,this.scene=window.__THREEJS_SCENE__,this.camera=window.__THREEJS_CAMERA__||this.findCamera(this.scene),this.log(`Three.js ${window.THREE?.REVISION?"r"+window.THREE.REVISION:""} detected`),this.log(`Scene: ${this.scene.children.length} top-level objects`),super.onEngineReady()}findCamera(e){if(!e)return null;const t=[e];for(;t.length>0;){const e=t.pop();if(e.isCamera)return e;for(const i of e.children)t.push(i)}return null}}function p(){new d({debug:!0})}return"loading"===document.readyState?document.addEventListener("DOMContentLoaded",p):p(),e.ThreeJsProfiler=d,e}({});
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { deltaE, lab, palette } from "../score/measure.js";
|
|
2
|
+
const DEG = Math.PI / 180;
|
|
3
|
+
const r1 = (v) => Math.round(v * 10) / 10;
|
|
4
|
+
const r2 = (v) => Math.round(v * 100) / 100;
|
|
5
|
+
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
6
|
+
const fmt = (v) => `(${v.map((x) => r1(x)).join(', ')})`;
|
|
7
|
+
export function horizonAt(pitch, vfov) {
|
|
8
|
+
return 0.5 - 0.5 * Math.tan(pitch) / Math.tan((vfov * DEG) / 2);
|
|
9
|
+
}
|
|
10
|
+
export function pitchFor(h, vfov) {
|
|
11
|
+
return Math.atan((0.5 - h) * 2 * Math.tan((vfov * DEG) / 2));
|
|
12
|
+
}
|
|
13
|
+
export function fovFor(vfov, k) {
|
|
14
|
+
return (2 * Math.atan(Math.tan((vfov * DEG) / 2) / k)) / DEG;
|
|
15
|
+
}
|
|
16
|
+
const hfovOf = (vfov, aspect) => (2 * Math.atan(Math.tan((vfov * DEG) / 2) * aspect)) / DEG;
|
|
17
|
+
export const HORIZON_TRUST = 0.2;
|
|
18
|
+
export const YAW_GAIN = 0.5;
|
|
19
|
+
export const CLEARANCE = 0.4;
|
|
20
|
+
export function framingK(d) {
|
|
21
|
+
if (d.hero)
|
|
22
|
+
return d.hero.target / d.hero.capture;
|
|
23
|
+
return d.zoom >= 1.12 || d.zoom <= 0.9 ? d.zoom : null;
|
|
24
|
+
}
|
|
25
|
+
export const LENS = { min: 22, max: 75, step: 1.25 };
|
|
26
|
+
export function cameraMoves(d, cam) {
|
|
27
|
+
if (!cam)
|
|
28
|
+
return [];
|
|
29
|
+
return cam.kind === '2d' ? moves2d(d, cam) : moves3d(d, cam);
|
|
30
|
+
}
|
|
31
|
+
function moves3d(d, cam) {
|
|
32
|
+
const out = [];
|
|
33
|
+
const sp = cam.shotParams ?? null;
|
|
34
|
+
const vfov = sp?.fov ?? cam.fov ?? null;
|
|
35
|
+
if (vfov === null)
|
|
36
|
+
return out;
|
|
37
|
+
const aspect = cam.aspect ?? 16 / 9;
|
|
38
|
+
const k = framingK(d);
|
|
39
|
+
let fov = vfov, distK = 1;
|
|
40
|
+
if (k !== null && Math.abs(Math.log(k)) > Math.log(1.08)) {
|
|
41
|
+
const lensK = clamp(k, 1 / LENS.step, LENS.step);
|
|
42
|
+
fov = clamp(fovFor(vfov, lensK), LENS.min, LENS.max);
|
|
43
|
+
const got = Math.tan((vfov * DEG) / 2) / Math.tan((fov * DEG) / 2);
|
|
44
|
+
distK = got / k;
|
|
45
|
+
}
|
|
46
|
+
const ht = d.horizon.target, hc = d.horizon.capture;
|
|
47
|
+
let horizonNote = null;
|
|
48
|
+
const pitchToward = (pitch, lens) => {
|
|
49
|
+
if (ht === null)
|
|
50
|
+
return pitch;
|
|
51
|
+
if (hc !== null && Math.abs(hc - horizonAt(pitch, vfov)) > HORIZON_TRUST) {
|
|
52
|
+
horizonNote = `the read skyline (${Math.round(hc * 100)}% down) is not where this camera's pitch puts the horizon (${Math.round(horizonAt(pitch, vfov) * 100)}%): an edge, not a horizon, so no tilt from it`;
|
|
53
|
+
return pitch;
|
|
54
|
+
}
|
|
55
|
+
if (hc === null) {
|
|
56
|
+
horizonNote = `a skyline is read in the target only (${Math.round(ht * 100)}% down), none in the capture: tilt by eye if the target's is a true horizon`;
|
|
57
|
+
return pitch;
|
|
58
|
+
}
|
|
59
|
+
if (Math.abs(ht - hc) < 0.06)
|
|
60
|
+
return pitch;
|
|
61
|
+
return pitchFor(horizonAt(pitch, lens) + (ht - hc), lens);
|
|
62
|
+
};
|
|
63
|
+
if (sp) {
|
|
64
|
+
const pitch = Math.atan2(sp.height, sp.distance), reach = Math.hypot(sp.distance, sp.height);
|
|
65
|
+
const want = pitchToward(pitch, fov);
|
|
66
|
+
const newReach = reach * distK;
|
|
67
|
+
const dist = newReach * Math.cos(want), height = newReach * Math.sin(want);
|
|
68
|
+
const base = cam.source;
|
|
69
|
+
if (Math.abs(fov - vfov) >= 1)
|
|
70
|
+
out.push({ param: `${base}.fov`, from: r1(vfov), to: r1(fov), closes: d.hero ? 'hero' : 'composition', why: `frame ×${r2(k)} ${k > 1 ? 'tighter' : 'wider'}${d.hero ? ` (the hero is ${Math.round(d.hero.capture * 100)}% of the height, the target's ${Math.round(d.hero.target * 100)}%)` : ' (the edge fit of the capture over the target)'}` });
|
|
71
|
+
if (Math.abs(height - sp.height) >= 0.1)
|
|
72
|
+
out.push({ param: `${base}.height`, from: r2(sp.height), to: r2(height), closes: 'composition', why: ht !== null ? `the horizon at ${Math.round(ht * 100)}% down the frame, as the target's (pitch ${r1(pitch / DEG)}° → ${r1(want / DEG)}° down at the same reach)` : `the same pitch at ${distK > 1 ? 'a longer' : 'a shorter'} reach` });
|
|
73
|
+
if (Math.abs(dist - sp.distance) >= 0.1)
|
|
74
|
+
out.push({ param: `${base}.distance`, from: r2(sp.distance), to: r2(dist), closes: 'composition', why: distK !== 1 ? `the rest of the framing is distance: the reach ×${r2(distK)} (the lens moves at most ×${LENS.step} a round, within ${LENS.min}–${LENS.max}°)` : 'keeps the reach while the pitch changes' });
|
|
75
|
+
const yaw = yawMove(d, fov, aspect);
|
|
76
|
+
if (horizonNote)
|
|
77
|
+
out.push({ param: 'note', from: '', to: '', closes: 'composition', why: horizonNote });
|
|
78
|
+
if (yaw !== null)
|
|
79
|
+
out.push({ param: `${base}.yaw`, from: r2(sp.yaw ?? 0), to: r2((sp.yaw ?? 0) + yaw), closes: 'composition', why: `the scene sits ${Math.round(Math.abs(d.pan.x) * 100)}% of the width to the ${d.pan.x > 0 ? 'left' : 'right'} of the target's: turn ${yaw > 0 ? 'left' : 'right'} ${r1(Math.abs(yaw) / DEG)}°` });
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
if (!cam.position || !cam.target) {
|
|
83
|
+
if (Math.abs(fov - vfov) >= 1)
|
|
84
|
+
out.push({ param: 'camera.fov', from: r1(vfov), to: r1(fov), closes: 'composition', why: `frame ×${r2(k)} ${k > 1 ? 'tighter' : 'wider'}` });
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
const P = cam.position, T0 = cam.target;
|
|
88
|
+
const L = [T0[0] - P[0], T0[1] - P[1], T0[2] - P[2]];
|
|
89
|
+
const reach = Math.hypot(...L), flat = Math.hypot(L[0], L[2]) || 1e-6;
|
|
90
|
+
const pitch = Math.atan2(-L[1], flat);
|
|
91
|
+
const vt = vanishTurn(d, vfov, aspect);
|
|
92
|
+
const yaw = vt ? (Math.abs(vt.left) >= 0.5 * DEG ? vt.left : null) : yawMove(d, fov, aspect);
|
|
93
|
+
const want = vt ? pitch - vt.up : pitchToward(pitch, fov);
|
|
94
|
+
let fx = L[0] / flat, fz = L[2] / flat;
|
|
95
|
+
if (yaw !== null) {
|
|
96
|
+
const c = Math.cos(yaw), s2 = Math.sin(yaw);
|
|
97
|
+
[fx, fz] = [fx * c + fz * s2, -fx * s2 + fz * c];
|
|
98
|
+
}
|
|
99
|
+
const dir = [fx * Math.cos(want), -Math.sin(want), fz * Math.cos(want)];
|
|
100
|
+
const turned = yaw !== null || Math.abs(want - pitch) >= 0.3 * DEG;
|
|
101
|
+
const T = turned ? [P[0] + dir[0] * reach, P[1] + dir[1] * reach, P[2] + dir[2] * reach] : T0;
|
|
102
|
+
const roomBehind = cam.room?.behind ?? null, roomAbove = cam.room?.above ?? null;
|
|
103
|
+
let nr = reach * distK, boxed = false;
|
|
104
|
+
if (roomBehind !== null && nr > reach + Math.max(0, roomBehind - CLEARANCE)) {
|
|
105
|
+
nr = reach + Math.max(0, roomBehind - CLEARANCE);
|
|
106
|
+
boxed = true;
|
|
107
|
+
}
|
|
108
|
+
const np = [T[0] - dir[0] * nr, T[1] - dir[1] * nr, T[2] - dir[2] * nr];
|
|
109
|
+
if (roomAbove !== null && np[1] > P[1] + Math.max(0, roomAbove - CLEARANCE)) {
|
|
110
|
+
np[1] = P[1] + Math.max(0, roomAbove - CLEARANCE);
|
|
111
|
+
boxed = true;
|
|
112
|
+
}
|
|
113
|
+
if (Math.abs(fov - vfov) >= 1)
|
|
114
|
+
out.push({ param: 'camera.fov', from: r1(vfov), to: r1(fov), closes: d.hero ? 'hero' : 'composition', why: `frame ×${r2(k)} ${k > 1 ? 'tighter' : 'wider'}${d.hero ? ` (hero ${Math.round(d.hero.capture * 100)}% of the height, target ${Math.round(d.hero.target * 100)}%)` : ''}` });
|
|
115
|
+
if (turned) {
|
|
116
|
+
const how = [yaw !== null ? `turn ${yaw > 0 ? 'left' : 'right'} ${r1(Math.abs(yaw) / DEG)}°` : '', Math.abs(want - pitch) >= 0.3 * DEG ? `tilt ${want < pitch ? 'up' : 'down'} ${r1(Math.abs(want - pitch) / DEG)}°` : ''].filter(Boolean).join(' and ');
|
|
117
|
+
const from = vt ? `the lines meet ${Math.round(d.vanish.capture.x * 100)}% across, ${Math.round(d.vanish.capture.y * 100)}% down; the target's at ${Math.round(d.vanish.target.x * 100)}%, ${Math.round(d.vanish.target.y * 100)}%` : yaw !== null ? `the scene sits ${Math.round(Math.abs(d.pan.x) * 100)}% of the width to the ${d.pan.x > 0 ? 'left' : 'right'} of the target's` : `the horizon to ${Math.round((ht ?? 0) * 100)}% down`;
|
|
118
|
+
out.push({ param: 'camera.lookAt', from: fmt(T0), to: fmt(T), closes: 'composition', why: `${from}: ${how}, in place` });
|
|
119
|
+
}
|
|
120
|
+
const moved = Math.hypot(np[0] - P[0], np[1] - P[1], np[2] - P[2]);
|
|
121
|
+
if (moved >= 0.1)
|
|
122
|
+
out.push({ param: 'camera.position', from: fmt(P), to: fmt(np), closes: 'composition', why: `along the view, ${r2(nr / reach)}× the reach (the lens moves at most ×${LENS.step} a round)${boxed ? `; held inside the room (${roomBehind !== null ? `${r1(roomBehind)} m free behind` : ''}${roomBehind !== null && roomAbove !== null ? ', ' : ''}${roomAbove !== null ? `${r1(roomAbove)} m above` : ''}): the rest of a wider frame is the lens, next round` : ''}` });
|
|
123
|
+
if (horizonNote)
|
|
124
|
+
out.push({ param: 'note', from: '', to: '', closes: 'composition', why: horizonNote });
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
export function vanishTurn(d, vfov, aspect) {
|
|
128
|
+
if (!d.vanish)
|
|
129
|
+
return null;
|
|
130
|
+
const th = Math.tan((hfovOf(vfov, aspect) * DEG) / 2), tv = Math.tan((vfov * DEG) / 2);
|
|
131
|
+
const ang = (u, t) => Math.atan(u * t);
|
|
132
|
+
return {
|
|
133
|
+
left: ang(2 * d.vanish.target.x - 1, th) - ang(2 * d.vanish.capture.x - 1, th),
|
|
134
|
+
up: ang(2 * d.vanish.target.y - 1, tv) - ang(2 * d.vanish.capture.y - 1, tv),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function yawMove(d, vfov, aspect) {
|
|
138
|
+
if (Math.abs(d.pan.x) < 0.05)
|
|
139
|
+
return null;
|
|
140
|
+
return YAW_GAIN * Math.atan(2 * d.pan.x * Math.tan((hfovOf(vfov, aspect) * DEG) / 2));
|
|
141
|
+
}
|
|
142
|
+
function moves2d(d, cam) {
|
|
143
|
+
const out = [];
|
|
144
|
+
const z = cam.zoom ?? 1, [w, h] = cam.viewport ?? [1280, 720], [ox, oy] = cam.offset ?? [0, 0];
|
|
145
|
+
const k = framingK(d);
|
|
146
|
+
if (k !== null && Math.abs(Math.log(k)) > Math.log(1.08))
|
|
147
|
+
out.push({ param: `${cam.source}.scale`, from: r2(z), to: r2(z * k), closes: d.hero ? 'hero' : 'composition', why: `frame ×${r2(k)} ${k > 1 ? 'tighter' : 'wider'}${d.hero ? ` (the hero ${Math.round(d.hero.capture * 100)}% of the height, the target's ${Math.round(d.hero.target * 100)}%)` : ''}` });
|
|
148
|
+
const dx = Math.abs(d.pan.x) >= 0.05 ? d.pan.x * w : 0;
|
|
149
|
+
const dy = Math.abs(d.pan.y) >= 0.05 ? d.pan.y * h : 0;
|
|
150
|
+
if (dx || dy)
|
|
151
|
+
out.push({ param: `${cam.source}.position`, from: `(${Math.round(ox)}, ${Math.round(oy)})`, to: `(${Math.round(ox + dx)}, ${Math.round(oy + dy)})`, closes: 'composition', why: `the scene moves ${dx ? `${Math.round(Math.abs(dx))} px ${dx > 0 ? 'right' : 'left'}` : ''}${dx && dy ? ' and ' : ''}${dy ? `${Math.round(Math.abs(dy))} px ${dy > 0 ? 'down' : 'up'}` : ''} to sit where the target has it` });
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
const lin = (c) => { const s = c / 255; return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4; };
|
|
155
|
+
export function meanLuminance(p) {
|
|
156
|
+
let s = 0;
|
|
157
|
+
const n = p.width * p.height;
|
|
158
|
+
for (let i = 0; i < n; i++)
|
|
159
|
+
s += 0.2126 * lin(p.data[i * 4]) + 0.7152 * lin(p.data[i * 4 + 1]) + 0.0722 * lin(p.data[i * 4 + 2]);
|
|
160
|
+
return n ? s / n : 0;
|
|
161
|
+
}
|
|
162
|
+
export function labToHex([L, a, b]) {
|
|
163
|
+
const fy = (L + 16) / 116, fx = fy + a / 500, fz = fy - b / 200;
|
|
164
|
+
const inv = (t) => (t ** 3 > 0.008856 ? t ** 3 : (t - 16 / 116) / 7.787);
|
|
165
|
+
const X = inv(fx) * 0.95047, Y = inv(fy), Z = inv(fz) * 1.08883;
|
|
166
|
+
const R = 3.2406 * X - 1.5372 * Y - 0.4986 * Z, G = -0.9689 * X + 1.8758 * Y + 0.0415 * Z, B = 0.0557 * X - 0.204 * Y + 1.057 * Z;
|
|
167
|
+
const g = (c) => Math.round(255 * clamp(c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055, 0, 1));
|
|
168
|
+
return `#${[R, G, B].map((c) => g(c).toString(16).padStart(2, '0')).join('')}`;
|
|
169
|
+
}
|
|
170
|
+
export function lookMoves(capture, target, cam) {
|
|
171
|
+
const out = [];
|
|
172
|
+
const yc = meanLuminance(capture), yt = meanLuminance(target);
|
|
173
|
+
if (yc > 0 && yt > 0) {
|
|
174
|
+
const ratio = yt / yc;
|
|
175
|
+
if (ratio > 1.25 || ratio < 0.8) {
|
|
176
|
+
const say = `the target's mean light is ×${r2(ratio)} the capture's (${ratio > 1 ? 'lighter' : 'darker'})`;
|
|
177
|
+
if (cam?.exposure != null)
|
|
178
|
+
out.push({ param: 'renderer.toneMappingExposure', from: r2(cam.exposure), to: r2(cam.exposure * ratio), closes: 'palette_light', why: say });
|
|
179
|
+
else
|
|
180
|
+
out.push({ param: 'light', from: '×1', to: `×${r2(ratio)}`, closes: 'palette_light', why: `${say}: scale the key and ambient light (or the sprites' tint) by that much` });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const pc = palette(capture), pt = palette(target);
|
|
184
|
+
const near = (s, list) => list.reduce((best, x) => { const e = deltaE(s.lab, x.lab); return e < best.e ? { e, x } : best; }, { e: Infinity, x: list[0] });
|
|
185
|
+
for (const s of pt.filter((x) => x.weight >= 0.1)) {
|
|
186
|
+
const n = near(s, pc);
|
|
187
|
+
if (n.e > 18 && n.x)
|
|
188
|
+
out.push({ param: 'colour', from: labToHex(n.x.lab), to: labToHex(s.lab), closes: 'palette_light', why: `the target spends ${Math.round(s.weight * 100)}% of the frame on ${labToHex(s.lab)}; the capture's nearest is ${labToHex(n.x.lab)} (ΔE ${Math.round(n.e)}): move that surface (sky, fog, ground or light) to it` });
|
|
189
|
+
}
|
|
190
|
+
for (const s of pc.filter((x) => x.weight >= 0.12)) {
|
|
191
|
+
const n = near(s, pt);
|
|
192
|
+
if (n.e > 22 && n.x && !out.some((m) => m.from === labToHex(s.lab)))
|
|
193
|
+
out.push({ param: 'colour', from: labToHex(s.lab), to: labToHex(n.x.lab), closes: 'palette_light', why: `the capture spends ${Math.round(s.weight * 100)}% of the frame on ${labToHex(s.lab)}, a colour the target does not use (nearest ${labToHex(n.x.lab)}, ΔE ${Math.round(n.e)})` });
|
|
194
|
+
}
|
|
195
|
+
return out.slice(0, 4);
|
|
196
|
+
}
|
|
197
|
+
const REGION = ['top left', 'top', 'top right', 'left', 'centre', 'right', 'bottom left', 'bottom', 'bottom right'];
|
|
198
|
+
function busyThirds(p, spread = 18) {
|
|
199
|
+
const out = new Array(9).fill(0), n = new Array(9).fill(0);
|
|
200
|
+
const TX = 16, TY = 9;
|
|
201
|
+
for (let ty = 0; ty < TY; ty++)
|
|
202
|
+
for (let tx = 0; tx < TX; tx++) {
|
|
203
|
+
let lo = 255, hi = 0;
|
|
204
|
+
for (let y = Math.floor((ty * p.height) / TY); y < Math.floor(((ty + 1) * p.height) / TY); y++)
|
|
205
|
+
for (let x = Math.floor((tx * p.width) / TX); x < Math.floor(((tx + 1) * p.width) / TX); x++) {
|
|
206
|
+
const i = (y * p.width + x) * 4, v = 0.299 * p.data[i] + 0.587 * p.data[i + 1] + 0.114 * p.data[i + 2];
|
|
207
|
+
lo = Math.min(lo, v);
|
|
208
|
+
hi = Math.max(hi, v);
|
|
209
|
+
}
|
|
210
|
+
const r = Math.min(2, Math.floor((ty * 3) / TY)) * 3 + Math.min(2, Math.floor((tx * 3) / TX));
|
|
211
|
+
n[r]++;
|
|
212
|
+
if (hi - lo > spread)
|
|
213
|
+
out[r]++;
|
|
214
|
+
}
|
|
215
|
+
return out.map((v, i) => (n[i] ? v / n[i] : 0));
|
|
216
|
+
}
|
|
217
|
+
export function densityMoves(capture, target) {
|
|
218
|
+
const c = busyThirds(capture), t = busyThirds(target);
|
|
219
|
+
const bare = REGION.filter((_, i) => t[i] - c[i] >= 0.35), busy = REGION.filter((_, i) => c[i] - t[i] >= 0.35);
|
|
220
|
+
const out = [];
|
|
221
|
+
const pct = (xs) => Math.round((xs.reduce((a, b) => a + b, 0) / xs.length) * 100);
|
|
222
|
+
if (bare.length)
|
|
223
|
+
out.push({ param: 'dressing', from: `${pct(c)}% of the frame with detail`, to: `${pct(t)}%`, closes: 'density', why: `the target carries detail where the capture is bare: ${bare.join(', ')} — props, texture or set dressing there` });
|
|
224
|
+
if (busy.length)
|
|
225
|
+
out.push({ param: 'dressing', from: busy.join(', '), to: 'quieter', closes: 'density', why: `the capture is busy where the target rests: ${busy.join(', ')}` });
|
|
226
|
+
return out;
|
|
227
|
+
}
|
|
228
|
+
export function fixesFor(o) {
|
|
229
|
+
const all = [...(o.delta ? cameraMoves(o.delta, o.cam) : []), ...lookMoves(o.capture, o.target, o.cam), ...densityMoves(o.capture, o.target)];
|
|
230
|
+
const rank = (m) => (o.gaps.includes(m.closes) ? 0 : 1);
|
|
231
|
+
return all.map((m, i) => ({ m, i })).sort((a, b) => rank(a.m) - rank(b.m) || a.i - b.i).map((x) => x.m);
|
|
232
|
+
}
|
|
233
|
+
export const moveLine = (m) => `${m.param} ${m.from} → ${m.to} — ${m.why}`;
|
|
234
|
+
export { lab };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export const READ_CAMERA_JS = `(() => { try {
|
|
2
|
+
const W = window, out = (o) => JSON.stringify(o);
|
|
3
|
+
if (typeof W.__FPX_CAMERA__ === 'function') { const c = W.__FPX_CAMERA__(); if (c && typeof c === 'object') return out(c); }
|
|
4
|
+
const cam = W.__THREEJS_CAMERA__ || (W.camera && W.camera.isPerspectiveCamera ? W.camera : null);
|
|
5
|
+
if (cam && cam.isPerspectiveCamera) {
|
|
6
|
+
cam.updateMatrixWorld && cam.updateMatrixWorld();
|
|
7
|
+
const p = cam.getWorldPosition ? cam.getWorldPosition(new cam.position.constructor()) : cam.position;
|
|
8
|
+
const d = cam.getWorldDirection ? cam.getWorldDirection(new cam.position.constructor()) : null;
|
|
9
|
+
let hy = 0;
|
|
10
|
+
const scene = W.__THREEJS_SCENE__;
|
|
11
|
+
const hero = scene && scene.getObjectByName ? scene.getObjectByName('player') : null;
|
|
12
|
+
if (hero && hero.getWorldPosition) hy = hero.getWorldPosition(new cam.position.constructor()).y + 1;
|
|
13
|
+
let t = null;
|
|
14
|
+
if (d) { const k = Math.abs(d.y) > 1e-3 ? (hy - p.y) / d.y : -1; const s = k > 0.5 && k < 200 ? k : 10; t = [p.x + d.x * s, p.y + d.y * s, p.z + d.z * s]; }
|
|
15
|
+
const r = W.__THREEJS_RENDERER__;
|
|
16
|
+
// Room behind and above the eye, when the page offers three.js to cast with: a pull-back never leaves the room.
|
|
17
|
+
let room = null;
|
|
18
|
+
try { const T3 = W.THREE; if (T3 && scene && d) { const rc = new T3.Raycaster(); const free = (dir) => { rc.set(p, dir); rc.far = 200; const hit = rc.intersectObjects(scene.children, true).find((h) => h.object && h.object.isMesh && h.object.visible); return hit ? hit.distance : null; };
|
|
19
|
+
// Behind: the frustum's centre and its four edges cast backwards, each hit projected on the view axis (a wall with a
|
|
20
|
+
// doorway on the axis still frames the shot, so the centre ray alone overstates the room; one game's vestibule).
|
|
21
|
+
const back = d.clone().negate(), up = new T3.Vector3(0, 1, 0), right = new T3.Vector3().crossVectors(d, up).normalize(), up2 = new T3.Vector3().crossVectors(right, d).normalize();
|
|
22
|
+
const tv = Math.tan(cam.fov * Math.PI / 360), th = tv * (cam.aspect || 1.78);
|
|
23
|
+
let behind = null;
|
|
24
|
+
for (const [a, b] of [[0, 0], [th, 0], [-th, 0], [0, tv], [0, -tv]]) { const e = back.clone().addScaledVector(right, a).addScaledVector(up2, b).normalize(); const h = free(e); if (h !== null) { const along = h * e.dot(back); behind = behind === null ? along : Math.min(behind, along); } }
|
|
25
|
+
room = { behind, above: free(up) }; } } catch (e) { room = null; }
|
|
26
|
+
return out({ kind: '3d', source: 'the three.js camera', room, position: [p.x, p.y, p.z], target: t, fov: cam.fov / (cam.zoom || 1) === cam.fov ? cam.fov : 2 * Math.atan(Math.tan(cam.fov * Math.PI / 360) / (cam.zoom || 1)) * 180 / Math.PI, aspect: cam.aspect, exposure: r && typeof r.toneMappingExposure === 'number' ? r.toneMappingExposure : null });
|
|
27
|
+
}
|
|
28
|
+
const app = W.__PIXI_APP__;
|
|
29
|
+
if (app && app.stage) {
|
|
30
|
+
const kids = app.stage.children || [];
|
|
31
|
+
const world = kids.find((c) => c.label === 'world' || c.name === 'world') || kids[0];
|
|
32
|
+
if (world) return out({ kind: '2d', source: 'the world container (' + (world.label || world.name || 'stage child 0') + ')', zoom: world.scale ? world.scale.x : 1, offset: [world.position ? world.position.x : 0, world.position ? world.position.y : 0], viewport: [innerWidth, innerHeight] });
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
} catch (e) { return null; } })()`;
|
|
36
|
+
export function parseCamera(raw) {
|
|
37
|
+
if (typeof raw !== 'string')
|
|
38
|
+
return null;
|
|
39
|
+
let c;
|
|
40
|
+
try {
|
|
41
|
+
c = JSON.parse(raw);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
if (!c || (c.kind !== '3d' && c.kind !== '2d'))
|
|
47
|
+
return null;
|
|
48
|
+
const v3 = (x) => (Array.isArray(x) && x.length === 3 && x.every((n) => Number.isFinite(n)) ? [x[0], x[1], x[2]] : undefined);
|
|
49
|
+
const num = (x) => (Number.isFinite(x) ? Number(x) : undefined);
|
|
50
|
+
const sp = c.shotParams && typeof c.shotParams === 'object' && [c.shotParams.distance, c.shotParams.height, c.shotParams.fov].every(Number.isFinite)
|
|
51
|
+
? { distance: c.shotParams.distance, height: c.shotParams.height, fov: c.shotParams.fov, ...(Number.isFinite(c.shotParams.lookHeight) ? { lookHeight: c.shotParams.lookHeight } : {}), ...(Number.isFinite(c.shotParams.yaw) ? { yaw: c.shotParams.yaw } : {}) }
|
|
52
|
+
: null;
|
|
53
|
+
const read = { kind: c.kind, source: typeof c.source === 'string' ? c.source : c.kind === '3d' ? 'the camera' : 'the world', shot: typeof c.shot === 'string' ? c.shot : null, position: v3(c.position), target: v3(c.target), fov: num(c.fov), aspect: num(c.aspect), shotParams: sp, zoom: num(c.zoom), offset: Array.isArray(c.offset) && c.offset.length === 2 ? [Number(c.offset[0]), Number(c.offset[1])] : undefined, viewport: Array.isArray(c.viewport) && c.viewport.length === 2 ? [Number(c.viewport[0]), Number(c.viewport[1])] : undefined, exposure: num(c.exposure) ?? null, room: c.room && typeof c.room === 'object' ? { behind: num(c.room.behind) ?? null, above: num(c.room.above) ?? null } : null };
|
|
54
|
+
if (read.kind === '3d' && read.fov === undefined && !sp)
|
|
55
|
+
return null;
|
|
56
|
+
if (read.kind === '2d' && read.zoom === undefined)
|
|
57
|
+
return null;
|
|
58
|
+
return read;
|
|
59
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
export const SCORES_PATH = join('design', 'look', 'scores.json');
|
|
4
|
+
export const HISTORY_PATH = join('design', 'look', 'score-history.jsonl');
|
|
5
|
+
export const BAR_DEFAULT = 75;
|
|
6
|
+
export const STRETCH_DEFAULT = 90;
|
|
7
|
+
export const GAIN_MIN = 1;
|
|
8
|
+
export const FLAT_ROUNDS = 3;
|
|
9
|
+
const readJson = (p) => { try {
|
|
10
|
+
return JSON.parse(readFileSync(p, 'utf8'));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return null;
|
|
14
|
+
} };
|
|
15
|
+
export function appendHistory(root, record) {
|
|
16
|
+
if (!record || !Array.isArray(record.moments))
|
|
17
|
+
return;
|
|
18
|
+
const line = {
|
|
19
|
+
at: record.at ?? new Date().toISOString(), viewport: record.viewport ?? null, bar: record.bar ?? BAR_DEFAULT,
|
|
20
|
+
moments: record.moments.filter((m) => typeof m?.score === 'number').map((m) => ({ moment: m.moment, score: m.score, axes: Object.fromEntries(Object.entries(m.axes ?? {}).map(([k, v]) => [k, v?.score ?? null])), fixes: (m.fixes ?? []).slice(0, 6) })),
|
|
21
|
+
};
|
|
22
|
+
if (!line.moments.length)
|
|
23
|
+
return;
|
|
24
|
+
const p = join(root, HISTORY_PATH);
|
|
25
|
+
try {
|
|
26
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
27
|
+
appendFileSync(p, JSON.stringify(line) + '\n');
|
|
28
|
+
}
|
|
29
|
+
catch { }
|
|
30
|
+
}
|
|
31
|
+
export function readHistory(root) {
|
|
32
|
+
let text = '';
|
|
33
|
+
try {
|
|
34
|
+
text = readFileSync(join(root, HISTORY_PATH), 'utf8');
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
return text.split('\n').filter(Boolean).map((l) => { try {
|
|
40
|
+
return JSON.parse(l);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
} }).filter((l) => !!l && Array.isArray(l.moments));
|
|
45
|
+
}
|
|
46
|
+
export function meanScore(record) {
|
|
47
|
+
const s = (record?.moments ?? []).map((m) => m?.score).filter((n) => typeof n === 'number');
|
|
48
|
+
return s.length ? Math.round(s.reduce((a, b) => a + b, 0) / s.length) : null;
|
|
49
|
+
}
|
|
50
|
+
export function fixList(root, raw = readJson(join(root, SCORES_PATH))) {
|
|
51
|
+
const bar = typeof raw?.bar === 'number' ? raw.bar : BAR_DEFAULT, stretch = typeof raw?.stretch === 'number' ? raw.stretch : STRETCH_DEFAULT;
|
|
52
|
+
const list = Array.isArray(raw?.moments) ? raw.moments : [];
|
|
53
|
+
const scored = list.filter((m) => typeof m?.score === 'number');
|
|
54
|
+
const below = scored.filter((m) => m.score < bar).sort((a, b) => a.score - b.score).map((m) => ({
|
|
55
|
+
moment: String(m.moment), score: m.score, bar, stretch, gaps: Array.isArray(m.gaps) ? m.gaps : [], source: m.camera_read?.source ?? null,
|
|
56
|
+
fixes: Array.isArray(m.fixes) && m.fixes.length ? m.fixes : (m.camera?.moves ?? []).map((w) => ({ param: 'camera', from: '', to: '', closes: 'composition', why: w })),
|
|
57
|
+
}));
|
|
58
|
+
return { at: raw?.at ?? null, bar, stretch, mean: meanScore(raw), below, atBar: scored.filter((m) => m.score >= bar).map((m) => `${m.moment} ${m.score}`) };
|
|
59
|
+
}
|
|
60
|
+
export const fixLine = (f) => (f.from === '' && f.to === '' ? f.why : `${f.param} ${f.from} → ${f.to} — ${f.why}`);
|
|
61
|
+
export function fixSummary(fl, n = 3) {
|
|
62
|
+
const m = fl.below[0];
|
|
63
|
+
if (!m)
|
|
64
|
+
return null;
|
|
65
|
+
const moves = m.fixes.slice(0, n).map(fixLine);
|
|
66
|
+
return `${m.moment} ${m.score}/${m.bar}${fl.below.length > 1 ? ` (+${fl.below.length - 1} more under the bar)` : ''}: ${moves.length ? moves.join('; ') : `no move printed (gaps: ${m.gaps.join(', ') || 'none named'})`}`;
|
|
67
|
+
}
|
|
68
|
+
export function flatRounds(rounds, stage) {
|
|
69
|
+
const scored = rounds.filter((r) => r.stage === stage && r.closed_at && typeof r.accuracy === 'number');
|
|
70
|
+
let flat = 0;
|
|
71
|
+
for (let i = scored.length - 1; i >= 0; i--) {
|
|
72
|
+
const best = Math.max(-Infinity, ...scored.slice(0, i).map((r) => r.accuracy));
|
|
73
|
+
if (i > 0 && scored[i].accuracy >= best + GAIN_MIN)
|
|
74
|
+
break;
|
|
75
|
+
if (i === 0)
|
|
76
|
+
break;
|
|
77
|
+
flat++;
|
|
78
|
+
}
|
|
79
|
+
return flat;
|
|
80
|
+
}
|