Skip to content

Commit d5819c8

Browse files
committed
Move property binding patching out of plugin scope
1 parent fe21e02 commit d5819c8

File tree

1 file changed

+107
-107
lines changed

1 file changed

+107
-107
lines changed

src/GLTFLoaderAnimationPointer.js

Lines changed: 107 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
@@ -1,729 +0,0 @@
21
import {
32
AnimationClip,
43
ColorKeyframeTrack,
@@ -33,14 +32,13 @@ const INTERPOLATION = {
3332
// HACK monkey patching findNode to ensure we can map to other types required by KHR_animation_pointer.
3433
const find = PropertyBinding.findNode;
3534
const _animationPointerDebug = false;
36-
let _havePatchedPropertyBindings = false;
3735

3836
/**
3937
* Animation Pointer Extension
4038
*
4139
* Draft Specification: https://github.com/ux3d/glTF/tree/extensions/KHR_animation_pointer/extensions/2.0/Khronos/KHR_animation_pointer
4240
*/
43-
class GLTFAnimationPointerExtension {
41+
export class GLTFAnimationPointerExtension {
4442

4543
constructor( parser ) {
4644

@@ -57,107 +55,6 @@ class GLTFAnimationPointerExtension {
5755

5856
}
5957

60-
_patchPropertyBindingFindNode() {
61-
62-
if ( _havePatchedPropertyBindings ) return;
63-
_havePatchedPropertyBindings = true;
64-
65-
// "node" is the Animator component in our case
66-
// "path" is the animated property path, just with translated material names.
67-
PropertyBinding.findNode = function ( node, path ) {
68-
69-
if ( path.startsWith( '.materials.' ) ) {
70-
71-
if ( _animationPointerDebug ) console.log( 'FIND', path );
72-
73-
const remainingPath = path.substring( '.materials.'.length ).substring( path.indexOf( '.' ) );
74-
const nextIndex = remainingPath.indexOf( '.' );
75-
const uuid = nextIndex < 0 ? remainingPath : remainingPath.substring( 0, nextIndex );
76-
let res = null;
77-
node.traverse( x => {
78-
79-
if ( res !== null || ( x.type !== 'Mesh' && x.type !== 'SkinnedMesh' ) ) return;
80-
if ( x[ 'material' ] && ( x[ 'material' ].uuid === uuid || x[ 'material' ].name === uuid ) ) {
81-
82-
res = x[ 'material' ];
83-
if ( _animationPointerDebug ) console.log( res, remainingPath );
84-
if ( res !== null ) {
85-
86-
if ( remainingPath.endsWith( '.map' ) )
87-
res = res[ 'map' ];
88-
else if ( remainingPath.endsWith( '.emissiveMap' ) )
89-
res = res[ 'emissiveMap' ];
90-
91-
// TODO other texture slots only make sense if three.js actually supports them
92-
// (currently only .map can have repeat/offset)
93-
94-
}
95-
96-
}
97-
98-
} );
99-
100-
return res;
101-
102-
} else if ( path.startsWith( '.nodes.' ) || path.startsWith( '.lights.' ) || path.startsWith( '.cameras.' ) ) {
103-
104-
const sections = path.split( '.' );
105-
let currentTarget = undefined;
106-
for ( let i = 1; i < sections.length; i ++ ) {
107-
108-
const val = sections[ i ];
109-
const isUUID = val.length == 36;
110-
if ( isUUID ) {
111-
112-
// access by UUID
113-
currentTarget = node.getObjectByProperty( 'uuid', val );
114-
115-
} else if ( currentTarget && currentTarget[ val ] ) {
116-
117-
// access by index
118-
const index = Number.parseInt( val );
119-
let key = val;
120-
if ( index >= 0 ) key = index;
121-
currentTarget = currentTarget[ key ];
122-
if ( _animationPointerDebug )
123-
console.log( currentTarget );
124-
125-
} else {
126-
127-
// access by node name
128-
const foundNode = node.getObjectByName( val );
129-
130-
if ( foundNode )
131-
currentTarget = foundNode;
132-
133-
}
134-
135-
}
136-
137-
if ( ! currentTarget ) {
138-
139-
const originalFindResult = find( node, sections[ 2 ] );
140-
141-
if ( ! originalFindResult )
142-
console.warn( KHR_ANIMATION_POINTER + ': Property binding not found', path, node, node.name, sections );
143-
144-
return originalFindResult;
145-
146-
}
147-
148-
if ( _animationPointerDebug )
149-
console.log( 'NODE', path, currentTarget );
150-
151-
return currentTarget;
152-
153-
}
154-
155-
return find( node, path );
156-
157-
};
158-
159-
}
160-
16158
/* DUPLICATE of functionality in GLTFLoader */
16259
loadAnimationTargetFromChannel( animationChannel ) {
16360

@@ -169,8 +66,7 @@ class GLTFAnimationPointerExtension {
16966

17067
loadAnimationTargetFromChannelWithAnimationPointer( animationChannel ) {
17168

172-
if ( ! this._havePatchedPropertyBindings )
173-
this._patchPropertyBindingFindNode();
69+
_ensurePropertyBindingPatch();
17470

17571
const target = animationChannel.target;
17672
const useExtension = target.extensions && target.extensions[ KHR_ANIMATION_POINTER ] && target.path && target.path === 'pointer';
@@ -727,4 +623,108 @@ class GLTFAnimationPointerExtension {
727623

728624
}
729625

730-
export { GLTFAnimationPointerExtension };
626+
627+
628+
let _havePatchedPropertyBindings = false;
629+
630+
function _ensurePropertyBindingPatch() {
631+
632+
if (_havePatchedPropertyBindings) return;
633+
_havePatchedPropertyBindings = true;
634+
635+
// "node" is the Animator component in our case
636+
// "path" is the animated property path, just with translated material names.
637+
PropertyBinding.findNode = function (node, path) {
638+
639+
if (path.startsWith('.materials.')) {
640+
641+
if (_animationPointerDebug) console.log('FIND', path);
642+
643+
const remainingPath = path.substring('.materials.'.length).substring(path.indexOf('.'));
644+
const nextIndex = remainingPath.indexOf('.');
645+
const uuid = nextIndex < 0 ? remainingPath : remainingPath.substring(0, nextIndex);
646+
let res = null;
647+
node.traverse(x => {
648+
649+
if (res !== null || (x.type !== 'Mesh' && x.type !== 'SkinnedMesh')) return;
650+
if (x['material'] && (x['material'].uuid === uuid || x['material'].name === uuid)) {
651+
652+
res = x['material'];
653+
if (_animationPointerDebug) console.log(res, remainingPath);
654+
if (res !== null) {
655+
656+
if (remainingPath.endsWith('.map'))
657+
res = res['map'];
658+
else if (remainingPath.endsWith('.emissiveMap'))
659+
res = res['emissiveMap'];
660+
661+
// TODO other texture slots only make sense if three.js actually supports them
662+
// (currently only .map can have repeat/offset)
663+
664+
}
665+
666+
}
667+
668+
});
669+
670+
return res;
671+
672+
} else if (path.startsWith('.nodes.') || path.startsWith('.lights.') || path.startsWith('.cameras.')) {
673+
674+
const sections = path.split('.');
675+
let currentTarget = undefined;
676+
for (let i = 1; i < sections.length; i++) {
677+
678+
const val = sections[i];
679+
const isUUID = val.length == 36;
680+
if (isUUID) {
681+
682+
// access by UUID
683+
currentTarget = node.getObjectByProperty('uuid', val);
684+
685+
} else if (currentTarget && currentTarget[val]) {
686+
687+
// access by index
688+
const index = Number.parseInt(val);
689+
/** @type {string|number} */
690+
let key = val;
691+
if (index >= 0) key = index;
692+
currentTarget = currentTarget[key];
693+
if (_animationPointerDebug)
694+
console.log(currentTarget);
695+
696+
} else {
697+
698+
// access by node name
699+
const foundNode = node.getObjectByName(val);
700+
701+
if (foundNode)
702+
currentTarget = foundNode;
703+
704+
}
705+
706+
}
707+
708+
if (!currentTarget) {
709+
710+
const originalFindResult = find(node, sections[2]);
711+
712+
if (!originalFindResult)
713+
console.warn(KHR_ANIMATION_POINTER + ': Property binding not found', path, node, node.name, sections);
714+
715+
return originalFindResult;
716+
717+
}
718+
719+
if (_animationPointerDebug)
720+
console.log('NODE', path, currentTarget);
721+
722+
return currentTarget;
723+
724+
}
725+
726+
return find(node, path);
727+
728+
};
729+
730+
}

0 commit comments

Comments
 (0)