diff --git a/M2Loader.js b/M2Loader.js index 4ea1b57..d7dd1a6 100644 --- a/M2Loader.js +++ b/M2Loader.js @@ -2853,13 +2853,13 @@ class SequenceManager { this.sequences = sequences; this.globalSequences = globalSequences; + this.currentSequenceId = - 1; + this._sequenceMap = new Map(); this._globalSequenceMap = new Map(); this._mixers = new Map(); this._globalMixers = new Map(); - this._currentSequence = - 1; - for ( let i = 0; i < sequences.length; i ++ ) { const sequence = sequences[ i ]; @@ -2880,7 +2880,7 @@ class SequenceManager { const sequence = this.sequences[ i ]; const animations = this._sequenceMap.get( sequence.id ); - animations.push( { clip, root, variationIndex: sequence.variationIndex } ); + animations.push( { clip, root, flags: sequence.flags, variationIndex: sequence.variationIndex } ); if ( this._mixers.has( root ) === false ) { @@ -2911,23 +2911,33 @@ class SequenceManager { if ( animation.variationIndex === variationIndex ) { - const mixer = this._mixers.get( animation.root ); - const action = mixer.clipAction( animation.clip ); - action.play(); + if ( animation.flags & M2_SEQUENCE_EMBEDDED_DATA ) { + + const mixer = this._mixers.get( animation.root ); + const action = mixer.clipAction( animation.clip ); + action.play(); + + } else { + + // TODO: Add support for sequences with external animation data (.anim files) + + console.warn( 'THREE.M2Loader: Sequences with external animation data not yet supported.' ); + + } } } - this._currentSequence = id; + this.currentSequenceId = id; } stopSequence() { - if ( this._currentSequence === - 1 ) return; + if ( this.currentSequenceId === - 1 ) return; - const sequence = this._sequenceMap.get( this._currentSequence ); + const sequence = this._sequenceMap.get( this.currentSequenceId ); for ( const animation of sequence ) { @@ -2973,38 +2983,46 @@ class SequenceManager { const list = []; - for ( let i = 0; i < this.sequences.length; i ++ ) { + for ( const id of this._sequenceMap.keys() ) { + + const name = M2_ANIMATION_LIST[ id ]; - const sequence = this.sequences[ i ]; + if ( name === undefined ) { - // TODO: Add support for sequences with external animation data (.anim files) + console.warn( 'THREE.M2Loader: Unknown animation ID:', id ); + name = ''; - if ( sequence.flags & M2_SEQUENCE_EMBEDDED_DATA ) { + } + + list.push( { + id: id, + name: name - const id = sequence.id; + } ); - const name = M2_ANIMATION_LIST[ id ]; + } - if ( name === undefined ) { + list.sort( compareId ); - console.warn( 'THREE.M2Loader: Unknown animation ID:', id ); - name = ''; + return list; - } + } - list.push( { - id: id, - name: name + listVariations( id ) { - } ); + const variationsSet = new Set(); - } + const animations = this._sequenceMap.get( id ); + + for ( const animation of animations ) { + + variationsSet.add( animation.variationIndex ); } - list.sort( sortId ); + const variations = Array.from( variationsSet ).sort(); - return list; + return variations; } @@ -3032,9 +3050,9 @@ class SequenceManager { } -function sortId( a, b ) { +function compareId( a, b ) { - return a.id > b.id; + return a.id - b.id; } diff --git a/test/index.html b/test/index.html index 403ce2b..1c0ed56 100644 --- a/test/index.html +++ b/test/index.html @@ -17,7 +17,8 @@ { "imports": { "three": "https://unpkg.com/three@0.160/build/three.module.js", - "three/addons/": "https://unpkg.com/three@0.160/examples/jsm/" + "three/addons/": "https://unpkg.com/three@0.160/examples/jsm/", + "lil-gui": "https://unpkg.com/lil-gui@0.19.1/dist/lil-gui.esm.js" } } @@ -27,13 +28,14 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; - import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + import { GUI } from 'lil-gui'; import { M2Loader } from '../M2Loader.js'; const params = { asset: 'cat/druidcat2.m2', - sequences: 0, + sequence: 0, + variation: 0, playGlobalSequences: true }; @@ -51,7 +53,7 @@ let camera, scene, renderer, controls, loader, clock; - let gui, animationFolder; + let gui, animationFolder, variationCtrl; let m2Scene, m2SequenceManager; @@ -115,20 +117,17 @@ // animations + animationFolder = gui.addFolder( 'Animations' ); + m2SequenceManager = m2.userData.sequenceManager; - // the list() methods provide arrays with all available sequences (animations) + // the list() method provide arrays with all available sequences (animations) const sequences = m2SequenceManager.listSequences(); - animationFolder = gui.addFolder( 'Animations' ); - if ( sequences.length > 0 ) { - const sequence = sequences[ 0 ]; // pick first sequence - m2SequenceManager.playSequence( sequence.id ); - - // make all sequences selectable via the UI + // make all sequences and variations selectable via the UI const uiSequences = {}; @@ -139,15 +138,21 @@ } - animationFolder.add( params, 'sequences', uiSequences ).onChange( onSequenceChange ); + animationFolder.add( params, 'sequence', uiSequences ).onChange( onSequenceChange ); + variationCtrl = animationFolder.add( params, 'variation', [] ).onChange( onVariationChange ); + + // play first sequence + + const sequence = sequences[ 0 ]; + onSequenceChange( sequence.id ); } if ( m2SequenceManager.hasGlobalSequences() ) { - m2SequenceManager.playGlobalSequences(); - animationFolder.add( params, 'playGlobalSequences' ).onChange( onPlayGlobalSequencesChange ); + + m2SequenceManager.playGlobalSequences(); } @@ -203,7 +208,8 @@ m2SequenceManager.stopSequence(); m2SequenceManager.stopGlobalSequences(); - params.sequences = 0; + params.sequence = 0; + params.variation = 0; params.playGlobalSequences = true; animationFolder.destroy(); @@ -217,6 +223,22 @@ m2SequenceManager.stopSequence(); m2SequenceManager.playSequence( id ); + // + + params.variation = 0; + + const variations = m2SequenceManager.listVariations( id ); + variationCtrl.options( variations ); + + ( variations.length > 1 ) ? variationCtrl.enable() : variationCtrl.disable(); + + } + + function onVariationChange( variationIndex ) { + + m2SequenceManager.stopSequence(); + m2SequenceManager.playSequence( m2SequenceManager.currentSequenceId, variationIndex ); + } function onPlayGlobalSequencesChange( value ) {