Skip to content

feat(skeleton): rest pose authoring — Slice C (#557) - #911

Merged
fernandotonon merged 4 commits into
masterfrom
feat/skeleton-rest-pose-557
Jul 20, 2026
Merged

feat(skeleton): rest pose authoring — Slice C (#557)#911
fernandotonon merged 4 commits into
masterfrom
feat/skeleton-rest-pose-557

Conversation

@fernandotonon

@fernandotonon fernandotonon commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • Capture / reset / snap rest pose with animation track re-bake so world motion stays the same when the bind pose changes (SkeletonEditor + undoable SetRestPoseCommand)
  • Edit-rest mode mutes playback and routes bone-gizmo commits through rest rebake; translucent rest-pose ghost overlay on SkeletonDebug
  • Inspector Rest Pose controls (Capture / Reset / Snap + Edit rest / Rest ghost); Sentry breadcrumbs scene.skel.rest_pose.*
  • Headless tests on a 3-bone fixture for capture / reset / snap / undo

Deferred: A-pose / T-pose helpers (need Slice E L/R naming).

Closes #557

Test plan

  • UnitTests: SkeletonEditorTest.* + BoneDragReleaseTest.* (incl. CaptureRestPoseRebasesAnimation, Reset, Snap, UndoRedo, EditRestMode)
  • GUI: skinned mesh → Animation mode → Skeleton Tools → Capture Rest at a mid-frame pose; scrub anim — motion should match pre-capture
  • Reset Rest returns to imported bind
  • Snap Bone updates only the selected bone
  • Edit rest pose: drag bone gizmo (no auto-key) updates bind; undo restores
  • Rest ghost: cyan translucent joints at rest alongside animated skeleton
  • Export glTF/FBX after capture and verify bind pose in Blender (optional smoke)

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added a Rest Pose workflow for skeleton editing (capture, reset, snap) with an Edit Rest Pose mode.
    • Added a “rest-pose ghost” overlay with global visibility controls, plus UI toggles to edit rest pose and show the ghost.
    • Rest-pose edits are now undoable/redoable via a dedicated rest-pose command.
  • Bug Fixes

    • Improved bone drag release behavior in edit-rest mode to produce the correct commit result and undo/redo bind outcomes.
    • Refined skeleton debug activation and rest-ghost lifecycle so visuals are preserved/cleaned correctly.
  • Tests

    • Added/updated coverage for rest-pose capture/reset/snap, animation rebasing, ghost behavior, and commit behavior.

…#557)

Add bind-pose capture with animation re-bake so world motion is preserved,
imported-rest reset/cache, per-bone snap, edit-rest mode (gizmo commits
rest + rebake), and a translucent rest-pose ghost overlay. Inspector
controls and SetRestPoseCommand undo cover the Slice C acceptance path;
A/T-pose helpers deferred until Slice E naming.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds rest-pose capture, reset, selected-bone snapping, edit mode, undo/redo, animation rebaking, bone-drag integration, and a translucent rest-pose ghost overlay to the skeleton tools UI.

Changes

Rest pose authoring

Layer / File(s) Summary
Rest-pose model and undo commands
src/SkeletonEditor.*, src/commands/SkeletonBoneCommands.*, src/SkeletonEditor_test.cpp
Adds imported-rest caching, rest-pose TRS application, animation track rebaking, bind-buffer snapshots, capture/reset/snap operations, undoable commands, and coverage for rebasing, reset, selection, mesh baking, and undo/redo.
Bone-drag rest-pose commits
src/BoneDragRelease.*, src/TransformOperator.cpp, src/BoneDragRelease_test.cpp
Routes edit-rest and no-animation bone releases to bind commits and records explicit rest-pose changes through SetRestPoseCommand.
Rest ghost visualization and UI
src/SkeletonDebug.*, src/AnimationWidget.*, src/PropertiesPanelController.*, qml/PropertiesPanel.qml, src/Manager.cpp
Adds ghost mesh creation, update and cleanup, overlay host management, controller synchronization, forbidden-node filtering, and Rest Pose controls and actions.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

  • Issue 554 — Covers the parent rest-pose authoring epic implemented by this change.

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant PropertiesPanel
  participant SkeletonEditor
  participant SetRestPoseCommand
  participant SkeletonEntity
  PropertiesPanel->>SkeletonEditor: captureRestPoseForSelected()
  SkeletonEditor->>SetRestPoseCommand: create and push command
  SetRestPoseCommand->>SkeletonEditor: apply rest-pose operation
  SkeletonEditor->>SkeletonEntity: update rest TRS and rebake animation tracks
  SetRestPoseCommand->>SkeletonEditor: emit restPoseChanged()
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: skeleton rest-pose authoring for Slice C.
Description check ✅ Passed It includes a clear summary and test plan, though the template's Technical Details and Features/Bugfixes sections are not filled.
Linked Issues check ✅ Passed The changes implement rest-pose capture/reset/snap, edit-rest mode, ghost overlay, undo support, breadcrumbs, and tests matching #557.
Out of Scope Changes check ✅ Passed The changes appear focused on the rest-pose authoring slice and its supporting tests, with no obvious unrelated additions.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/skeleton-rest-pose-557

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@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: 1b053f1850

ℹ️ 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 thread src/SkeletonEditor.cpp
Comment on lines +1430 to +1432
if (m_editRestPoseMode == on) return;
m_editRestPoseMode = on;
applyEditRestAnimMute(on);

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 Reapply edit-rest muting after selection changes

When Edit rest pose is left enabled and the user selects a different animated entity, this setter is not invoked again and no selectionChanged path calls applyEditRestAnimMute(true) for the new selection. TransformOperator still treats every later drag as edit-rest mode, so the new entity's active animation states remain enabled and the drag can commit an animated frame into the bind pose instead of the reset bind pose; the previously selected entity also stays muted until the mode is turned off. Re-run the mute/reset when the selected skinned entity changes, or scope edit-rest mode to the entity that was muted.

Useful? React with 👍 / 👎.

Comment thread src/SkeletonEditor.cpp
Comment on lines +245 to +249
for (const auto& [name, newRest] : newRests) {
if (!skel->hasBone(name)) {
if (error) *error = QStringLiteral("Bone not found: %1").arg(QString::fromStdString(name));
return false;
}

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 Validate cached rest bones before rebaking

If the imported-rest cache was captured before a bone was renamed or deleted, Reset Rest passes stale bone names into this loop. Because the loop rebakes and updates each existing bone as it goes and only returns false when it eventually hits the missing cached bone, a reset that reports failure can still partially mutate earlier bones and animation tracks depending on the unordered iteration order. Validate all cached names before applying, or filter out missing bones before starting the rebake.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🧹 Nitpick comments (3)
src/SkeletonEditor.cpp (1)

1428-1442: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider breadcrumbs for the edit-rest and ghost toggles.

Capture/snap/reset already emit scene.skel.rest_pose.* breadcrumbs, but entering/exiting edit-rest mode and toggling the ghost overlay are user-facing actions that currently record nothing. Adding ui.action (or scene.skel.rest_pose.*) breadcrumbs here keeps the operation trail complete.
As per coding guidelines: "Track all user-facing actions and significant operations with SentryReporter::addBreadcrumb; use ui.action for toolbar/menu clicks".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/SkeletonEditor.cpp` around lines 1428 - 1442, Add
SentryReporter::addBreadcrumb calls to SkeletonEditor::setEditRestPoseMode and
setShowRestPoseGhost after each state change, using ui.action or the established
scene.skel.rest_pose category with descriptive data for entering/exiting
edit-rest mode and enabling/disabling the ghost overlay. Preserve the existing
early returns and signal/update ordering.

Source: Coding guidelines

qml/PropertiesPanel.qml (1)

3145-3179: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the file's existing themed checkbox instead of a stock CheckBox.

This file already defines InspectorCheckBox (lines 25-64) specifically to match the Inspector's dark palette (16px box + checkmark), and the Skeleton section a few lines above hand-rolls themed Rectangle-based toggles for the same reason. editRestCheck/ghostRestCheck instead use a stock Qt Quick CheckBox with only the contentItem restyled, leaving the default indicator — this will visually clash with the rest of the panel.

♻️ Suggested fix
-                CheckBox {
-                    id: editRestCheck
-                    text: "Edit rest pose"
-                    checked: SkeletonEditor.editRestPoseMode
-                    onCheckedChanged: {
-                        if (checked !== SkeletonEditor.editRestPoseMode)
-                            SkeletonEditor.editRestPoseMode = checked
-                    }
-                    contentItem: Text {
-                        text: editRestCheck.text
-                        color: PropertiesPanelController.textColor
-                        font.pixelSize: 11
-                        leftPadding: editRestCheck.indicator.width + 4
-                        verticalAlignment: Text.AlignVCenter
-                    }
-                }
+                InspectorCheckBox {
+                    id: editRestCheck
+                    text: "Edit rest pose"
+                    checked: SkeletonEditor.editRestPoseMode
+                    onCheckedChanged: {
+                        if (checked !== SkeletonEditor.editRestPoseMode)
+                            SkeletonEditor.editRestPoseMode = checked
+                    }
+                }

(same for ghostRestCheck)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qml/PropertiesPanel.qml` around lines 3145 - 3179, Replace the stock CheckBox
controls editRestCheck and ghostRestCheck with the file’s existing
InspectorCheckBox component, preserving their labels, checked bindings, and
onCheckedChanged synchronization with SkeletonEditor.editRestPoseMode and
SkeletonEditor.showRestPoseGhost. Remove the custom contentItem styling that is
only needed for the stock controls.

Source: Coding guidelines

src/SkeletonDebug.cpp (1)

120-122: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Ghost transform recompute runs every timer tick, not only when the rest pose changes.

updateGhostVisuals() allocates an std::unordered_map and walks the full bone hierarchy recursively on every onTimerTick() call while the ghost is visible — this timer fires continuously (mTimer.start(0)). The rest pose it visualizes is static except right after a capture/reset/snap/commit, so this work is wasted on nearly every frame. Consider only calling updateGhostVisuals() when the rest pose actually changes (e.g. after SetRestPoseCommand applies, or from rebuildVisuals()/showRestGhost(true)), instead of unconditionally each tick.

♻️ Suggested direction
-    if (mShowRestGhost)
-        updateGhostVisuals();
+    // updateGhostVisuals() is now invoked only when the rest pose changes
+    // (showRestGhost(true), rebuildVisuals(), and rest-pose commit/undo),
+    // not on every tick.

Also applies to: 389-418

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/SkeletonDebug.cpp` around lines 120 - 122, Remove the unconditional
updateGhostVisuals() call from onTimerTick when mShowRestGhost is true, and
invoke it only at rest-pose change points such as SetRestPoseCommand
application, rebuildVisuals(), or showRestGhost(true). Preserve ghost visibility
updates while avoiding repeated hierarchy traversal on unchanged poses.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@qml/PropertiesPanel.qml`:
- Around line 3129-3135: Update the hint Text containing “Capture the current
pose as bind...” to use PropertiesPanelController.textColor instead of
borderColor, and apply the file’s established reduced opacity for description
text so it matches the other hints.

In `@src/PropertiesPanelController.cpp`:
- Around line 1208-1226: Update setRestPoseGhostVisible so enabling the
rest-pose ghost does not activate skeleton debugging for every skinned entity.
Restrict the behavior to the currently active skeleton-debug instances, or track
and restore each entity’s prior debug state when the ghost is disabled; preserve
the existing ghost visibility update.

In `@src/SkeletonEditor.cpp`:
- Around line 1444-1460: Update the unmute branch of
SkeletonEditor::applyEditRestAnimMute so restoration depends only on
m_editRestMutedEntity and the resolved entity, not on the unused
AnimationControlController::instance() result. Keep re-enabling each recorded
animation state before clearing m_editRestMutedEntity and m_editRestMutedAnims.

---

Nitpick comments:
In `@qml/PropertiesPanel.qml`:
- Around line 3145-3179: Replace the stock CheckBox controls editRestCheck and
ghostRestCheck with the file’s existing InspectorCheckBox component, preserving
their labels, checked bindings, and onCheckedChanged synchronization with
SkeletonEditor.editRestPoseMode and SkeletonEditor.showRestPoseGhost. Remove the
custom contentItem styling that is only needed for the stock controls.

In `@src/SkeletonDebug.cpp`:
- Around line 120-122: Remove the unconditional updateGhostVisuals() call from
onTimerTick when mShowRestGhost is true, and invoke it only at rest-pose change
points such as SetRestPoseCommand application, rebuildVisuals(), or
showRestGhost(true). Preserve ghost visibility updates while avoiding repeated
hierarchy traversal on unchanged poses.

In `@src/SkeletonEditor.cpp`:
- Around line 1428-1442: Add SentryReporter::addBreadcrumb calls to
SkeletonEditor::setEditRestPoseMode and setShowRestPoseGhost after each state
change, using ui.action or the established scene.skel.rest_pose category with
descriptive data for entering/exiting edit-rest mode and enabling/disabling the
ghost overlay. Preserve the existing early returns and signal/update ordering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 41024155-d996-4dd2-b521-7c9e83fb170c

📥 Commits

Reviewing files that changed from the base of the PR and between 06e34d1 and 1b053f1.

📒 Files selected for processing (16)
  • qml/PropertiesPanel.qml
  • src/AnimationWidget.cpp
  • src/AnimationWidget.h
  • src/BoneDragRelease.cpp
  • src/BoneDragRelease.h
  • src/BoneDragRelease_test.cpp
  • src/PropertiesPanelController.cpp
  • src/PropertiesPanelController.h
  • src/SkeletonDebug.cpp
  • src/SkeletonDebug.h
  • src/SkeletonEditor.cpp
  • src/SkeletonEditor.h
  • src/SkeletonEditor_test.cpp
  • src/TransformOperator.cpp
  • src/commands/SkeletonBoneCommands.cpp
  • src/commands/SkeletonBoneCommands.h

Comment thread qml/PropertiesPanel.qml
Comment thread src/PropertiesPanelController.cpp
Comment thread src/SkeletonEditor.cpp
… reviews

Rest ghost no longer force-enables the Skeleton overlay; ghost-only hosts
stay bone-hidden and tear down when unchecked. Inspector-themed checkboxes,
edit-rest remute on selection change, safer rest-cache reset, and unmute
without depending on AnimationControlController.

Co-authored-by: Cursor <cursoragent@cursor.com>
@fernandotonon

Copy link
Copy Markdown
Owner Author

Addressed review + UX feedback:

  • Rest ghost ≠ Skeleton debug: enabling ghost no longer toggles skeleton bones on; unchecking ghost only hides the ghost (and tears down ghost-only hosts).
  • InspectorCheckBox theme for Edit rest / Rest ghost; hint text uses textColor @ 0.75 opacity.
  • Codex/CodeRabbit: validate bones before rest rebake; skip stale cache names on reset; unmute without animCtrl gate; remute edit-rest on selection change; breadcrumbs for edit-mode/ghost toggles.

build-linux failure was Qt mirror SSL during install (infra), not compile — unit-tests-linux already passed.

fernandotonon and others added 2 commits July 20, 2026 02:41
Rest-pose gizmo/snap commits now bake skinned verts into bind buffers so
the mesh stays posed after release. The rest ghost clones mesh at enable
time so it keeps the old rest while live geometry updates. Avoid
mesh->_dirtyState() so skeleton TagPoints survive commit; keep skeleton
debug visible when the overlay checkbox is checked.

Co-authored-by: Cursor <cursoragent@cursor.com>
@fernandotonon

Copy link
Copy Markdown
Owner Author

Follow-up after manual QA (rest gizmo + ghost):

Rest commit / mesh bake

  • Gizmo release and Snap Bone now bake software-skinned verts into bind buffers so the mesh stays posed (LBS at bind is identity otherwise).
  • Gizmo commits use explicit after-TRS + muted blend masks through commit; no clip rebake on gizmo path (preserves edited rest when Mixamo is enabled).
  • In-place skeleton sync (no entity->_initialise(true)) so SkeletonDebug TagPoints are not orphaned.

Rest ghost

  • Translucent blue mesh ghost uses a private Mesh::clone frozen at enable time — live rest bakes no longer move the ghost.
  • Ghost is independent of Skeleton debug checkbox; skeleton overlay stays visible after commit.
  • Skip ghost mesh entities in AnimationWidget::setRestPoseGhostVisible; forbid _restGhostRoot in Manager.

Tests

  • CommitBoneRestPoseBakesMeshVertices, CommitBoneRestPoseDoesNotDirtyMeshState, RestGhostMeshStaysAtEnableTimePoseAfterBake, updated BoneDragReleaseTest.

Merged latest master (telemetry + meshseg fixes).

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/SkeletonEditor.cpp`:
- Around line 322-326: Update the bounding-sphere radius calculation in the mesh
bounds block to use Ogre::Math::boundingRadiusFromAABB(box) instead of the
manual std::max expression, while preserving the existing mesh->_setBounds and
conditional any flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0346b810-1f6e-4ef3-a9bc-d5f920c6563c

📥 Commits

Reviewing files that changed from the base of the PR and between 2f4478f and ec486f4.

📒 Files selected for processing (13)
  • src/AnimationWidget.cpp
  • src/BoneDragRelease.cpp
  • src/BoneDragRelease.h
  • src/BoneDragRelease_test.cpp
  • src/Manager.cpp
  • src/SkeletonDebug.cpp
  • src/SkeletonDebug.h
  • src/SkeletonEditor.cpp
  • src/SkeletonEditor.h
  • src/SkeletonEditor_test.cpp
  • src/TransformOperator.cpp
  • src/commands/SkeletonBoneCommands.cpp
  • src/commands/SkeletonBoneCommands.h
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/commands/SkeletonBoneCommands.h
  • src/AnimationWidget.cpp
  • src/SkeletonEditor.h
  • src/BoneDragRelease.h
  • src/SkeletonDebug.h

Comment thread src/SkeletonEditor.cpp
Comment on lines +322 to +326
if (any) {
mesh->_setBounds(box, false);
mesh->_setBoundingSphereRadius(
std::max(box.getMaximum().length(), box.getMinimum().length()));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Ogre::Math::boundingRadiusFromAABB signature

💡 Result:

The signature for the Ogre::Math::boundingRadiusFromAABB function in the OGRE engine is as follows [1][2][3]: static Real boundingRadiusFromAABB(const AxisAlignedBox& aabb); This static method returns a Real value and accepts a constant reference to an AxisAlignedBox object as its only parameter [1][4][3]. Its purpose is to calculate the radius of a bounding sphere that is centered at the origin, based on the provided axis-aligned bounding box [1][3]. A related function, boundingRadiusFromAABBCentered, exists to calculate the radius of a sphere centered on the bounding box itself [3][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- src/SkeletonEditor.cpp excerpt ---'
sed -n '300,335p' src/SkeletonEditor.cpp

printf '\n%s\n' '--- geometric probe ---'
python3 - <<'PY'
import itertools, math

box_min = (-3, -3, 0)
box_max = (0, 0, 3)

current = max(
    math.sqrt(sum(c*c for c in box_max)),
    math.sqrt(sum(c*c for c in box_min)),
)
true_max = max(
    math.sqrt(sum(c*c for c in corner))
    for corner in itertools.product(
        [box_min[0], box_max[0]],
        [box_min[1], box_max[1]],
        [box_min[2], box_max[2]],
    )
)

print("current:", current)
print("true_max:", true_max)
PY

Repository: fernandotonon/QtMeshEditor

Length of output: 1818


Use Ogre::Math::boundingRadiusFromAABB(box) here std::max(box.getMaximum().length(), box.getMinimum().length()) can under-estimate the true radius when the AABB straddles the origin asymmetrically, which can cause culling glitches. src/SkeletonEditor.cpp:322-326

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/SkeletonEditor.cpp` around lines 322 - 326, Update the bounding-sphere
radius calculation in the mesh bounds block to use
Ogre::Math::boundingRadiusFromAABB(box) instead of the manual std::max
expression, while preserving the existing mesh->_setBounds and conditional any
flow.

@sonarqubecloud

Copy link
Copy Markdown

@fernandotonon
fernandotonon merged commit ba88c44 into master Jul 20, 2026
21 checks passed
@fernandotonon
fernandotonon deleted the feat/skeleton-rest-pose-557 branch July 20, 2026 13:59
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.

Skel: Slice C — Rest pose authoring

1 participant