Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three /src /animation /AnimationObjectGroup.js
| import { PropertyBinding } from './PropertyBinding.js'; | |
| import * as MathUtils from '../math/MathUtils.js'; | |
| /** | |
| * | |
| * A group of objects that receives a shared animation state. | |
| * | |
| * Usage: | |
| * | |
| * - Add objects you would otherwise pass as 'root' to the | |
| * constructor or the .clipAction method of AnimationMixer. | |
| * | |
| * - Instead pass this object as 'root'. | |
| * | |
| * - You can also add and remove objects later when the mixer | |
| * is running. | |
| * | |
| * Note: | |
| * | |
| * Objects of this class appear as one object to the mixer, | |
| * so cache control of the individual objects must be done | |
| * on the group. | |
| * | |
| * Limitation: | |
| * | |
| * - The animated properties must be compatible among the | |
| * all objects in the group. | |
| * | |
| * - A single property can either be controlled through a | |
| * target group or directly, but not both. | |
| */ | |
| class AnimationObjectGroup { | |
| constructor() { | |
| this.isAnimationObjectGroup = true; | |
| this.uuid = MathUtils.generateUUID(); | |
| // cached objects followed by the active ones | |
| this._objects = Array.prototype.slice.call( arguments ); | |
| this.nCachedObjects_ = 0; // threshold | |
| // note: read by PropertyBinding.Composite | |
| const indices = {}; | |
| this._indicesByUUID = indices; // for bookkeeping | |
| for ( let i = 0, n = arguments.length; i !== n; ++ i ) { | |
| indices[ arguments[ i ].uuid ] = i; | |
| } | |
| this._paths = []; // inside: string | |
| this._parsedPaths = []; // inside: { we don't care, here } | |
| this._bindings = []; // inside: Array< PropertyBinding > | |
| this._bindingsIndicesByPath = {}; // inside: indices in these arrays | |
| const scope = this; | |
| this.stats = { | |
| objects: { | |
| get total() { | |
| return scope._objects.length; | |
| }, | |
| get inUse() { | |
| return this.total - scope.nCachedObjects_; | |
| } | |
| }, | |
| get bindingsPerObject() { | |
| return scope._bindings.length; | |
| } | |
| }; | |
| } | |
| add() { | |
| const objects = this._objects, | |
| indicesByUUID = this._indicesByUUID, | |
| paths = this._paths, | |
| parsedPaths = this._parsedPaths, | |
| bindings = this._bindings, | |
| nBindings = bindings.length; | |
| let knownObject = undefined, | |
| nObjects = objects.length, | |
| nCachedObjects = this.nCachedObjects_; | |
| for ( let i = 0, n = arguments.length; i !== n; ++ i ) { | |
| const object = arguments[ i ], | |
| uuid = object.uuid; | |
| let index = indicesByUUID[ uuid ]; | |
| if ( index === undefined ) { | |
| // unknown object -> add it to the ACTIVE region | |
| index = nObjects ++; | |
| indicesByUUID[ uuid ] = index; | |
| objects.push( object ); | |
| // accounting is done, now do the same for all bindings | |
| for ( let j = 0, m = nBindings; j !== m; ++ j ) { | |
| bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); | |
| } | |
| } else if ( index < nCachedObjects ) { | |
| knownObject = objects[ index ]; | |
| // move existing object to the ACTIVE region | |
| const firstActiveIndex = -- nCachedObjects, | |
| lastCachedObject = objects[ firstActiveIndex ]; | |
| indicesByUUID[ lastCachedObject.uuid ] = index; | |
| objects[ index ] = lastCachedObject; | |
| indicesByUUID[ uuid ] = firstActiveIndex; | |
| objects[ firstActiveIndex ] = object; | |
| // accounting is done, now do the same for all bindings | |
| for ( let j = 0, m = nBindings; j !== m; ++ j ) { | |
| const bindingsForPath = bindings[ j ], | |
| lastCached = bindingsForPath[ firstActiveIndex ]; | |
| let binding = bindingsForPath[ index ]; | |
| bindingsForPath[ index ] = lastCached; | |
| if ( binding === undefined ) { | |
| // since we do not bother to create new bindings | |
| // for objects that are cached, the binding may | |
| // or may not exist | |
| binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); | |
| } | |
| bindingsForPath[ firstActiveIndex ] = binding; | |
| } | |
| } else if ( objects[ index ] !== knownObject ) { | |
| console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + | |
| 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); | |
| } // else the object is already where we want it to be | |
| } // for arguments | |
| this.nCachedObjects_ = nCachedObjects; | |
| } | |
| remove() { | |
| const objects = this._objects, | |
| indicesByUUID = this._indicesByUUID, | |
| bindings = this._bindings, | |
| nBindings = bindings.length; | |
| let nCachedObjects = this.nCachedObjects_; | |
| for ( let i = 0, n = arguments.length; i !== n; ++ i ) { | |
| const object = arguments[ i ], | |
| uuid = object.uuid, | |
| index = indicesByUUID[ uuid ]; | |
| if ( index !== undefined && index >= nCachedObjects ) { | |
| // move existing object into the CACHED region | |
| const lastCachedIndex = nCachedObjects ++, | |
| firstActiveObject = objects[ lastCachedIndex ]; | |
| indicesByUUID[ firstActiveObject.uuid ] = index; | |
| objects[ index ] = firstActiveObject; | |
| indicesByUUID[ uuid ] = lastCachedIndex; | |
| objects[ lastCachedIndex ] = object; | |
| // accounting is done, now do the same for all bindings | |
| for ( let j = 0, m = nBindings; j !== m; ++ j ) { | |
| const bindingsForPath = bindings[ j ], | |
| firstActive = bindingsForPath[ lastCachedIndex ], | |
| binding = bindingsForPath[ index ]; | |
| bindingsForPath[ index ] = firstActive; | |
| bindingsForPath[ lastCachedIndex ] = binding; | |
| } | |
| } | |
| } // for arguments | |
| this.nCachedObjects_ = nCachedObjects; | |
| } | |
| // remove & forget | |
| uncache() { | |
| const objects = this._objects, | |
| indicesByUUID = this._indicesByUUID, | |
| bindings = this._bindings, | |
| nBindings = bindings.length; | |
| let nCachedObjects = this.nCachedObjects_, | |
| nObjects = objects.length; | |
| for ( let i = 0, n = arguments.length; i !== n; ++ i ) { | |
| const object = arguments[ i ], | |
| uuid = object.uuid, | |
| index = indicesByUUID[ uuid ]; | |
| if ( index !== undefined ) { | |
| delete indicesByUUID[ uuid ]; | |
| if ( index < nCachedObjects ) { | |
| // object is cached, shrink the CACHED region | |
| const firstActiveIndex = -- nCachedObjects, | |
| lastCachedObject = objects[ firstActiveIndex ], | |
| lastIndex = -- nObjects, | |
| lastObject = objects[ lastIndex ]; | |
| // last cached object takes this object's place | |
| indicesByUUID[ lastCachedObject.uuid ] = index; | |
| objects[ index ] = lastCachedObject; | |
| // last object goes to the activated slot and pop | |
| indicesByUUID[ lastObject.uuid ] = firstActiveIndex; | |
| objects[ firstActiveIndex ] = lastObject; | |
| objects.pop(); | |
| // accounting is done, now do the same for all bindings | |
| for ( let j = 0, m = nBindings; j !== m; ++ j ) { | |
| const bindingsForPath = bindings[ j ], | |
| lastCached = bindingsForPath[ firstActiveIndex ], | |
| last = bindingsForPath[ lastIndex ]; | |
| bindingsForPath[ index ] = lastCached; | |
| bindingsForPath[ firstActiveIndex ] = last; | |
| bindingsForPath.pop(); | |
| } | |
| } else { | |
| // object is active, just swap with the last and pop | |
| const lastIndex = -- nObjects, | |
| lastObject = objects[ lastIndex ]; | |
| if ( lastIndex > 0 ) { | |
| indicesByUUID[ lastObject.uuid ] = index; | |
| } | |
| objects[ index ] = lastObject; | |
| objects.pop(); | |
| // accounting is done, now do the same for all bindings | |
| for ( let j = 0, m = nBindings; j !== m; ++ j ) { | |
| const bindingsForPath = bindings[ j ]; | |
| bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; | |
| bindingsForPath.pop(); | |
| } | |
| } // cached or active | |
| } // if object is known | |
| } // for arguments | |
| this.nCachedObjects_ = nCachedObjects; | |
| } | |
| // Internal interface used by befriended PropertyBinding.Composite: | |
| subscribe_( path, parsedPath ) { | |
| // returns an array of bindings for the given path that is changed | |
| // according to the contained objects in the group | |
| const indicesByPath = this._bindingsIndicesByPath; | |
| let index = indicesByPath[ path ]; | |
| const bindings = this._bindings; | |
| if ( index !== undefined ) return bindings[ index ]; | |
| const paths = this._paths, | |
| parsedPaths = this._parsedPaths, | |
| objects = this._objects, | |
| nObjects = objects.length, | |
| nCachedObjects = this.nCachedObjects_, | |
| bindingsForPath = new Array( nObjects ); | |
| index = bindings.length; | |
| indicesByPath[ path ] = index; | |
| paths.push( path ); | |
| parsedPaths.push( parsedPath ); | |
| bindings.push( bindingsForPath ); | |
| for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) { | |
| const object = objects[ i ]; | |
| bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); | |
| } | |
| return bindingsForPath; | |
| } | |
| unsubscribe_( path ) { | |
| // tells the group to forget about a property path and no longer | |
| // update the array previously obtained with 'subscribe_' | |
| const indicesByPath = this._bindingsIndicesByPath, | |
| index = indicesByPath[ path ]; | |
| if ( index !== undefined ) { | |
| const paths = this._paths, | |
| parsedPaths = this._parsedPaths, | |
| bindings = this._bindings, | |
| lastBindingsIndex = bindings.length - 1, | |
| lastBindings = bindings[ lastBindingsIndex ], | |
| lastBindingsPath = path[ lastBindingsIndex ]; | |
| indicesByPath[ lastBindingsPath ] = index; | |
| bindings[ index ] = lastBindings; | |
| bindings.pop(); | |
| parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; | |
| parsedPaths.pop(); | |
| paths[ index ] = paths[ lastBindingsIndex ]; | |
| paths.pop(); | |
| } | |
| } | |
| } | |
| export { AnimationObjectGroup }; | |
Xet Storage Details
- Size:
- 9.23 kB
- Xet hash:
- cbb2a6a183a454b1ed61deadf7a8ab35ecaa6a4b849b90459b3e1fd0a1369104
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.