I've attached a sample script that creates a custom vizact action that animates a bone. The code at the bottom of the script shows how to use the action. This action will be included in the vizact library in the next release of Vizard. Let me know if anything is unclear.
Code:
import viz
viz.go()
"""
Code for creating action that animates a bone rotating
"""
_paramval_ = vizact._paramval_
_paramlist_ = vizact._paramlist_
VizCubicQuatInterpolator = vizact.VizCubicQuatInterpolator
VizLinearQuatInterpolator = vizact.VizLinearQuatInterpolator
def boneSpinTo(bone,mode=viz.ABS_PARENT,quat=None,euler=None,axisAngle=None,speed=None,time=None,p1=None,p2=None):
bla = viz.ActionData()
bla.bone = bone
bla.mode = mode
bla.speed = speed
bla.time = time
bla.quat = quat
bla.euler = euler
bla.axisAngle = axisAngle
bla.p1 = p1
bla.p2 = p2
bla.actionclass = VizBoneSpintToAction
return bla
class VizBoneSpintToAction(viz.ActionClass):
def begin(self,object):
self.elapsed = 0.0
self.duration = 0.0
#If bone is not a Vizard bone object, assume it is string and get bone from name
bone = _paramval_(self._actiondata_.bone,object)
if isinstance(bone,viz.VizBone):
self.bone = bone
else:
self.bone = object.getBone(bone)
#Make sure bone is valid
if not self.bone:
self.end(object)
return
#Lock the bone for animating
self.bone.lock()
#Get coordinate frame mode for bone rotations
self.mode = _paramval_(self._actiondata_.mode,object)
#Get begin and end rotation
beginQuat = self.bone.getQuat(self.mode)
if self._actiondata_.quat is not None:
self.endQuat = _paramlist_(self._actiondata_.quat,object)
elif self._actiondata_.euler is not None:
self.endQuat = vizmat.EulerToQuat(_paramlist_(self._actiondata_.euler,object))
elif self._actiondata_.axisAngle is not None:
self.endQuat = vizmat.AxisAngleToQuat(_paramlist_(self._actiondata_.axisAngle,object))
else:
self.end(object)
return
#Compute whether animation duration is based on time or speed
speed = _paramval_(self._actiondata_.speed,object)
time = _paramval_(self._actiondata_.time,object)
if time is not None:
self.duration = time
elif speed is not None:
self.duration = vizmat.QuatDiff(beginQuat,self.endQuat) / speed
#Make sure duration is valid
if self.duration <= 0.0:
self.bone.setQuat(self.endQuat,self.mode)
self.end(object)
return
#Check if we are using linear or cubic interpolation
p1 = _paramlist_(self._actiondata_.p1,object)
p2 = _paramlist_(self._actiondata_.p2,object)
if p1[0] is not None and p2[0] is not None:
interpolator = VizCubicQuatInterpolator(p1[0],p2[0])
else:
interpolator = VizLinearQuatInterpolator()
interpolator.init(beginQuat,self.endQuat)
self.interpolate = interpolator.interpolate
def update(self,elapsed,object):
self.elapsed += elapsed
p = self.elapsed / self.duration
if p >= 1.0:
self._overtime_ = self.elapsed - self.duration
self.bone.setQuat(self.endQuat,self.mode)
self.end(object)
return
self.bone.setQuat(self.interpolate(p),self.mode)
model = viz.add('vcc_female.cfg',pos=(0,0,5),euler=(180,0,0))
lookRight = boneSpinTo('Bip01 Spine1',mode=viz.AVATAR_LOCAL,euler=(45,0,0),speed=90)
lookLeft = boneSpinTo('Bip01 Spine1',mode=viz.AVATAR_LOCAL,euler=(-45,0,0),speed=90)
vizact.onkeydown(viz.KEY_RIGHT,model.runAction,lookRight,pool=1)
vizact.onkeydown(viz.KEY_LEFT,model.runAction,lookLeft,pool=1)