Implement multi-scheme animation name mapper for Owen Animation System
Some checks failed
CI/CD Pipeline / Test & Lint (16.x) (push) Has been cancelled
CI/CD Pipeline / Test & Lint (18.x) (push) Has been cancelled
CI/CD Pipeline / Test & Lint (20.x) (push) Has been cancelled
CI/CD Pipeline / Security Audit (push) Has been cancelled
CI/CD Pipeline / Release (push) Has been cancelled
Release / Validate Version (push) Has been cancelled
Release / Build and Test (push) Has been cancelled
Release / Create Release (push) Has been cancelled
Release / Publish to NPM (push) Has been cancelled
Release / Deploy Demo (push) Has been cancelled
Animation Processing Pipeline / Validate Animation Names (push) Has been cancelled
Animation Processing Pipeline / Process Blender Animation Assets (push) Has been cancelled
Animation Processing Pipeline / Update Animation Documentation (push) Has been cancelled
Animation Processing Pipeline / Deploy Animation Demo (push) Has been cancelled
Some checks failed
CI/CD Pipeline / Test & Lint (16.x) (push) Has been cancelled
CI/CD Pipeline / Test & Lint (18.x) (push) Has been cancelled
CI/CD Pipeline / Test & Lint (20.x) (push) Has been cancelled
CI/CD Pipeline / Security Audit (push) Has been cancelled
CI/CD Pipeline / Release (push) Has been cancelled
Release / Validate Version (push) Has been cancelled
Release / Build and Test (push) Has been cancelled
Release / Create Release (push) Has been cancelled
Release / Publish to NPM (push) Has been cancelled
Release / Deploy Demo (push) Has been cancelled
Animation Processing Pipeline / Validate Animation Names (push) Has been cancelled
Animation Processing Pipeline / Process Blender Animation Assets (push) Has been cancelled
Animation Processing Pipeline / Update Animation Documentation (push) Has been cancelled
Animation Processing Pipeline / Deploy Animation Demo (push) Has been cancelled
- Added AnimationNameMapper class to handle conversion between different animation naming schemes (legacy, artist, hierarchical, semantic). - Included methods for initialization, pattern matching, conversion, and validation of animation names. - Developed comprehensive unit tests for the animation name converter and demo pages using Playwright. - Created a Vite configuration for the demo application, including asset handling and optimization settings. - Enhanced the demo with features for batch conversion, performance metrics, and responsive design.
This commit is contained in:
252
scripts/generate-animation-constants.js
Normal file
252
scripts/generate-animation-constants.js
Normal file
@ -0,0 +1,252 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Generate Animation Constants Script
|
||||
* Automatically generates/updates AnimationConstants.js based on current AnimationNameMapper definitions
|
||||
*/
|
||||
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { fileURLToPath, pathToFileURL } from 'url'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
|
||||
const PROJECT_ROOT = path.resolve(__dirname, '..')
|
||||
const ANIMATION_CONSTANTS_PATH = path.join(PROJECT_ROOT, 'src', 'animation', 'AnimationConstants.js')
|
||||
const ANIMATION_MAPPER_PATH = path.join(PROJECT_ROOT, 'src', 'animation', 'AnimationNameMapper.js')
|
||||
|
||||
/**
|
||||
* Generate animation constants file content
|
||||
*/
|
||||
async function generateAnimationConstants () {
|
||||
try {
|
||||
console.log('🔧 Generating Animation Constants...')
|
||||
|
||||
// Import the AnimationNameMapper to get current definitions
|
||||
const animationMapperUrl = pathToFileURL(ANIMATION_MAPPER_PATH)
|
||||
const { AnimationNameMapper } = await import(animationMapperUrl)
|
||||
const mapper = new AnimationNameMapper()
|
||||
|
||||
// Get all animation names by scheme
|
||||
const legacyAnimations = mapper.getAllAnimationsByScheme('legacy')
|
||||
const artistAnimations = mapper.getAllAnimationsByScheme('artist')
|
||||
const hierarchicalAnimations = mapper.getAllAnimationsByScheme('hierarchical')
|
||||
const semanticAnimations = mapper.getAllAnimationsByScheme('semantic')
|
||||
|
||||
const timestamp = new Date().toISOString()
|
||||
|
||||
const constantsContent = `/**
|
||||
* Animation Constants - Auto-generated file
|
||||
*
|
||||
* This file contains type-safe constants for all animation naming schemes
|
||||
* supported by the Owen Animation System.
|
||||
*
|
||||
* Generated: ${timestamp}
|
||||
*
|
||||
* @fileoverview Auto-generated animation constants for all naming schemes
|
||||
* @module AnimationConstants
|
||||
*/
|
||||
|
||||
// Import the core mapper for utility functions
|
||||
import { AnimationNameMapper } from './AnimationNameMapper.js'
|
||||
|
||||
/**
|
||||
* Naming scheme enumeration
|
||||
* @readonly
|
||||
* @enum {string}
|
||||
*/
|
||||
export const NamingSchemes = Object.freeze({
|
||||
LEGACY: 'legacy',
|
||||
ARTIST: 'artist',
|
||||
HIERARCHICAL: 'hierarchical',
|
||||
SEMANTIC: 'semantic'
|
||||
})
|
||||
|
||||
/**
|
||||
* Legacy animation names (e.g., wait_idle_L)
|
||||
* @readonly
|
||||
*/
|
||||
export const LegacyAnimations = Object.freeze({
|
||||
${legacyAnimations.map(anim => {
|
||||
const constantName = anim.toUpperCase().replace(/[^A-Z0-9]/g, '_')
|
||||
return ` ${constantName}: '${anim}'`
|
||||
}).join(',\n')}
|
||||
})
|
||||
|
||||
/**
|
||||
* Artist-friendly animation names (e.g., Owen_WaitIdle)
|
||||
* @readonly
|
||||
*/
|
||||
export const ArtistAnimations = Object.freeze({
|
||||
${artistAnimations.map(anim => {
|
||||
const constantName = anim.replace(/^Owen_/, '').toUpperCase().replace(/[^A-Z0-9]/g, '_')
|
||||
return ` ${constantName}: '${anim}'`
|
||||
}).join(',\n')}
|
||||
})
|
||||
|
||||
/**
|
||||
* Hierarchical animation names (e.g., owen.state.wait.idle.loop)
|
||||
* @readonly
|
||||
*/
|
||||
export const HierarchicalAnimations = Object.freeze({
|
||||
${hierarchicalAnimations.map(anim => {
|
||||
const constantName = anim.replace(/owen\./, '').split('.').map(part =>
|
||||
part.charAt(0).toUpperCase() + part.slice(1)
|
||||
).join('_').toUpperCase()
|
||||
return ` ${constantName}: '${anim}'`
|
||||
}).join(',\n')}
|
||||
})
|
||||
|
||||
/**
|
||||
* Semantic animation names (e.g., OwenWaitIdleLoop)
|
||||
* @readonly
|
||||
*/
|
||||
export const SemanticAnimations = Object.freeze({
|
||||
${semanticAnimations.map(anim => {
|
||||
const constantName = anim.replace(/^Owen/, '').replace(/([A-Z])/g, '_$1').toUpperCase().substring(1)
|
||||
return ` ${constantName}: '${anim}'`
|
||||
}).join(',\n')}
|
||||
})
|
||||
|
||||
/**
|
||||
* All animation constants grouped by scheme
|
||||
* @readonly
|
||||
*/
|
||||
export const AnimationsByScheme = Object.freeze({
|
||||
[NamingSchemes.LEGACY]: LegacyAnimations,
|
||||
[NamingSchemes.ARTIST]: ArtistAnimations,
|
||||
[NamingSchemes.HIERARCHICAL]: HierarchicalAnimations,
|
||||
[NamingSchemes.SEMANTIC]: SemanticAnimations
|
||||
})
|
||||
|
||||
// Create global mapper instance for utility functions
|
||||
const mapper = new AnimationNameMapper()
|
||||
|
||||
/**
|
||||
* Convert an animation name between schemes
|
||||
* @param {string} animationName - The animation name to convert
|
||||
* @param {string} targetScheme - The target naming scheme
|
||||
* @returns {string} The converted animation name
|
||||
* @throws {Error} If conversion fails
|
||||
*/
|
||||
export function convertAnimationName(animationName, targetScheme) {
|
||||
return mapper.convert(animationName, targetScheme)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all animation names for a specific scheme
|
||||
* @param {string} scheme - The naming scheme
|
||||
* @returns {string[]} Array of animation names
|
||||
*/
|
||||
export function getAllAnimationNames(scheme) {
|
||||
return mapper.getAllAnimationsByScheme(scheme)
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an animation name and get suggestions
|
||||
* @param {string} animationName - The animation name to validate
|
||||
* @returns {Object} Validation result with isValid flag and suggestions
|
||||
*/
|
||||
export function validateAnimationName(animationName) {
|
||||
return mapper.validateAnimationName(animationName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get animations filtered by state and emotion
|
||||
* @param {string} state - The animation state (wait, react, sleep, etc.)
|
||||
* @param {string} [emotion] - Optional emotion filter (angry, happy, etc.)
|
||||
* @param {string} [scheme='semantic'] - The naming scheme to use
|
||||
* @returns {string[]} Array of matching animation names
|
||||
*/
|
||||
export function getAnimationsByStateAndEmotion(state, emotion = null, scheme = 'semantic') {
|
||||
const allAnimations = getAllAnimationNames(scheme)
|
||||
|
||||
return allAnimations.filter(anim => {
|
||||
const lowerAnim = anim.toLowerCase()
|
||||
const hasState = lowerAnim.includes(state.toLowerCase())
|
||||
const hasEmotion = !emotion || lowerAnim.includes(emotion.toLowerCase())
|
||||
|
||||
return hasState && hasEmotion
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Animation metadata for development tools
|
||||
* @readonly
|
||||
*/
|
||||
export const AnimationMetadata = Object.freeze({
|
||||
totalAnimations: ${legacyAnimations.length},
|
||||
schemes: Object.keys(NamingSchemes).length,
|
||||
generatedAt: '${timestamp}',
|
||||
version: '1.0.0'
|
||||
})
|
||||
|
||||
// Default export for convenience
|
||||
export default {
|
||||
NamingSchemes,
|
||||
LegacyAnimations,
|
||||
ArtistAnimations,
|
||||
HierarchicalAnimations,
|
||||
SemanticAnimations,
|
||||
AnimationsByScheme,
|
||||
convertAnimationName,
|
||||
getAllAnimationNames,
|
||||
validateAnimationName,
|
||||
getAnimationsByStateAndEmotion,
|
||||
AnimationMetadata
|
||||
}
|
||||
`
|
||||
|
||||
// Write the generated constants file
|
||||
fs.writeFileSync(ANIMATION_CONSTANTS_PATH, constantsContent, 'utf8')
|
||||
|
||||
console.log('✅ Animation Constants generated successfully!')
|
||||
console.log(`📝 Generated ${legacyAnimations.length} animation constants across 4 schemes`)
|
||||
console.log(`📍 File: ${ANIMATION_CONSTANTS_PATH}`)
|
||||
|
||||
// Generate summary report
|
||||
const report = {
|
||||
generated: timestamp,
|
||||
totalAnimations: legacyAnimations.length,
|
||||
schemes: {
|
||||
legacy: legacyAnimations.length,
|
||||
artist: artistAnimations.length,
|
||||
hierarchical: hierarchicalAnimations.length,
|
||||
semantic: semanticAnimations.length
|
||||
},
|
||||
outputFile: ANIMATION_CONSTANTS_PATH
|
||||
}
|
||||
|
||||
// Ensure reports directory exists
|
||||
const reportsDir = path.join(PROJECT_ROOT, 'reports')
|
||||
if (!fs.existsSync(reportsDir)) {
|
||||
fs.mkdirSync(reportsDir, { recursive: true })
|
||||
}
|
||||
|
||||
// Write report
|
||||
fs.writeFileSync(
|
||||
path.join(reportsDir, 'animation-constants-generation.json'),
|
||||
JSON.stringify(report, null, 2),
|
||||
'utf8'
|
||||
)
|
||||
|
||||
return report
|
||||
} catch (error) {
|
||||
console.error('❌ Error generating Animation Constants:', error.message)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the script if called directly
|
||||
if (process.argv[1] === __filename) {
|
||||
generateAnimationConstants()
|
||||
.then(report => {
|
||||
console.log('📊 Generation complete!')
|
||||
console.log(JSON.stringify(report, null, 2))
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('💥 Script failed:', error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user