Created
May 13, 2020 09:17
-
-
Save devcem/0de6441f43326e438dfbadfc1bcea510 to your computer and use it in GitHub Desktop.
PlayCanvas animation blending, a clone from repository
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Mixer = pc.createScript('mixer'); | |
Mixer.attributes.add('spineBone', { type: 'string', default: 'SpineBone', title: 'Spine Bone' }); | |
Mixer.attributes.add('upperLayerMask', { type: 'string', array : true }); | |
Mixer.attributes.add('lowerLayerMask', { type: 'string', array : true }); | |
Mixer.attributes.add('animationNames', { type: 'string', array : true }); | |
Mixer.attributes.add('animationMasks', { type: 'string', array : true }); | |
Mixer.prototype.initialize = function() { | |
this.skins = this.entity.model.model.skinInstances; | |
this.bones = {}; | |
this.force = false; | |
this.timestamp = 0; | |
this.currentTime = 0; | |
this.currentSpeed = 1; | |
this.animationStop = false; | |
for(var s = 0; s < this.skins.length; s++) { | |
for(var b = 0; b < this.skins[s].bones.length; b++) { | |
this.bones[this.skins[s].bones[b].name] = this.skins[s].bones[b]; | |
} | |
} | |
this.layers = []; | |
this.frames = []; | |
this.animations = this.entity.animation.data.animations; | |
for(var animationIndex in this.animationNames){ | |
var animation = this.animationNames[animationIndex]; | |
this.layers.push(this.CreateAvatarAnim( | |
this.spineBone, | |
this[this.animationMasks[animationIndex]], | |
this.CreateLayerAnim(this[this.animationMasks[animationIndex]], animation, | |
this.entity.animation.getAnimation(animation) | |
) | |
)); | |
} | |
}; | |
Mixer.prototype.CreateLayerAnim = function(layer, id, anim){ | |
return { | |
'layer' : layer, | |
'id' : id, | |
'anim' : anim | |
}; | |
}; | |
Mixer.prototype.CreateSkeleton = function(rootBone, skinnedMesh, targetBones) { | |
var boneGraph = skinnedMesh.model.model.getGraph(); | |
var rootBoneNodes = boneGraph.findByName(rootBone); | |
var bones = { }; | |
var thisGraph = []; | |
var skins = skinnedMesh.model.model.skinInstances; | |
for(var s = 0; s < skins.length; s++) { | |
for(var b = 0; b < skins[s].bones.length; b++) { | |
bones[skins[s].bones[b].name] = skins[s].bones[b]; | |
} | |
} | |
for(var index in targetBones) { | |
var boneNode = targetBones[index]; | |
for(var xindex in bones) { | |
var bone = bones[xindex]; | |
if(bone.name == boneNode) { | |
thisGraph.push(bone); | |
} | |
} | |
} | |
var rootBoneSkeleton = new pc.Skeleton(rootBoneNodes); | |
rootBoneSkeleton.setGraph(rootBoneNodes); | |
rootBoneSkeleton.boneGraph = thisGraph; | |
return rootBoneSkeleton; | |
}; | |
Mixer.prototype.CreateAvatarAnim = function(rootBone, targetBones, animObject, animation){ | |
var thisSkeleton = this.CreateSkeleton(rootBone, this.entity, targetBones); | |
this.layerSkeletonAnimClip = new pc.Animation(); | |
var layerSkeletonNodes = animObject.anim.nodes; | |
var relevantFilteredNodes = layerSkeletonNodes.filter(function(node) { | |
for(var index in targetBones) { | |
var skelNode = targetBones[index]; | |
if(node._name == skelNode) { | |
return node; | |
} | |
} | |
}); | |
for(var index in relevantFilteredNodes) { | |
var node = relevantFilteredNodes[index]; | |
if(index != "binaryIndexOf"){ | |
this.layerSkeletonAnimClip.addNode(node); | |
} | |
} | |
this.layerSkeletonAnimClip.name = animObject.id; | |
this.layerSkeletonAnimClip.duration = animObject.anim.duration; | |
thisSkeleton.animation = this.layerSkeletonAnimClip; | |
thisSkeleton.updateAnim = false; | |
thisSkeleton.targetBones = targetBones; | |
thisSkeleton.id = animObject.id; | |
return thisSkeleton; | |
}; | |
Mixer.prototype.play = function(id, time, speed) { | |
this.layers.find(function(layer){ | |
if(layer.id == id) { | |
layer.updateAnim = true; | |
} | |
}); | |
this.timestamp = 0; | |
this.currentTime = time; | |
this.currentSpeed = speed; | |
this.animationStop = false; | |
}; | |
Mixer.prototype.stop = function() { | |
if(this.animationStop){ | |
return false; | |
} | |
this.force = true; | |
this.currentTime = 0; | |
this.timestamp = 0; | |
for(var index in this.layers) { | |
var skeletonLayer = this.layers[index]; | |
skeletonLayer.updateAnim = false; | |
} | |
this.animationStop = true; | |
}; | |
Mixer.prototype.postUpdate = function(dt) { | |
for(var index in this.layers) { | |
var skeletonLayer = this.layers[index]; | |
if(skeletonLayer.updateAnim) { | |
skeletonLayer.addTime(dt * this.currentSpeed); | |
skeletonLayer.updateGraph(); | |
} | |
} | |
if(this.timestamp > this.currentTime){ | |
this.stop(); | |
} | |
this.timestamp+=dt; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey @devcem, does this still work? I would really like to use this, but cannot figure it out. Thanks