Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[splib3] Adds features and one fix #116

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 34 additions & 15 deletions python3/src/splib3/animation/animate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import Sofa.Core
from splib3.utils import deprecated_alias


class Animation(object):
"""An animation clip that trigger callback at regular intervales for a given duration.

Expand All @@ -27,12 +28,17 @@ def onDone(target, factor):

animate(onUpdate, {"target" : rootNode }, 12, onDone=onDone)
"""

@deprecated_alias(cb='onUpdate')
def __init__(self, duration, mode, onUpdate, params, onDone=None):
def __init__(self, duration, mode, onUpdate, params, onDone=None, terminationDelay=None):
if 'startTime' in params:
self.startTime = params['startTime']
else:
self.startTime = None
self.startTimeInit = None

self.terminationDelay = terminationDelay
self.terminationDelayInit = self.terminationDelay

self.duration = duration
self.onUpdate = onUpdate
Expand All @@ -42,6 +48,10 @@ def __init__(self, duration, mode, onUpdate, params, onDone=None):
self.direction = 1.0
self.mode = mode

def reset(self):
self.startTime = self.startTimeInit
self.terminationDelay = self.terminationDelayInit

def doOnDone(self, currentTime):
self.onDone(factor=self.factor, **self.params)

Expand All @@ -52,9 +62,9 @@ def update(self, currentTime):
if self.duration == 0.0:
self.factor = 1.0
elif self.direction > 0.0:
self.factor = (currentTime-self.startTime) / self.duration
self.factor = (currentTime - self.startTime) / self.duration
else:
self.factor = 1.0-(currentTime-self.startTime) / self.duration
self.factor = 1.0 - (currentTime - self.startTime) / self.duration

if self.factor > 1.0:
self.factor = 1.0
Expand All @@ -77,9 +87,10 @@ def __init__(self, *args, **kwargs):
self.node = args[0]
self.totalTime = 0
self.animations = []

def clearAnimations(self):
self.animations = []
self.totalTime = 0

def addAnimation(self, animation):
self.animations.append(animation)
Expand All @@ -92,20 +103,23 @@ def bwdInitGraph(self, root):

def onAnimateBeginEvent(self, event):
self.totalTime += self.node.getRoot().dt.value

nextanimations = []
for animation in self.animations:
if self.totalTime == 0:
animation.reset()
animation.update(self.totalTime)
if animation.factor < 1.0 and animation.direction > 0.0:
nextanimations.append(animation)
elif animation.factor > 0.0 and animation.direction < 0.0:
nextanimations.append(animation)
elif animation.mode == "pingpong":
animation.direction = -animation.direction
animation.startTime = None
animation.startTime = animation.duration + animation.terminationDelay + animation.startTime if animation.terminationDelay is not None else None
nextanimations.append(animation)
elif animation.mode == "loop":
animation.direction = animation.direction
animation.startTime = None
animation.startTime = animation.duration + animation.terminationDelay + animation.startTime if animation.terminationDelay is not None else None
nextanimations.append(animation)
elif animation.onDone is not None:
animation.doOnDone(self.totalTime)
Expand All @@ -115,7 +129,8 @@ def onAnimateBeginEvent(self, event):

manager = None

def animate(onUpdate, params, duration, mode="once", onDone=None):

def animate(onUpdate, params, duration, mode="once", onDone=None, terminationDelay=None):
"""Construct and starts an animation

Build a new animation from a callback function that computes the animation value,
Expand All @@ -137,18 +152,20 @@ def createScene(rootNode)
AnimationManager(rootNode)
animate(myAnimate, {"target" : rootNode }, 10)
"""
if manager == None:
if manager is None:
raise Exception("Missing manager in this scene")

manager.addAnimation(Animation(duration=duration, mode=mode, onUpdate=onUpdate, params=params, onDone=onDone))
manager.addAnimation(Animation(duration=duration, mode=mode, onUpdate=onUpdate, params=params,
onDone=onDone, terminationDelay=terminationDelay))


def removeAnimation(animation):
if manager == None:
if manager is None:
raise Exception("Missing manager in this scene")

manager.removeAnimation(animation)


def AnimationManager(node):
"""
A Controller to manage all animations in the scene
Expand All @@ -168,7 +185,8 @@ def createScene(rootNode)
"""
global manager
if manager is not None:
#Sofa.msg_info(node, "There is already one animation manager in this scene...why do you need a second one ? Resting it.")
# Sofa.msg_info(node, "There is already one animation manager
# in this scene...why do you need a second one ? Resting it.")
manager.clearAnimations()
return manager
manager = AnimationManagerController(node)
Expand All @@ -177,15 +195,16 @@ def createScene(rootNode)

# This function is just an example on how to use the animate function.
def createScene(rootNode):
def myAnimate1(target, factor):
print("I should do something on: "+target.name+" factor is: "+str(factor))
def myAnimate1(target, factor, terminationDelay=0):
print("I should do something on: " + target.getName() + " factor is: " + str(factor))

def myAnimate2(target, factor):
print("Function 2: "+target.name+" factor is: "+str(factor))
print("Function 2: " + target.getName() + " factor is: " + str(factor))

def myOnDone(target, factor):
print("onDone: "+target.name+" factor is: "+str(factor))
print("onDone: " + target.getName() + " factor is: " + str(factor))

rootNode.addObject(AnimationManager(rootNode))
animate(myAnimate1, {"target": rootNode}, 10)
animate(myAnimate2, {"target": rootNode}, 12, onDone=myOnDone)
animate(myAnimate1, {"target": rootNode}, 2, mode="loop", terminationDelay=2)
13 changes: 12 additions & 1 deletion python3/src/splib3/numerics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
RigidDofZero = [0.0,0.0,0.0,0.0,0.0,0.0,1.0]

def to_radians(v):
"""Converts degree to radians
"""Converts degrees to radians

:param v: the angle to convert
"""
Expand All @@ -58,6 +58,17 @@ def to_radians(v):
return p
return v * pi * 2.0 / 360.0

def to_degrees(v):
"""Converts radians to degrees

:param v: the angle to convert
"""
if isinstance(v, list):
p = []
for tp in v:
p.append( tp / pi / 2.0 * 360.0 )
return p
return v / pi / 2.0 * 360.0

def TRS_to_matrix(translation, rotation=None, scale=None, eulerRotation=None):
t = numpy.identity(4)
Expand Down
6 changes: 4 additions & 2 deletions python3/src/splib3/numerics/quat.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Quat(numpy.ndarray):
q = Quat.product(q1,q2)
q = Quat.createFromEuler([x,y,z])
q = Quat.createFromAxisAngle([axis],angle)
q = Quat.createFromVectors(v1, v2)
"""

def __new__(cls, *args):
Expand Down Expand Up @@ -317,13 +318,13 @@ def createFromAxisAngle(axis, angle):
return q

@staticmethod
def createFromEuler(a, axes='sxyz', inDegree=False):
def createFromEuler(v, axes='sxyz', inDegree=False):
"""Returns a quaternion from Euler angles (in radian) and axis sequence.
The quaternion is of type Quat.

Args:

a is a list of three Euler angles [x,y,z]
v is a list of three Euler angles [x,y,z]
axes : One of 24 axis sequences as string or encoded tuple

Example:
Expand All @@ -337,6 +338,7 @@ def createFromEuler(a, axes='sxyz', inDegree=False):
[ 0.5 -0.5 0.5 0.5]
"""

a = numpy.copy(v)
if inDegree:
a = [a[0] * pi / 180, a[1] * pi / 180, a[2] * pi / 180]

Expand Down
Loading