Skip to content

feat(pose-lib): sub-slice D5 — apply-with-mask#608

Merged
fernandotonon merged 1 commit into
masterfrom
feat/pose-lib-slice-d5-mask
May 18, 2026
Merged

feat(pose-lib): sub-slice D5 — apply-with-mask#608
fernandotonon merged 1 commit into
masterfrom
feat/pose-lib-slice-d5-mask

Conversation

@fernandotonon
Copy link
Copy Markdown
Owner

Sixth sub-slice of #521 (named-pose library). Adds the "apply only a subset of bones from this pose" operation that makes pose blending workable in practice — author a facial expression library without disturbing whatever body pose the animator already has.

What ships

PoseLibrary::applyPoseMasked(entity, name, boneFilter)QSet<QString> mask, only bones whose names appear get touched. The mask check fires before the skeleton lookup so per-bone filtering is one hash lookup per pose entry. Bones in the mask but missing on the skeleton are counted separately for the Sentry breadcrumb.

Empty mask is intentionally "no bones" (strict-filter interpretation), not "all bones". Pass the existing applyPose for "everything". Decision recorded in the header comment.

3 new tests

  • ApplyPoseMaskedTouchesOnlyListedBones — 2-bone fixture, save with both at X=7, reset to origin, apply masked to bone[0]. Assert bone[0]=7 AND bone[1]=0.
  • ApplyPoseMaskedRejectsUnknownPoseAndMissingEntity.
  • ApplyPoseMaskedWithEmptyMaskAppliesNothing — empty mask returns TRUE but touches no bone (documents the "empty = nothing" contract).

What's deferred

  • MCP apply_pose_masked. Lifting QSet<QString> through JSON-RPC is a bit clunky; defer until a real use case names the arg shape (probably a JSON array).
  • CLI flag.
  • Inspector multi-bone-pick UI (D2 territory).

🤖 Generated with Claude Code

Sixth sub-slice of #521 (named-pose library). Adds the
"apply only a subset of bones from this pose" operation that
makes pose blending workable in practice — author a facial
expression library without disturbing whatever body pose the
animator already has.

## What ships

`PoseLibrary::applyPoseMasked(entity, name, boneFilter)` —
`QSet<QString>` mask, only bones whose names appear get touched.
The mask check fires before the skeleton lookup so per-bone
filtering is one hash lookup per pose entry. Bones in the mask
but missing on the skeleton are counted separately so the
breadcrumb tells "bones applied / filtered / missing".

Empty mask is intentionally "no bones" (strict-filter
interpretation), not "all bones". Pass the existing applyPose
for "everything". Decision recorded in the header comment so
future readers don't second-guess it.

## 3 new tests

- `ApplyPoseMaskedTouchesOnlyListedBones` — 2-bone fixture, save
  with both at X=7, reset to origin, apply masked to bone[0]
  only. Assert bone[0]=7 AND bone[1]=0. Without the mask the
  pre-existing tests would have both at 7.
- `ApplyPoseMaskedRejectsUnknownPoseAndMissingEntity` — null
  entity / empty pose name / unknown pose name all return false.
- `ApplyPoseMaskedWithEmptyMaskAppliesNothing` — empty mask
  returns TRUE (pose was found) but doesn't touch any bone.
  Documents the "empty = nothing" contract.

What's deferred:
- MCP `apply_pose_masked` tool. Lifting QSet<QString> through
  the JSON-RPC layer is a bit clunky; defer until a real use
  case names what arg shape we want (probably a JSON array).
- CLI flag. Same shape question; defer to D-CLI follow-up.
- Inspector multi-bone-pick UI. D2 territory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

Warning

Rate limit exceeded

@fernandotonon has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 23 minutes and 56 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b7980c6-2e93-4595-a8a3-bb3ba35fa72e

📥 Commits

Reviewing files that changed from the base of the PR and between 47a973b and b16a772.

📒 Files selected for processing (3)
  • src/PoseLibrary.cpp
  • src/PoseLibrary.h
  • src/PoseLibrary_test.cpp
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/pose-lib-slice-d5-mask

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 and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

@fernandotonon fernandotonon merged commit 5202b14 into master May 18, 2026
20 checks passed
@fernandotonon fernandotonon deleted the feat/pose-lib-slice-d5-mask branch May 18, 2026 09:22
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