Animation rows can target behavior variables and shader parameters (#104)
game-maker / gate (push) Successful in 1m33s
game-maker / suite (push) Successful in 5m38s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5 committed 2026-09-17 09:04:29 +02:00
1 parent b278605c53
commit beeea355d9
9 files changed
+273 -77

No files matched your search

+12 -12
View File
@@ -1,12 +1,12 @@
import { newId } from '../ids';
import {
ANIMATION_ROOT_TYPES,
animatableDefs,
animatedKind,
blends,
isKeyInterpolation,
normalizeKeys,
targetAssetOf,
targetDefs,
trackDef,
trackValueAt,
} from '../model/animation';
import type { AnimationAsset, AnimationKey, AnimationTrack, KeyInterpolation } from '../model/Asset';
@@ -42,10 +42,13 @@ function requireAnimatable(
property: string,
): string {
if (!findAsset(project, asset.root)) throw new CommandError(`${asset.name} has nothing to animate yet`);
const aimed = targetAssetOf(project, asset, target);
if (!aimed) throw new CommandError('That object is not part of the animated asset');
const kind = animatedKind(aimed.type, property);
if (!kind) throw new CommandError(`${aimed.name} has no property ${property} to animate`);
const defs = targetDefs(project, asset, target);
if (!defs) throw new CommandError('That object is not part of the animated asset');
const kind = defs.find((d) => d.key === property)?.kind;
if (!kind)
throw new CommandError(
`${targetAssetOf(project, asset, target)?.name} has no property ${property} to animate`,
);
return kind;
}
@@ -163,8 +166,7 @@ export class RetargetAnimationTrackCommand extends TimelineCommand {
protected apply(project: Project, asset: AnimationAsset): void {
const track = requireTrack(asset, this.trackId);
const kind = requireAnimatable(project, asset, this.target, this.property);
const aimed = targetAssetOf(project, asset, track.target);
const was = aimed ? animatedKind(aimed.type, track.property) : undefined;
const was = trackDef(project, asset, track)?.kind;
if (was !== undefined && was !== kind) throw new CommandError(`A ${was} row cannot become a ${kind} row`);
requireUnique(asset, this.target, this.property, track.id);
track.target = this.target;
@@ -217,8 +219,7 @@ export class SetAnimationKeyCommand extends TimelineCommand {
const track = requireTrack(asset, this.trackId);
if (!Number.isInteger(this.frame) || this.frame < 0)
throw new CommandError('A key sits on a whole frame from 0');
const aimed = targetAssetOf(project, asset, track.target);
const def = aimed && animatableDefs(aimed.type).find((d) => d.key === track.property);
const def = trackDef(project, asset, track);
if (!def) throw new CommandError('The row aims at something that is gone');
const current = trackValueAt(track.keys, def.kind, this.frame);
const raw = this.value ?? current ?? (track.relative ? 0 : def.default);
@@ -252,8 +253,7 @@ export class SetKeyInterpolationCommand extends TimelineCommand {
const track = requireTrack(asset, ref.trackId);
const key = track.keys.find((k) => k.frame === ref.frame);
if (!key) throw new CommandError(`No key on frame ${ref.frame}`);
const aimed = targetAssetOf(project, asset, track.target);
const kind = aimed ? animatedKind(aimed.type, track.property) : undefined;
const kind = trackDef(project, asset, track)?.kind;
if (kind !== undefined && !blends(kind)) continue;
if (this.interpolation === 'linear') delete key.interpolation;
else key.interpolation = this.interpolation;