Skip to content

Phase 5 slice D2 — Dope sheet per-channel rows #376

Description

@fernandotonon

Overview

Second chunk of slice D from #260. Builds on D1 (#375) by adding per-channel expansion to each bone row in the dope sheet — TX / TY / TZ / RW / RX / RY / RZ / SX / SY / SZ shown as sub-rows under the bone.

D3 (the curve editor + Bezier handles) is the remaining chunk.

Scope (this slice)

Controller

  • Q_INVOKABLE QVariantList allBoneRows() already returns { bone, keyTimes }. Extend each row with a channels map: for each animated bone, indicate which TRS channels actually deviate from the bind pose at any keyframe. Avoids painting empty sub-rows for channels the clip never touches.
    • Specifically: a channel tx is "active" if any keyframe on the track has translate.x non-zero (within epsilon). Same for the rest.
  • New optional sub-row keyframe API for D3 — not implemented in this slice; sub-row diamonds reuse the existing per-track keyframes.

QML

  • Bone row gains a chevron (▶/▼) on the left of the bone name that toggles per-channel expansion. Persists per-bone in QML state.
  • When expanded, render up to 9 sub-rows (one per active channel, in TRS order). Each sub-row has a single horizontal track with diamonds at the same key times as the parent bone, colored per channel:
    • T.X = red, T.Y = green, T.Z = blue
    • R.W = magenta, R.X = red, R.Y = green, R.Z = blue
    • S.X = orange-red, S.Y = orange-green, S.Z = orange-blue
  • Sub-row diamonds participate in selection / drag / copy-paste as the parent keyframe in this slice — moving a sub-row diamond moves the entire keyframe time. Per-channel-only edits + Bezier handles arrive in slice D3.
  • Sub-row Y-coordinates inherit the same row-height (22 px) as the parent. The dope sheet expands vertically when a bone is expanded.

Marquee + bulk move

  • Marquee continues to operate on the parent bone keyframes; sub-rows are visual decoration in this slice.
  • Bulk move on a parent diamond moves all channels (no change from D1).

Out of scope

  • Per-channel keyframe values (slice D3 introduces a side-table or extended TransformKeyFrame).
  • Bezier handles (slice D3).
  • Per-channel marquee selection (would only matter once D3 lands).

Tests

Pure-data:

  • allBoneRows() shape: each row now has a channels field, populated only with channels whose values actually differ from bind pose somewhere on the track.

Ogre fixture:

  • TestAnim's Child track has only translate motion (0.5 → 0.5 on x at t=0.5). Verify tx is active, ty/tz/r*/s* are not.

Acceptance criteria

  • Each bone row shows a ▶/▼ chevron; clicking expands per-channel sub-rows
  • Only channels that actually animate appear (no all-zero rows)
  • Sub-row diamonds are color-coded per channel
  • Clicking a sub-row diamond selects the parent keyframe + sets the playhead
  • Multi-select (D1) still works on parent bone diamonds
  • Linux CI: at least 2 new tests pass

Plan (#260)

Follows: #373 (D / dope sheet view), #375 (D1 / multi-select + copy/paste).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions