Skip to content

Add native skeletal animation authoring, curves, and 3D IK - #209

Merged
SpectralDragon merged 1 commit into
mainfrom
codex/animation-authoring
Nov 7, 2026
Merged

SpectralDragon merged 1 commit into
mainfrom
codex/animation-authoring

Conversation

@SpectralDragon

@SpectralDragon SpectralDragon commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Imported skeletal clips can now be copied into project-owned animation libraries, edited on the native timeline, and combined with an ordered 3D IK stack. Studio, the editor agent and developer Tools share revision-checked edits, explicit saving and Undo/Redo. Imported GLB/glTF files remain unchanged.

Implemented:

  • Native .animlib authoring, bone/morph tracks, grouped key editing, scrubbing, clip/duration/loop controls and production curve previews.
  • A resizable model hierarchy, contextual Inspector, shared viewport and node-canvas clip/blend/additive graph.
  • Eleven easing families and temporal Bézier offsets, schema-2 persistence and quaternion-safe restrictions.
  • Two-Bone/FABRIK 3D IK after mixing/LOD, .animmod resources, current scene-marker bindings, viewport gizmos and shared agent/Tool operations.
  • Styled native controls, English/Russian localization, user guides and executable Tool examples.

Validation:

  • 89 animation tests across 11 suites passed against production modules.
  • 76 Editor/localization tests across 3 suites passed; native keyboard editing, Apply, single-step Undo/Redo, save/reopen and real Tool VM curve payloads were exercised.
  • A complete Windows distribution was staged and exercised in Studio and Play. Visible mesh captures verified curve motion and IK; measured IK reach error was 3.58e-7. A saved schema-2 library was bound and rendered in the game camera without reported scenario/script errors.
  • Localization, 27 bundled offline guides, git diff --check and the unmodified DocC temporal-curve example passed their focused checks.

This is a draft delivery of the implemented stages, not completion of the full animation roadmap. Native 2D rigs/weighted deformation/IK, spatial splines, typed animation/Auto Key of IK parameters, additional tangent modes and canvas handle dragging remain outstanding. State-machine/blend-space and remaining property/playback stages are also not included.

Full local review validation has not passed: retained attempts hit a Windows SPIRV-Cross/MSVC link failure, missing SwiftLint/analyzer prerequisites, an Editor build timeout, Windows DocC conversion failure and unavailable platform/render checks. Independent review found no remaining concrete defect in the reviewed 3D IK and temporal-curve slices but withheld full-task approval for these validation/completion gaps. CI results must be assessed before merge.

Local Git hooks were bypassed once for this draft because SwiftLint is unavailable on this host and complete local validation has not passed. GitHub CI is retained; this draft is not ready to merge.

Initial CI result: SwiftPM Test on macOS stops in Test Studio installation before the Swift tests. Five installer tests report PermissionError: Operation not permitted while preparing a temporary .app fixture. The installer/test files are unchanged by this PR. Other workflows were still pending at publication; no overall CI pass is claimed.

@SpectralDragon
SpectralDragon marked this pull request as ready for review November 6, 2026 12:43
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-06T12:48:52.561620Z c1e5a7b Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c1e5a7b2a5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +131 to +132
guard let rig, libraryIDs.insert(library.id).inserted else {
throw AssetError.message("Animation libraries need a rig and unique library IDs.")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retain a hierarchy rig for authored animations on static models

For a glTF with neither skins nor imported animations, creating a rest-pose animation library succeeds because EditorAnimationAuthoringService.importLibrary builds a hierarchy rig unconditionally, and scene binding validates against that rig. However, ModelAsset3D sets animationRig to nil for precisely these models, so scene instantiation subsequently throws here instead of playing the authored node tracks. Preserve or reconstruct the compatible hierarchy rig when installing authored animations so a successfully created and bound library can actually run.

Useful? React with 👍 / 👎.

textureSettingsModels.removeValue(forKey: documentID)
shaderGraphModels.removeValue(forKey: documentID)
animationWorkspaces.removeValue(forKey: documentID)?.cancel()
if case let .asset(asset) = closingDocument, asset.kind == .animationLibrary { try? animationService?.close(asset.relativePath) }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep animation libraries alive while model workspaces reference them

If a model workspace has an animation library attached, closing that library's saved resource tab calls service.close, which discards the shared document even though the model workspace still references it. EditorAnimationTimelineModel.isEditable then becomes false, and subsequent refreshes detach the library, interrupting editing in the still-open model tab. Check workspace ownership before closing the shared document, as releaseUnreferencedModifierDocuments already does for modifier resources.

Useful? React with 👍 / 👎.

Comment on lines +15 to +18
} else if workspace.sourceLibrary != nil || workspace.library != nil {
EditorAnimationTimeline(workspace: workspace)
} else {
Text(L10n.text("Choose an imported clip to copy, or create an animation from the rig's rest pose."))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve playback controls for animated voxel assets

Opening an animated .vox now leaves its preview permanently paused: the workspace initializes preview.playsAnimation to false, while voxel assets have no animationRig, so neither sourceLibrary nor library is populated and this branch never displays the timeline's Play control. The previous model preview explicitly enabled playback for hasVoxelAnimation; repository-wide inspection of the replacement animation views finds no equivalent voxel transport. Retain a voxel playback control rather than routing these assets into the skeletal-library empty state.

Useful? React with 👍 / 👎.

Comment on lines +108 to +111
icon("⏮", title: "Stop", id: "Stop") { model.seek(0) }
icon("‹◆", title: "Previous Key", id: "PreviousKey") { model.step(-1, byKey: true) }
icon("‹", title: "Previous Frame", id: "PreviousFrame") { model.step(-1, byKey: false) }
icon(workspace.preview.playsAnimation ? "Ⅱ" : "▶", title: "Play", id: "Play") { togglePlayback() }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use the shared icon assets and accessible transport labels

The new transport renders arbitrary Unicode strings in the system font, and its icon helper supplies only an accessibility identifier and hover text, not an accessible action name. Consequently, assistive technology receives glyph labels such as ‹◆ rather than “Previous Key,” and appearance depends on font fallback instead of the bundled icon system. AGENTS.md explicitly prohibits substituting arbitrary Unicode interface icons and requires localized tooltips and accessible names; use the existing Material Symbols helper and label each action.

AGENTS.md reference: AGENTS.md:L55-L59

Useful? React with 👍 / 👎.

@SpectralDragon
SpectralDragon merged commit 5d81182 into main Nov 7, 2026
5 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant