feat(generation): integrate animation generation API and directional sprite records - #218
Conversation
…sprite records Replace mock animation generation logic with production API endpoints and React Query mutations to support real animation workflows in the asset editor. Introduce directional asset helper utilities, core sprite record data structures, and UI components including directional animation triggers and task status tracking. Enable end-to-end animation generation trigger, progress monitoring, and session store synchronization with complete test coverage.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…nd runtime texture loading Add unit test coverage for animated sprite canvas rendering components and texture loading error handling. Introduce SpriteSheetFrameRenderer test suite and expand SpriteSheetFrameTextureCache and AnimatedSpriteCanvasRuntime tests to verify frame cropping, missing texture skipping, and deduplication. Improve test reliability and ensure robust sprite canvas rendering state under missing or asynchronous frame texture loads.
|
@nighca |
External animation refreshes were recorded as local edits. Skip no-op refreshes, pause tracking, and rebase temporal snapshots onto the incoming server baseline. Undo now preserves generated animations while reverting local edits.
There was a problem hiding this comment.
Review: animation generation API integration
Solid migration off the mock path. The three-way animation merge, the perspective-scoped direction picker, and the texture-cache gate that stops PixiJS building textures from unloaded sources are all well-handled, and the new tests cover the interesting branches.
The findings below cluster around what happens when the Core API does not behave: a failed asset fetch, a failed run, or metadata that never made it to localStorage. Inline comments carry the detail.
Main themes
-
Fallback to mock records doesn't actually work.
loadCoreSpriteAssetWorkspacehas no error handling, andunwrapApiResponse(frontend/src/model/fetchers.ts:63-83) throws on any non-2xx. So(await loadCoreSpriteAssetWorkspace(input)) ?? getMockAssetRecord(input)inrecord.api.ts:6-7only falls back for non-numeric ids and non-sprite types — a 404 or 500 rejects the whole record query instead. -
Unbounded reconciliation retries. In
generation-runs.query.ts,handledRunIdsis set only in the terminal branches whilereconcilingRunIdsis always cleared infinally. Thecatchpath and any non-terminaldetail.statustherefore retry every poll tick (GENERATION_POLL_INTERVAL_MS = 1_000) with no cap or backoff.refreshSettledAssetspassesthrowOnError: true, so a persistently unreadable record keeps the loop alive indefinitely. -
Animation runs depend on
localStorageto stay visible.generationKindToAssetKindresolvesgenerate_animationonly viarequestedKind, which comes solely from the metadata written byrememberGenerationRunMetadata. If that write failed or the run started in another browser/tab,toGenerationRunreturnsundefinedand the run disappears from the queue and is never reconciled — so the finished animation only appears after a manual reload. Other kinds degrade vianame: request?.name ?? \New ${kind}``; animations have no equivalent.
Smaller items
pruneGenerationRequests(generation.api.ts:83) has no production caller left — the PR removed the one inlistRunsand added anassetIdparameter nothing passes. Per.agents/principle.md("remove orphans your change creates"), it and its four tests look removable. Note this also leavesforgetGenerationRunMetadataas the only cleanup, and it runs only when the editor is mounted and observes acompleted/cancelleddetail — metadata for failed runs, or runs that settle with the tab closed, stays inlocalStorageindefinitely.generationPromptis now unused infrontend/src(replaced bycreativeBrief) but remains inen-US/generation.json:46andzh-CN/generation.json:46.syncEditorSessionExternalRecordmerges onlyanimations;prompt,prototype, andnodePositionsfrom the incoming record are dropped. Since the inspector'sedit_character_prototyperuns trigger a record refetch on completion, the canvas keeps showing the stale prototype. Worth either widening the merge or renaming to reflect the animation-only scope.
Verified clean: i18n keys are complete in both en-US and zh-CN (all directions.*, frameCount, fps, sourceDuration, secondsShort, animationSummary, queueingAnimation, creativeBrief, plus the editor.json status keys), interpolation placeholders match their call sites, no dangerouslySetInnerHTML on the path that renders backend detail.error, no secrets in the diff, and no dangling references to the removed GenerateAnimationResult / GeneratedCharacterAnimation / mock-animation-generation / sprite.animation.generated.
Not verified: I could not run the test suite — pnpm install fails in this sandbox (the pinned pnpm needs a newer Node than the available v20). All findings are from static analysis and reading the surrounding code, not execution.
Settled runs could poll indefinitely when detail or record refresh requests kept failing. Track at most three reconciliation attempts and finalize completed runs before refreshing dependent caches. Generation queues now stop retrying stale runs while later server lists can rediscover active work.
Animation runs disappeared when localStorage metadata was unavailable, and the unused pruning helper no longer had a production caller. Resolve missing animation kinds from Core assets, fall back to a visible character placeholder, and remove obsolete pruning coverage. Generation queues now retain cross-tab or storage-failure runs for reconciliation.
Clearing a number input left the previous request value in state while the field appeared empty. Allow numeric draft fields to become undefined and keep the submit control disabled until validation succeeds. Animation generation settings now stay synchronized with their visible form values.
The animation form now uses the creative brief label and no longer reads the legacy generation prompt key. Remove the orphaned key from the English and Chinese generation locale files. Both locales now match the current animation generation UI contract.
|
|
||
| export const recordApi: AssetRecordApi = { | ||
| get: getMockAssetRecord, | ||
| get: async (input) => |
There was a problem hiding this comment.
这个怪怪的,get record 跟 loadCoreSpriteAssetWorkspace 语义上并不相关,record 和 core-sprite-asset-workspace 是一个东西吗?
| return record.mode === "character" || record.mode === "object"; | ||
| } | ||
|
|
||
| function mergeExternalAnimations( |
There was a problem hiding this comment.
Nit: 看上去很多复杂度是前端跟服务端(generation 逻辑)同时都会去修改 asset 内部数据引入的
如果 generation 自己不去写(甚至也不读)project/asset 数据,只提供生成能力和对生成任务状态的管理,只由前端的 editor(通过消费生成任务的状态和结果)去做 asset 数据的修改,那样可能整体会更简单些;当然这个是大的调整了,是不是确实要调整可以再看
Change Description
directional-asset.ts) and core sprite record models (core-sprite-record.ts).CreateAnimationTriggerand header generation dropdown to handle real-time task status tracking and session store updates.Implementation Approach
animation-generation.api.tsandanimation-generation.mutation.tsfor API interactions.directional-asset.tsto compute available target directions based on project/asset perspective rules.zh-CNanden-US) for animation trigger controls and task dropdown options.Related Issue
Closes #217
Testing
PUBLIC_CORE_API_BASE_URL=http://localhost/api/v1 pnpm test --run- 73 test files passed (305 tests)Checklist