0.10.4: button still-frames render only on their own state
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fcb8edbb88
commit
8895fc76ef
8 files changed
+311
-23
No files matched your search
@@ -13,7 +13,7 @@ import {
|
||||
PhTrash,
|
||||
} from '@phosphor-icons/vue'
|
||||
import { useSceneStore } from '@/stores/scene'
|
||||
import { isLayerActiveAt, sampleLayer } from '@/lib/interpolate'
|
||||
import { isButtonLayerActiveAt, isLayerActiveAt, sampleLayer } from '@/lib/interpolate'
|
||||
import { importImageFile, loadImage } from '@/lib/fileLoader'
|
||||
import { useClipartStore } from '@/stores/clipart'
|
||||
import { drawButtonFrame, drawSceneFrame, loadSceneImages } from '@/lib/render'
|
||||
@@ -501,6 +501,9 @@ function buttonStackForTime(
|
||||
const layers = asset.layers.slice().reverse()
|
||||
for (const l of layers) {
|
||||
if (!l.visible) continue
|
||||
// Button-state visibility: still-frame kfs render only on their
|
||||
// own state, not held into neighbouring states.
|
||||
if (!isButtonLayerActiveAt(l, stateTime)) continue
|
||||
const a = assetMap.value.get(l.assetId)
|
||||
if (!a) continue
|
||||
out.push({ layer: l, asset: a, props: sampleLayer(l, stateTime) })
|
||||
@@ -754,7 +757,9 @@ function applyLivePose(props: AnimatableProps, layerId: string): AnimatableProps
|
||||
const stackItems = computed<StackItem[]>(() => {
|
||||
// Button-asset edit: show only the active state's layer stack. In the
|
||||
// 'hit' cell show the normal state's layers as an onion-skin
|
||||
// underneath the hit-area gizmos.
|
||||
// underneath the hit-area gizmos. Visibility follows the
|
||||
// button-specific rule: a still-frame kf renders only on its own
|
||||
// state, not held into subsequent states.
|
||||
if (store.activeButtonAssetId) {
|
||||
const out: StackItem[] = []
|
||||
const ba = store.activeButtonAsset
|
||||
@@ -764,6 +769,7 @@ const stackItems = computed<StackItem[]>(() => {
|
||||
for (const layer of layers) {
|
||||
if (!layer.visible) continue
|
||||
if (layer.editorHidden) continue
|
||||
if (!isButtonLayerActiveAt(layer, store.playhead)) continue
|
||||
const asset = assetMap.value.get(layer.assetId)
|
||||
if (!asset) continue
|
||||
const props = applyLivePose(sampleLayer(layer, store.playhead), layer.id)
|
||||
|
||||
@@ -1138,11 +1138,33 @@ interface KfSegment {
|
||||
tail?: boolean
|
||||
}
|
||||
|
||||
function segmentsOf(kfs: Keyframe[], duration: number): KfSegment[] {
|
||||
function segmentsOf(kfs: Keyframe[], duration: number, buttonMode = false): KfSegment[] {
|
||||
if (kfs.length === 0) return []
|
||||
const sorted = [...kfs].sort((a, b) => a.time - b.time)
|
||||
const out: KfSegment[] = []
|
||||
|
||||
// Button-state timelines have discrete state frames rather than a
|
||||
// continuous timeline. A still-frame kf only renders on its own
|
||||
// state; the layer is NOT held into the following states. The
|
||||
// connector line must stop at the still, not span past it.
|
||||
if (buttonMode) {
|
||||
for (let i = 0; i < sorted.length - 1; i++) {
|
||||
const a = sorted[i]
|
||||
const b = sorted[i + 1]
|
||||
// Stills terminate any interpolation — no connector emerges from
|
||||
// a hold kf toward the next state.
|
||||
if (a.hold) continue
|
||||
out.push({
|
||||
id: `${a.id}>${b.id}`,
|
||||
fromTime: a.time,
|
||||
toTime: b.time,
|
||||
easing: b.easing,
|
||||
held: false,
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Single keyframe means the layer is always visible (no animation
|
||||
// range), so the line should span the entire timeline as a solid
|
||||
// dim "on-stage" indicator — same treatment as a still-frame tail.
|
||||
@@ -2953,7 +2975,7 @@ onBeforeUnmount(() => {
|
||||
>
|
||||
<span class="playhead" :style="{ left: pxFromTime(store.playhead) + 'px' }" />
|
||||
<span
|
||||
v-for="seg in segmentsOf(track.kfs, duration)"
|
||||
v-for="seg in segmentsOf(track.kfs, duration, !!store.activeButtonAssetId)"
|
||||
:key="seg.id"
|
||||
class="kf-seg"
|
||||
:class="[seg.held ? 'held' : `easing-${seg.easing}`, { tail: seg.tail }]"
|
||||
|
||||
Reference in new issue
Block a user