Browse Source
idlePassiveTimeoutMs moves out of a one-off deriveAvatarState options type into $lib/humanoid/config.ts's AnimationConfig, with DEFAULT_ANIMATION_CONFIG and resolveAnimationConfig(overrides) merging partial overrides onto it. Documents the convention in HUMANOID.md so future knobs ported from the Unreal Engine avatar app's animation systems land in this same interface instead of scattered options. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>main
4 changed files with 78 additions and 21 deletions
@ -0,0 +1,20 @@ |
|||||
|
import { describe, expect, it } from 'vitest'; |
||||
|
import { DEFAULT_ANIMATION_CONFIG, resolveAnimationConfig } from './config.js'; |
||||
|
|
||||
|
describe('resolveAnimationConfig', () => { |
||||
|
it('returns the defaults when called with no overrides', () => { |
||||
|
expect(resolveAnimationConfig()).toEqual(DEFAULT_ANIMATION_CONFIG); |
||||
|
}); |
||||
|
|
||||
|
it('merges a partial override onto the defaults', () => { |
||||
|
expect(resolveAnimationConfig({ idlePassiveTimeoutMs: 5_000 })).toEqual({ |
||||
|
...DEFAULT_ANIMATION_CONFIG, |
||||
|
idlePassiveTimeoutMs: 5_000 |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('does not mutate DEFAULT_ANIMATION_CONFIG', () => { |
||||
|
resolveAnimationConfig({ idlePassiveTimeoutMs: 5_000 }); |
||||
|
expect(DEFAULT_ANIMATION_CONFIG.idlePassiveTimeoutMs).toBe(30_000); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,34 @@ |
|||||
|
/** |
||||
|
* Single home for every tunable value the `humanoid` package's own state |
||||
|
* derivation exposes — currently just the idleActive->idlePassive timeout, |
||||
|
* but the intent is that any future knob this package's own reducers/ |
||||
|
* derivation logic need (further idle-escalation thresholds, turn-taking |
||||
|
* heuristics, etc. — the kind of thing an Unreal Engine avatar app's |
||||
|
* animation systems tend to expose as constants) lands here too, instead of |
||||
|
* as a one-off option on whichever function first needed it. See |
||||
|
* docs/HUMANOID.md's "Configuration" section. |
||||
|
* |
||||
|
* A future animation library built as a *consumer* of this package (eye |
||||
|
* look-at, blink, lip-sync, body/gesture — see HUMANOID.md's "What's not |
||||
|
* built here") is a separate package with its own config surface, not an |
||||
|
* extension of this interface — follow the same three-piece shape |
||||
|
* (`XConfig` interface, `DEFAULT_X_CONFIG`, `resolveXConfig`) there rather |
||||
|
* than growing this one across package boundaries. |
||||
|
*/ |
||||
|
export interface AnimationConfig { |
||||
|
/** |
||||
|
* How long the avatar sits in `idleActive` with no other signal before |
||||
|
* `deriveAvatarState` (`$lib/client/humanoid/avatar-state.ts`) fires the |
||||
|
* `idle_timeout` signal that settles it into `idlePassive`. |
||||
|
*/ |
||||
|
idlePassiveTimeoutMs: number; |
||||
|
} |
||||
|
|
||||
|
export const DEFAULT_ANIMATION_CONFIG: AnimationConfig = { |
||||
|
idlePassiveTimeoutMs: 30_000 |
||||
|
}; |
||||
|
|
||||
|
/** Merges a project's partial overrides onto `DEFAULT_ANIMATION_CONFIG`. */ |
||||
|
export function resolveAnimationConfig(overrides: Partial<AnimationConfig> = {}): AnimationConfig { |
||||
|
return { ...DEFAULT_ANIMATION_CONFIG, ...overrides }; |
||||
|
} |
||||
Loading…
Reference in new issue