LerpInterval.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. """LerpInterval module: contains the LerpInterval class"""
  2. from Interval import *
  3. from PandaModules import *
  4. import LerpBlendHelpers
  5. class LerpInterval(Interval):
  6. # create LerpInterval DirectNotify category
  7. notify = directNotify.newCategory('LerpInterval')
  8. # Class methods
  9. def __init__(self, name, duration, functorFunc, blendType='noBlend'):
  10. """__init__(name, duration, functorFunc, blendType)
  11. """
  12. # Record instance variables
  13. self.lerp = None
  14. self.functorFunc = functorFunc
  15. self.blendType = self.getBlend(blendType)
  16. # Initialize superclass
  17. Interval.__init__(self, name, duration)
  18. def updateFunc(self, t, event = IVAL_NONE):
  19. """ updateFunc(t, event)
  20. """
  21. # Check to see if we need to create the lerp
  22. if (event == IVAL_INIT):
  23. self.lerp = Lerp(self.functorFunc(), self.duration,
  24. self.blendType)
  25. # Make sure lerp exists
  26. if (not self.lerp):
  27. self.lerp = Lerp(self.functorFunc(), self.duration,
  28. self.blendType)
  29. # Evaluate the lerp
  30. self.lerp.setT(t)
  31. # Print debug information
  32. self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t))
  33. def getBlend(self, blendType):
  34. """__getBlend(self, string)
  35. Return the C++ blend class corresponding to blendType string
  36. """
  37. if (blendType == "easeIn"):
  38. return LerpBlendHelpers.easeIn
  39. elif (blendType == "easeOut"):
  40. return LerpBlendHelpers.easeOut
  41. elif (blendType == "easeInOut"):
  42. return LerpBlendHelpers.easeInOut
  43. elif (blendType == "noBlend"):
  44. return LerpBlendHelpers.noBlend
  45. else:
  46. raise Exception(
  47. 'Error: LerpInterval.__getBlend: Unknown blend type')
  48. class LerpPosInterval(LerpInterval):
  49. # Name counter
  50. lerpPosNum = 1
  51. # Class methods
  52. def __init__(self, node, duration, pos, startPos=None,
  53. other=None, blendType='noBlend', name=None):
  54. """ __init__(node, duration, pos, startPos, other, blendType, name)
  55. """
  56. def functorFunc(node=node, pos=pos, startPos=startPos,
  57. other=other):
  58. assert(not node.isEmpty())
  59. if callable(pos):
  60. # This may be a thunk that returns a point.
  61. pos = pos()
  62. if (other != None):
  63. # lerp wrt other
  64. if (startPos == None):
  65. startPos = node.getPos(other)
  66. functor = PosLerpFunctor(node, startPos, pos, other)
  67. else:
  68. if (startPos == None):
  69. startPos = node.getPos()
  70. functor = PosLerpFunctor(node, startPos, pos)
  71. return functor
  72. # Generate unique name if necessary
  73. if (name == None):
  74. name = 'LerpPosInterval-%d' % LerpPosInterval.lerpPosNum
  75. LerpPosInterval.lerpPosNum += 1
  76. # Initialize superclass
  77. LerpInterval.__init__(self, name, duration, functorFunc, blendType)
  78. class LerpHprInterval(LerpInterval):
  79. # Name counter
  80. lerpHprNum = 1
  81. # Class methods
  82. def __init__(self, node, duration, hpr, startHpr=None,
  83. other=None, blendType='noBlend', name=None):
  84. """ __init__(node, duration, hpr, startHpr, other, blendType, name)
  85. """
  86. def functorFunc(node=node, hpr=hpr, startHpr=startHpr,
  87. other=other):
  88. assert(not node.isEmpty())
  89. if callable(hpr):
  90. # This may be a thunk that returns a point.
  91. hpr = hpr()
  92. if (other != None):
  93. # lerp wrt other
  94. if (startHpr == None):
  95. startHpr = node.getHpr(other)
  96. functor = HprLerpFunctor(node, startHpr, hpr, other)
  97. else:
  98. if (startHpr == None):
  99. startHpr = node.getHpr()
  100. functor = HprLerpFunctor(node, startHpr, hpr)
  101. return functor
  102. # Generate unique name if necessary
  103. if (name == None):
  104. name = 'LerpHprInterval-%d' % LerpHprInterval.lerpHprNum
  105. LerpHprInterval.lerpHprNum += 1
  106. # Initialize superclass
  107. LerpInterval.__init__(self, name, duration, functorFunc, blendType)
  108. class LerpScaleInterval(LerpInterval):
  109. # Interval counter
  110. lerpScaleNum = 1
  111. # Class methods
  112. def __init__(self, node, duration, scale, startScale=None,
  113. other=None, blendType='noBlend', name=None):
  114. """ __init__(node, duration, scale, startScale, other, blendType, name)
  115. """
  116. def functorFunc(node=node, scale=scale,
  117. startScale=startScale, other=other):
  118. assert(not node.isEmpty())
  119. if callable(scale):
  120. # This may be a thunk that returns a point.
  121. scale = scale()
  122. if (other != None):
  123. # lerp wrt other
  124. if (startScale == None):
  125. startScale = node.getScale(other)
  126. functor = ScaleLerpFunctor(node, startScale, scale, other)
  127. else:
  128. if (startScale == None):
  129. startScale = node.getScale()
  130. functor = ScaleLerpFunctor(node, startScale, scale)
  131. return functor
  132. # Generate unique name if necessary
  133. if (name == None):
  134. name = 'LerpScaleInterval-%d' % LerpScaleInterval.lerpScaleNum
  135. LerpScaleInterval.lerpScaleNum += 1
  136. # Initialize superclass
  137. LerpInterval.__init__(self, name, duration, functorFunc, blendType)
  138. class LerpPosHprInterval(LerpInterval):
  139. # Interval counter
  140. lerpPosHprNum = 1
  141. def __init__(self, node, duration, pos, hpr, startPos=None,
  142. startHpr=None, other=None, blendType='noBlend', name=None):
  143. """ __init__(node, duration, pos, hpr, startPos, startHpr,
  144. other, blendType, name)
  145. """
  146. def functorFunc(node=node, pos=pos, hpr=hpr,
  147. startPos=startPos, startHpr=startHpr, other=other):
  148. assert(not node.isEmpty())
  149. if callable(pos):
  150. # This may be a thunk that returns a point.
  151. pos = pos()
  152. if callable(hpr):
  153. # This may be a thunk that returns a point.
  154. hpr = hpr()
  155. if (other != None):
  156. # lerp wrt other
  157. if (startPos == None):
  158. startPos = node.getPos(other)
  159. if (startHpr == None):
  160. startHpr = node.getHpr(other)
  161. functor = PosHprLerpFunctor(
  162. node, startPos, pos,
  163. startHpr, hpr, other)
  164. else:
  165. if (startPos == None):
  166. startPos = node.getPos()
  167. if (startHpr == None):
  168. startHpr = node.getHpr()
  169. functor = PosHprLerpFunctor(
  170. node, startPos, pos,
  171. startHpr, hpr)
  172. return functor
  173. # Generate unique name if necessary
  174. if (name == None):
  175. name = 'LerpPosHpr-%d' % LerpPosHprInterval.lerpPosHprNum
  176. LerpPosHprInterval.lerpPosHprNum += 1
  177. # Initialize superclass
  178. LerpInterval.__init__(self, name, duration, functorFunc, blendType)
  179. class LerpPosHprScaleInterval(LerpInterval):
  180. # Interval counter
  181. lerpPosHprScaleNum = 1
  182. # Class methods
  183. def __init__(self, node, duration, pos, hpr, scale,
  184. startPos=None, startHpr=None, startScale=None,
  185. other=None, blendType='noBlend', name=None):
  186. """ __init__(node, duration, pos, hpr, scale,
  187. startPos, startHpr, startScale,
  188. other, blendType, name)
  189. """
  190. def functorFunc(node=node, pos=pos, hpr=hpr, scale=scale,
  191. startPos=startPos, startHpr=startHpr,
  192. startScale=startScale, other=other):
  193. assert(not node.isEmpty())
  194. if callable(pos):
  195. # This may be a thunk that returns a point.
  196. pos = pos()
  197. if callable(hpr):
  198. # This may be a thunk that returns a point.
  199. hpr = hpr()
  200. if callable(scale):
  201. # This may be a thunk that returns a point.
  202. scale = scale()
  203. if (other != None):
  204. # lerp wrt other
  205. if (startPos == None):
  206. startPos = node.getPos(other)
  207. if (startHpr == None):
  208. startHpr = node.getHpr(other)
  209. if (startScale == None):
  210. startScale = node.getScale(other)
  211. functor = PosHprScaleLerpFunctor(
  212. node, startPos, pos, startHpr, hpr,
  213. startScale, scale, other)
  214. else:
  215. if (startPos == None):
  216. startPos = node.getPos()
  217. if (startHpr == None):
  218. startHpr = node.getHpr()
  219. if (startScale == None):
  220. startScale = node.getScale()
  221. functor = PosHprScaleLerpFunctor(
  222. node, startPos, pos, startHpr, hpr, startScale, scale)
  223. return functor
  224. # Generate unique name if necessary
  225. if (name == None):
  226. name = ('LerpPosHprScale-%d' %
  227. LerpPosHprScaleInterval.lerpPosHprScaleNum)
  228. LerpPosHprScaleInterval.lerpPosHprScaleNum += 1
  229. # Initialize superclass
  230. LerpInterval.__init__(self, name, duration, functorFunc, blendType)
  231. # Class used to execute a function over time. Function can access fromData
  232. # and toData to perform blend. If fromData and toData not specified, will
  233. # execute the given function passing in values ranging from 0 to 1
  234. class LerpFunctionInterval(Interval):
  235. # Interval counter
  236. lerpFunctionIntervalNum = 1
  237. # create LerpFunctionInterval DirectNotify category
  238. notify = directNotify.newCategory('LerpFunctionInterval')
  239. # Class methods
  240. def __init__(self, function, fromData = 0, toData = 1, duration = 0.0,
  241. blendType = 'noBlend', extraArgs = [], name = None):
  242. """__init__(function, duration, fromData, toData, name)
  243. """
  244. # Record instance variables
  245. self.function = function
  246. self.fromData = fromData
  247. self.toData = toData
  248. self.blendType = self.getBlend(blendType)
  249. self.extraArgs = extraArgs
  250. # Generate unique name if necessary
  251. if (name == None):
  252. name = ('LerpFunctionInterval-%d' %
  253. LerpFunctionInterval.lerpFunctionIntervalNum)
  254. LerpFunctionInterval.lerpFunctionIntervalNum += 1
  255. # Initialize superclass
  256. Interval.__init__(self, name, duration)
  257. def updateFunc(self, t, event = IVAL_NONE):
  258. """ updateFunc(t, event)
  259. """
  260. # Evaluate the function
  261. if (t >= self.duration):
  262. # Set to end value
  263. apply(self.function, [self.toData] + self.extraArgs)
  264. elif self.duration == 0.0:
  265. # Zero duration, just use endpoint
  266. apply(self.function, [self.toData] + self.extraArgs)
  267. else:
  268. # In the middle of the lerp, compute appropriate blended value
  269. bt = self.blendType(t/self.duration)
  270. data = (self.fromData * (1 - bt)) + (self.toData * bt)
  271. # Evaluate function
  272. apply(self.function, [data] + self.extraArgs)
  273. # Print debug information
  274. self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t))
  275. def getBlend(self, blendType):
  276. """__getBlend(self, string)
  277. Return the C++ blend class corresponding to blendType string
  278. """
  279. # Note, this is temporary until blend functions get exposed
  280. if (blendType == "easeIn"):
  281. return LerpBlendHelpers.easeIn
  282. elif (blendType == "easeOut"):
  283. return LerpBlendHelpers.easeOut
  284. elif (blendType == "easeInOut"):
  285. return LerpBlendHelpers.easeInOut
  286. elif (blendType == "noBlend"):
  287. return LerpBlendHelpers.noBlend
  288. else:
  289. raise Exception(
  290. 'Error: LerpInterval.__getBlend: Unknown blend type')