macro-clips slice 4d: button canvas runtime + pointer handling
- ButtonInstance gains optional x/y; new instances default to stage center and setButtonInstancePosition updates them - useButtonRuntime composable holds per-instance state/disabled overrides (runtime-only, not persisted). getState layers the runtime disabled override on top of the persisted initial flag. - store.actionRuntime's setButtonState/setButtonDisabled now drive useButtonRuntime instead of mutating the scene, so script-triggered state changes stay ephemeral - CanvasStage renders each visible (playhead >= startTime) button instance inside a <v-group> at (bi.x, bi.y), drawing the current state's layer stack with draggable/listening disabled plus a transparent hit-rect sized to the clip's hitArea or the bbox of the first rect/circle layer. The group wires mouseenter/leave/ down/up into the state machine and fires onClick via evalAction. - exportPlayer runtime mirrors the same thing: getEffectiveButtonState, per-frame buttonHits array, canvas-level mousemove/down/up handlers do their own hit testing in scene space. RUNTIME_VERSION bumped to 5. - tests cover useButtonRuntime defaults/overrides and the store.actionRuntime → runtime-state roundtrip via label resolution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
024883943b
commit
f61f90d613
6 files changed
+412
-8
No files matched your search
@@ -0,0 +1,48 @@
|
||||
import { reactive } from 'vue'
|
||||
import type { ButtonState } from '@/types/scene'
|
||||
|
||||
// Runtime-only per-instance state. Not persisted; resets on page reload.
|
||||
interface RuntimeState {
|
||||
// Which state the button is currently showing. Undefined = 'normal'.
|
||||
state: Map<string, ButtonState>
|
||||
// Runtime disabled flag — overrides (and can be overridden by) the
|
||||
// instance's persisted `disabled` field. Undefined = use persisted.
|
||||
disabled: Map<string, boolean>
|
||||
}
|
||||
|
||||
const runtime: RuntimeState = reactive({
|
||||
state: new Map<string, ButtonState>(),
|
||||
disabled: new Map<string, boolean>(),
|
||||
})
|
||||
|
||||
export function useButtonRuntime() {
|
||||
return {
|
||||
state: runtime.state,
|
||||
disabled: runtime.disabled,
|
||||
getState(id: string, persistedDisabled?: boolean): ButtonState {
|
||||
const override = runtime.disabled.get(id)
|
||||
const effectiveDisabled =
|
||||
override !== undefined ? override : !!persistedDisabled
|
||||
if (effectiveDisabled) return 'disabled'
|
||||
return runtime.state.get(id) ?? 'normal'
|
||||
},
|
||||
isDisabled(id: string, persistedDisabled?: boolean): boolean {
|
||||
const override = runtime.disabled.get(id)
|
||||
return override !== undefined ? override : !!persistedDisabled
|
||||
},
|
||||
setState(id: string, next: ButtonState) {
|
||||
if (next === 'normal') runtime.state.delete(id)
|
||||
else runtime.state.set(id, next)
|
||||
},
|
||||
setDisabled(id: string, next: boolean) {
|
||||
runtime.disabled.set(id, next)
|
||||
},
|
||||
clearDisabled(id: string) {
|
||||
runtime.disabled.delete(id)
|
||||
},
|
||||
reset() {
|
||||
runtime.state.clear()
|
||||
runtime.disabled.clear()
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user