Skip to content

Commit 41a13ac

Browse files
committed
add support for booleananimationtracks
1 parent 2bc3d7b commit 41a13ac

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/GLTFLoaderAnimationPointer.js

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
PropertyBinding,
88
QuaternionKeyframeTrack,
99
VectorKeyframeTrack,
10-
SkinnedMesh
10+
SkinnedMesh,
11+
BooleanKeyframeTrack
1112
} from 'three';
1213

1314
/**
@@ -414,6 +415,29 @@ export class GLTFAnimationPointerExtension {
414415
// default
415416
__createTrack( this.parser );
416417

418+
419+
function isBooleanTarget(node, trackPath) {
420+
// trackPath like ".nodes.MyNode.visible" or ".materials.<uuid>.wireframe"
421+
try {
422+
423+
// get last token after '.'
424+
const sections = trackPath.split('.').filter(Boolean);
425+
let last = sections[sections.length - 1]; // e.g., 'visible' or 'iridescenceThicknessRange[0]'
426+
427+
// strip indexers like [0]
428+
const propName = last.replace(/\[.*\]$/, '');
429+
430+
// bail if not a direct property
431+
if (!(propName in node)) return false;
432+
433+
const val = node[propName];
434+
return typeof val === 'boolean';
435+
}
436+
catch {
437+
return false;
438+
}
439+
}
440+
417441
/** Create a new track using the current parts array */
418442
function __createTrack( parser ) {
419443

@@ -423,11 +447,31 @@ export class GLTFAnimationPointerExtension {
423447
console.log( node, inputAccessor, outputAccessor, target, animationPointerPropertyPath );
424448

425449
let TypedKeyframeTrack;
426-
450+
let convertToBoolean = false;
427451
switch ( outputAccessor.itemSize ) {
428452

429-
case 1:
430-
TypedKeyframeTrack = NumberKeyframeTrack;
453+
case 1:
454+
// Get type of outputAccessor.array elements
455+
const arrayType = Object.prototype.toString.call(outputAccessor.array);
456+
const isUInt8 = (arrayType === '[object Uint8Array]');
457+
458+
const looksLikeBool = isUInt8 && // UNSIGNED_BYTE as a strong hint
459+
isBooleanTarget(node, animationPointerPropertyPath);
460+
461+
// Log once per target property if it looks like a boolean
462+
if (looksLikeBool) {
463+
console.log('Assuming boolean animation for', animationPointerPropertyPath, 'based on property type and accessor type');
464+
}
465+
else
466+
{
467+
console.log('Not a boolean target', animationPointerPropertyPath);
468+
}
469+
if (looksLikeBool) {
470+
TypedKeyframeTrack = BooleanKeyframeTrack;
471+
convertToBoolean = true; // map 0 => false, >0 => true
472+
} else {
473+
TypedKeyframeTrack = NumberKeyframeTrack;
474+
}
431475
break;
432476
case 2:
433477
case 3:
@@ -457,7 +501,11 @@ export class GLTFAnimationPointerExtension {
457501
if ( animationPointerPropertyPath.endsWith( '.fov' ) ) {
458502

459503
outputArray = outputArray.map( value => value / Math.PI * 180 );
504+
}
460505

506+
if (convertToBoolean) {
507+
// boolean values are stored as ubyte in glTF, 0 = false, anything else = true
508+
outputArray = outputArray.map( v => v > 0 );
461509
}
462510

463511
const track = new TypedKeyframeTrack(

0 commit comments

Comments
 (0)