revert macro-clips button feature (keep markers + scripts)

The button authoring ended up too far from the intended model after
three correction passes. Pulling it out entirely so we can rebuild
from a clean spec. Markers, script tracks, script frames, the Action
editor, the Script DSL and the runtime for all of the above stay —
they work.

Removed:
- types: ButtonState, StateTransition, ButtonHitArea, ButtonClip,
  ButtonInstance, setButtonState/setButtonDisabled Action variants,
  Scene.buttonClips/buttonInstances
- store: activeButtonClip* getters, all add/remove/setButton* actions,
  seedDefaultButtonClip, enterButtonEdit/setActiveButtonState/
  exitButtonEdit, button-label resolution in actionRuntime
- useButtonRuntime composable, buttonBlend helper,
  ButtonInstanceDialog, sidebar Buttons section, Timeline button
  rendering + pointer handlers, CanvasStage button rendering +
  pointer state machine, exportPlayer button runtime + hit-testing
- DSL commands state/enable/disable and their parse errors
- 35 button-related tests + helpers; stale testing doc; stale design
  doc

Re-applied three uncommitted fixes that were unrelated to the button
work:
- clicking a marker no longer jumps the playhead (only drag / dblclick
  act on it)
- script tracks get a right-click context menu (rename + delete,
  color in the existing palette)
- onTracksPointerDown excludes .script-lane / .script-frame so
  clicks on empty lanes or on frame dots reach the frame-open path
  instead of being swallowed by box-select pointer capture

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
thandClaude Opus 4.7 committed 2026-04-20 23:37:49 +02:00
1 parent 616973b0fa
commit 31604052ca
16 files changed
+84 -2809

No files matched your search

+1 -50
View File
@@ -1,4 +1,4 @@
import type { Action, ButtonState } from '@/types/scene'
import type { Action } from '@/types/scene'
export interface ParseError {
line: number
@@ -10,13 +10,6 @@ export interface ParseResult {
errors: ParseError[]
}
const BUTTON_STATES = new Set<ButtonState>([
'normal',
'hover',
'pressed',
'disabled',
])
/**
* Parse a small line-based DSL into Action[]. Comments start with `//`
* and each non-empty line is one command. Known commands:
@@ -25,12 +18,6 @@ const BUTTON_STATES = new Set<ButtonState>([
* jump <seconds> (e.g. `jump 2.5`)
* jump #<frame> (e.g. `jump #135`)
* jump @<marker> (e.g. `jump @intro`)
* state btn:<label> <state> (state ∈ normal|hover|pressed|disabled)
* enable btn:<label>
* disable btn:<label>
*
* Button labels are left as-is in `instanceId`. The runtime resolves
* labels to real instance IDs at eval time.
*/
export function parseScript(source: string): ParseResult {
const actions: Action[] = []
@@ -64,12 +51,6 @@ function parseLine(line: string): { action?: Action; error?: string } {
return ok({ type: 'rewindToLoop' })
case 'jump':
return parseJump(tokens)
case 'state':
return parseState(tokens)
case 'enable':
return parseEnable(tokens, false)
case 'disable':
return parseEnable(tokens, true)
default:
return { error: `unknown command "${cmd}"` }
}
@@ -96,33 +77,3 @@ function parseJump(tokens: string[]): { action?: Action; error?: string } {
if (!Number.isFinite(time)) return { error: `jump: invalid time "${arg}"` }
return ok({ type: 'jumpTo', time })
}
function parseButtonRef(token: string): string | null {
if (!token.startsWith('btn:')) return null
const label = token.slice(4)
return label || null
}
function parseState(tokens: string[]): { action?: Action; error?: string } {
if (tokens.length < 3) return { error: 'state: expected `btn:<label> <state>`' }
const label = parseButtonRef(tokens[1])
if (!label) return { error: `state: expected button ref like btn:<label>, got "${tokens[1]}"` }
const state = tokens[2] as ButtonState
if (!BUTTON_STATES.has(state)) {
return { error: `state: unknown state "${state}"` }
}
return ok({ type: 'setButtonState', instanceId: label, state })
}
function parseEnable(
tokens: string[],
disabled: boolean,
): { action?: Action; error?: string } {
const verb = disabled ? 'disable' : 'enable'
if (tokens.length < 2) return { error: `${verb}: missing button ref` }
const label = parseButtonRef(tokens[1])
if (!label) {
return { error: `${verb}: expected button ref like btn:<label>` }
}
return ok({ type: 'setButtonDisabled', instanceId: label, disabled })
}