Refactor code for consistency and readability
- Updated import statements to use consistent formatting across files. - Adjusted method definitions and class constructors for uniform spacing and style. - Simplified promise handling and error messages in state handlers. - Enhanced state transition logic in various state handlers. - Improved quirk animation handling in WaitStateHandler. - Streamlined animation loading and caching mechanisms in AnimationLoader. - Updated Vite configuration for aliasing.
This commit is contained in:
@ -3,7 +3,7 @@
|
||||
* @module core
|
||||
*/
|
||||
|
||||
import { States, Emotions, Config } from '../constants.js';
|
||||
import { States, Emotions, Config } from '../constants.js'
|
||||
|
||||
/**
|
||||
* Main controller for the Owen animation system
|
||||
@ -18,97 +18,97 @@ export class OwenAnimationContext {
|
||||
* @param {AnimationClipFactory} animationClipFactory - Factory for creating clips
|
||||
* @param {StateFactory} stateFactory - Factory for creating state handlers
|
||||
*/
|
||||
constructor(model, mixer, animationClipFactory, stateFactory) {
|
||||
constructor (model, mixer, animationClipFactory, stateFactory) {
|
||||
/**
|
||||
* The 3D character model
|
||||
* @type {THREE.Object3D}
|
||||
*/
|
||||
this.model = model;
|
||||
this.model = model
|
||||
|
||||
/**
|
||||
* The Three.js animation mixer
|
||||
* @type {THREE.AnimationMixer}
|
||||
*/
|
||||
this.mixer = mixer;
|
||||
this.mixer = mixer
|
||||
|
||||
/**
|
||||
* Factory for creating animation clips
|
||||
* @type {AnimationClipFactory}
|
||||
*/
|
||||
this.animationClipFactory = animationClipFactory;
|
||||
this.animationClipFactory = animationClipFactory
|
||||
|
||||
/**
|
||||
* Factory for creating state handlers
|
||||
* @type {StateFactory}
|
||||
*/
|
||||
this.stateFactory = stateFactory;
|
||||
this.stateFactory = stateFactory
|
||||
|
||||
/**
|
||||
* Map of animation clips by name
|
||||
* @type {Map<string, AnimationClip>}
|
||||
*/
|
||||
this.clips = new Map();
|
||||
this.clips = new Map()
|
||||
|
||||
/**
|
||||
* Map of state handlers by name
|
||||
* @type {Map<string, StateHandler>}
|
||||
*/
|
||||
this.states = new Map();
|
||||
this.states = new Map()
|
||||
|
||||
/**
|
||||
* Current active state
|
||||
* @type {string}
|
||||
*/
|
||||
this.currentState = States.WAIT;
|
||||
this.currentState = States.WAIT
|
||||
|
||||
/**
|
||||
* Current active state handler
|
||||
* @type {StateHandler|null}
|
||||
*/
|
||||
this.currentStateHandler = null;
|
||||
this.currentStateHandler = null
|
||||
|
||||
/**
|
||||
* Timer for inactivity detection
|
||||
* @type {number}
|
||||
*/
|
||||
this.inactivityTimer = 0;
|
||||
this.inactivityTimer = 0
|
||||
|
||||
/**
|
||||
* Inactivity timeout in milliseconds
|
||||
* @type {number}
|
||||
*/
|
||||
this.inactivityTimeout = Config.INACTIVITY_TIMEOUT;
|
||||
this.inactivityTimeout = Config.INACTIVITY_TIMEOUT
|
||||
|
||||
/**
|
||||
* Whether the system is initialized
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.initialized = false;
|
||||
this.initialized = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the animation system
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async initialize() {
|
||||
if (this.initialized) return;
|
||||
async initialize () {
|
||||
if (this.initialized) return
|
||||
|
||||
// Create animation clips from model
|
||||
this.clips = await this.animationClipFactory.createClipsFromModel(this.model);
|
||||
this.clips = await this.animationClipFactory.createClipsFromModel(this.model)
|
||||
|
||||
// Create actions for all clips
|
||||
for (const [ , clip ] of this.clips) {
|
||||
clip.createAction(this.mixer);
|
||||
for (const [, clip] of this.clips) {
|
||||
clip.createAction(this.mixer)
|
||||
}
|
||||
|
||||
// Initialize state handlers
|
||||
this.initializeStates();
|
||||
this.initializeStates()
|
||||
|
||||
// Start in wait state
|
||||
await this.transitionTo(States.WAIT);
|
||||
await this.transitionTo(States.WAIT)
|
||||
|
||||
this.initialized = true;
|
||||
console.log('Owen Animation System initialized');
|
||||
this.initialized = true
|
||||
console.log('Owen Animation System initialized')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,12 +116,12 @@ export class OwenAnimationContext {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
initializeStates() {
|
||||
const stateNames = this.stateFactory.getAvailableStates();
|
||||
initializeStates () {
|
||||
const stateNames = this.stateFactory.getAvailableStates()
|
||||
|
||||
for (const stateName of stateNames) {
|
||||
const handler = this.stateFactory.createStateHandler(stateName, this);
|
||||
this.states.set(stateName, handler);
|
||||
const handler = this.stateFactory.createStateHandler(stateName, this)
|
||||
this.states.set(stateName, handler)
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,28 +132,28 @@ export class OwenAnimationContext {
|
||||
* @returns {Promise<void>}
|
||||
* @throws {Error} If state is not found or transition is invalid
|
||||
*/
|
||||
async transitionTo(newStateName, emotion = Emotions.NEUTRAL) {
|
||||
async transitionTo (newStateName, emotion = Emotions.NEUTRAL) {
|
||||
if (!this.states.has(newStateName)) {
|
||||
throw new Error(`State '${newStateName}' not found`);
|
||||
throw new Error(`State '${newStateName}' not found`)
|
||||
}
|
||||
|
||||
const oldState = this.currentState;
|
||||
const newStateHandler = this.states.get(newStateName);
|
||||
const oldState = this.currentState
|
||||
const newStateHandler = this.states.get(newStateName)
|
||||
|
||||
console.log(`Transitioning from ${oldState} to ${newStateName}`);
|
||||
console.log(`Transitioning from ${oldState} to ${newStateName}`)
|
||||
|
||||
// Exit current state
|
||||
if (this.currentStateHandler) {
|
||||
await this.currentStateHandler.exit(newStateName, emotion);
|
||||
await this.currentStateHandler.exit(newStateName, emotion)
|
||||
}
|
||||
|
||||
// Enter new state
|
||||
this.currentState = newStateName;
|
||||
this.currentStateHandler = newStateHandler;
|
||||
await this.currentStateHandler.enter(oldState, emotion);
|
||||
this.currentState = newStateName
|
||||
this.currentStateHandler = newStateHandler
|
||||
await this.currentStateHandler.enter(oldState, emotion)
|
||||
|
||||
// Reset inactivity timer
|
||||
this.resetActivityTimer();
|
||||
this.resetActivityTimer()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,26 +161,26 @@ export class OwenAnimationContext {
|
||||
* @param {string} message - The user message
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async handleUserMessage(message) {
|
||||
console.log(`Handling user message: "${message}"`);
|
||||
async handleUserMessage (message) {
|
||||
console.log(`Handling user message: "${message}"`)
|
||||
|
||||
this.onUserActivity();
|
||||
this.onUserActivity()
|
||||
|
||||
// If sleeping, wake up first
|
||||
if (this.currentState === States.SLEEP) {
|
||||
await this.transitionTo(States.REACT);
|
||||
await this.transitionTo(States.REACT)
|
||||
}
|
||||
|
||||
// Let current state handle the message
|
||||
if (this.currentStateHandler) {
|
||||
await this.currentStateHandler.handleMessage(message);
|
||||
await this.currentStateHandler.handleMessage(message)
|
||||
}
|
||||
|
||||
// Transition to appropriate next state based on current state
|
||||
if (this.currentState === States.WAIT) {
|
||||
await this.transitionTo(States.REACT);
|
||||
await this.transitionTo(States.REACT)
|
||||
} else if (this.currentState === States.REACT) {
|
||||
await this.transitionTo(States.TYPE);
|
||||
await this.transitionTo(States.TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,12 +188,12 @@ export class OwenAnimationContext {
|
||||
* Called when user activity is detected
|
||||
* @returns {void}
|
||||
*/
|
||||
onUserActivity() {
|
||||
this.resetActivityTimer();
|
||||
onUserActivity () {
|
||||
this.resetActivityTimer()
|
||||
|
||||
// Wake up if sleeping
|
||||
if (this.currentState === States.SLEEP) {
|
||||
this.transitionTo(States.WAIT);
|
||||
this.transitionTo(States.WAIT)
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,8 +202,8 @@ export class OwenAnimationContext {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
resetActivityTimer() {
|
||||
this.inactivityTimer = 0;
|
||||
resetActivityTimer () {
|
||||
this.inactivityTimer = 0
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,9 +211,9 @@ export class OwenAnimationContext {
|
||||
* @private
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async handleInactivity() {
|
||||
console.log('Inactivity detected, transitioning to sleep');
|
||||
await this.transitionTo(States.SLEEP);
|
||||
async handleInactivity () {
|
||||
console.log('Inactivity detected, transitioning to sleep')
|
||||
await this.transitionTo(States.SLEEP)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,21 +221,21 @@ export class OwenAnimationContext {
|
||||
* @param {number} deltaTime - Time elapsed since last update (ms)
|
||||
* @returns {void}
|
||||
*/
|
||||
update(deltaTime) {
|
||||
if (!this.initialized) return;
|
||||
update (deltaTime) {
|
||||
if (!this.initialized) return
|
||||
|
||||
// Update Three.js mixer
|
||||
this.mixer.update(deltaTime / 1000); // Convert to seconds
|
||||
this.mixer.update(deltaTime / 1000) // Convert to seconds
|
||||
|
||||
// Update current state
|
||||
if (this.currentStateHandler) {
|
||||
this.currentStateHandler.update(deltaTime);
|
||||
this.currentStateHandler.update(deltaTime)
|
||||
}
|
||||
|
||||
// Update inactivity timer
|
||||
this.inactivityTimer += deltaTime;
|
||||
this.inactivityTimer += deltaTime
|
||||
if (this.inactivityTimer > this.inactivityTimeout && this.currentState !== States.SLEEP) {
|
||||
this.handleInactivity();
|
||||
this.handleInactivity()
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,8 +244,8 @@ export class OwenAnimationContext {
|
||||
* @param {string} name - The animation clip name
|
||||
* @returns {AnimationClip|undefined} The animation clip or undefined if not found
|
||||
*/
|
||||
getClip(name) {
|
||||
return this.clips.get(name);
|
||||
getClip (name) {
|
||||
return this.clips.get(name)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -253,80 +253,80 @@ export class OwenAnimationContext {
|
||||
* @param {string} pattern - Pattern to match (supports * wildcards)
|
||||
* @returns {AnimationClip[]} Array of matching clips
|
||||
*/
|
||||
getClipsByPattern(pattern) {
|
||||
const regex = new RegExp(pattern.replace(/\*/g, '.*'));
|
||||
const matches = [];
|
||||
getClipsByPattern (pattern) {
|
||||
const regex = new RegExp(pattern.replace(/\*/g, '.*'))
|
||||
const matches = []
|
||||
|
||||
for (const [ name, clip ] of this.clips) {
|
||||
for (const [name, clip] of this.clips) {
|
||||
if (regex.test(name)) {
|
||||
matches.push(clip);
|
||||
matches.push(clip)
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
return matches
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state name
|
||||
* @returns {string} The current state name
|
||||
*/
|
||||
getCurrentState() {
|
||||
return this.currentState;
|
||||
getCurrentState () {
|
||||
return this.currentState
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state handler
|
||||
* @returns {StateHandler|null} The current state handler
|
||||
*/
|
||||
getCurrentStateHandler() {
|
||||
return this.currentStateHandler;
|
||||
getCurrentStateHandler () {
|
||||
return this.currentStateHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available transitions from current state
|
||||
* @returns {string[]} Array of available state transitions
|
||||
*/
|
||||
getAvailableTransitions() {
|
||||
getAvailableTransitions () {
|
||||
if (this.currentStateHandler) {
|
||||
return this.currentStateHandler.getAvailableTransitions();
|
||||
return this.currentStateHandler.getAvailableTransitions()
|
||||
}
|
||||
return [];
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available animation clip names
|
||||
* @returns {string[]} Array of clip names
|
||||
*/
|
||||
getAvailableClips() {
|
||||
return Array.from(this.clips.keys());
|
||||
getAvailableClips () {
|
||||
return Array.from(this.clips.keys())
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available state names
|
||||
* @returns {string[]} Array of state names
|
||||
*/
|
||||
getAvailableStates() {
|
||||
return Array.from(this.states.keys());
|
||||
getAvailableStates () {
|
||||
return Array.from(this.states.keys())
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose of the animation system and clean up resources
|
||||
* @returns {void}
|
||||
*/
|
||||
dispose() {
|
||||
dispose () {
|
||||
// Stop all animations
|
||||
for (const [ , clip ] of this.clips) {
|
||||
for (const [, clip] of this.clips) {
|
||||
if (clip.action) {
|
||||
clip.action.stop();
|
||||
clip.action.stop()
|
||||
}
|
||||
}
|
||||
|
||||
// Clear caches
|
||||
this.clips.clear();
|
||||
this.states.clear();
|
||||
this.animationClipFactory.clearCache();
|
||||
this.clips.clear()
|
||||
this.states.clear()
|
||||
this.animationClipFactory.clearCache()
|
||||
|
||||
this.initialized = false;
|
||||
console.log('Owen Animation System disposed');
|
||||
this.initialized = false
|
||||
console.log('Owen Animation System disposed')
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user