FunctionInterval.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. """FunctionInterval module: contains the FunctionInterval class"""
  2. from PandaModules import *
  3. from MessengerGlobal import *
  4. from DirectNotifyGlobal import *
  5. import Interval
  6. import types
  7. #############################################################
  8. ### ###
  9. ### See examples of function intervals in IntervalTest.py ###
  10. ### ###
  11. #############################################################
  12. class FunctionInterval(Interval.Interval):
  13. # Name counter
  14. functionIntervalNum = 1
  15. # create FunctionInterval DirectNotify category
  16. notify = directNotify.newCategory('FunctionInterval')
  17. # Class methods
  18. def __init__(self, function, name = None, openEnded = 1, extraArgs = []):
  19. """__init__(function, name = None)
  20. """
  21. # Record instance variables
  22. self.function = function
  23. # Create a unique name for the interval if necessary
  24. if (name == None):
  25. name = 'FunctionInterval-%s-%d' % (function.__name__, FunctionInterval.functionIntervalNum)
  26. FunctionInterval.functionIntervalNum += 1
  27. assert(isinstance(name, types.StringType))
  28. # Record any arguments
  29. self.extraArgs = extraArgs
  30. # Initialize superclass
  31. # Set openEnded true if privInitialize after end time cause interval
  32. # function to be called. If false, privInitialize calls have no effect
  33. # Event, Accept, Ignore intervals default to openEnded = 0
  34. # Parent, Pos, Hpr, etc intervals default to openEnded = 1
  35. Interval.Interval.__init__(self, name, duration = 0.0, openEnded = openEnded)
  36. def privInstant(self):
  37. # Evaluate the function
  38. apply(self.function, self.extraArgs)
  39. # Print debug information
  40. self.notify.debug(
  41. 'updateFunc() - %s: executing Function' % self.name)
  42. ### FunctionInterval subclass for throwing events ###
  43. class EventInterval(FunctionInterval):
  44. # Initialization
  45. def __init__(self, event, sentArgs=[]):
  46. """__init__(event, sentArgs)
  47. """
  48. def sendFunc(event = event, sentArgs = sentArgs):
  49. messenger.send(event, sentArgs)
  50. # Create function interval
  51. FunctionInterval.__init__(self, sendFunc, name = event,
  52. openEnded = 0)
  53. ### FunctionInterval subclass for accepting hooks ###
  54. class AcceptInterval(FunctionInterval):
  55. # Initialization
  56. def __init__(self, dirObj, event, function, name = None):
  57. """__init__(dirObj, event, function, name)
  58. """
  59. def acceptFunc(dirObj = dirObj, event = event, function = function):
  60. dirObj.accept(event, function)
  61. # Determine name
  62. if (name == None):
  63. name = 'Accept-' + event
  64. # Create function interval
  65. FunctionInterval.__init__(self, acceptFunc, name = name,
  66. openEnded = 0)
  67. ### FunctionInterval subclass for ignoring events ###
  68. class IgnoreInterval(FunctionInterval):
  69. # Initialization
  70. def __init__(self, dirObj, event, name = None):
  71. """__init__(dirObj, event, name)
  72. """
  73. def ignoreFunc(dirObj = dirObj, event = event):
  74. dirObj.ignore(event)
  75. # Determine name
  76. if (name == None):
  77. name = 'Ignore-' + event
  78. # Create function interval
  79. FunctionInterval.__init__(self, ignoreFunc, name = name,
  80. openEnded = 0)
  81. ### Function Interval subclass for adjusting scene graph hierarchy ###
  82. class ParentInterval(FunctionInterval):
  83. # ParentInterval counter
  84. parentIntervalNum = 1
  85. # Initialization
  86. def __init__(self, nodePath, parent, name = None):
  87. """__init__(nodePath, parent, name)
  88. """
  89. def reparentFunc(nodePath = nodePath, parent = parent):
  90. nodePath.reparentTo(parent)
  91. # Determine name
  92. if (name == None):
  93. name = 'ParentInterval-%d' % ParentInterval.parentIntervalNum
  94. ParentInterval.parentIntervalNum += 1
  95. # Create function interval
  96. FunctionInterval.__init__(self, reparentFunc, name = name)
  97. ### Function Interval subclass for adjusting scene graph hierarchy ###
  98. class WrtParentInterval(FunctionInterval):
  99. # WrtParentInterval counter
  100. wrtParentIntervalNum = 1
  101. # Initialization
  102. def __init__(self, nodePath, parent, name = None):
  103. """__init__(nodePath, parent, name)
  104. """
  105. def wrtReparentFunc(nodePath = nodePath, parent = parent):
  106. nodePath.wrtReparentTo(parent)
  107. # Determine name
  108. if (name == None):
  109. name = ('WrtParentInterval-%d' %
  110. WrtParentInterval.wrtParentIntervalNum)
  111. WrtParentInterval.wrtParentIntervalNum += 1
  112. # Create function interval
  113. FunctionInterval.__init__(self, wrtReparentFunc, name = name)
  114. ### Function Interval subclasses for instantaneous pose changes ###
  115. class PosInterval(FunctionInterval):
  116. # PosInterval counter
  117. posIntervalNum = 1
  118. # Initialization
  119. def __init__(self, nodePath, pos, duration = 0.0,
  120. name = None, other = None):
  121. """__init__(nodePath, pos, duration, name)
  122. """
  123. # Create function
  124. def posFunc(np = nodePath, pos = pos, other = other):
  125. if other:
  126. np.setPos(other, pos)
  127. else:
  128. np.setPos(pos)
  129. # Determine name
  130. if (name == None):
  131. name = 'PosInterval-%d' % PosInterval.posIntervalNum
  132. PosInterval.posIntervalNum += 1
  133. # Create function interval
  134. FunctionInterval.__init__(self, posFunc, name = name)
  135. class HprInterval(FunctionInterval):
  136. # HprInterval counter
  137. hprIntervalNum = 1
  138. # Initialization
  139. def __init__(self, nodePath, hpr, duration = 0.0,
  140. name = None, other = None):
  141. """__init__(nodePath, hpr, duration, name)
  142. """
  143. # Create function
  144. def hprFunc(np = nodePath, hpr = hpr, other = other):
  145. if other:
  146. np.setHpr(other, hpr)
  147. else:
  148. np.setHpr(hpr)
  149. # Determine name
  150. if (name == None):
  151. name = 'HprInterval-%d' % HprInterval.hprIntervalNum
  152. HprInterval.hprIntervalNum += 1
  153. # Create function interval
  154. FunctionInterval.__init__(self, hprFunc, name = name)
  155. class ScaleInterval(FunctionInterval):
  156. # ScaleInterval counter
  157. scaleIntervalNum = 1
  158. # Initialization
  159. def __init__(self, nodePath, scale, duration = 0.0,
  160. name = None, other = None):
  161. """__init__(nodePath, scale, duration, name)
  162. """
  163. # Create function
  164. def scaleFunc(np = nodePath, scale = scale, other = other):
  165. if other:
  166. np.setScale(other, scale)
  167. else:
  168. np.setScale(scale)
  169. # Determine name
  170. if (name == None):
  171. name = 'ScaleInterval-%d' % ScaleInterval.scaleIntervalNum
  172. ScaleInterval.scaleIntervalNum += 1
  173. # Create function interval
  174. FunctionInterval.__init__(self, scaleFunc, name = name)
  175. class PosHprInterval(FunctionInterval):
  176. # PosHprInterval counter
  177. posHprIntervalNum = 1
  178. # Initialization
  179. def __init__(self, nodePath, pos, hpr, duration = 0.0,
  180. name = None, other = None):
  181. """__init__(nodePath, pos, hpr, duration, name)
  182. """
  183. # Create function
  184. def posHprFunc(np = nodePath, pos = pos, hpr = hpr, other = other):
  185. if other:
  186. np.setPosHpr(other, pos, hpr)
  187. else:
  188. np.setPosHpr(pos, hpr)
  189. # Determine name
  190. if (name == None):
  191. name = 'PosHprInterval-%d' % PosHprInterval.posHprIntervalNum
  192. PosHprInterval.posHprIntervalNum += 1
  193. # Create function interval
  194. FunctionInterval.__init__(self, posHprFunc, name = name)
  195. class HprScaleInterval(FunctionInterval):
  196. # HprScaleInterval counter
  197. hprScaleIntervalNum = 1
  198. # Initialization
  199. def __init__(self, nodePath, hpr, scale, duration = 0.0,
  200. name = None, other = None):
  201. """__init__(nodePath, hpr, scale, duration, other, name)
  202. """
  203. # Create function
  204. def hprScaleFunc(np=nodePath, hpr=hpr, scale=scale,
  205. other = other):
  206. if other:
  207. np.setHprScale(other, hpr, scale)
  208. else:
  209. np.setHprScale(hpr, scale)
  210. # Determine name
  211. if (name == None):
  212. name = ('HprScale-%d' %
  213. HprScaleInterval.hprScaleIntervalNum)
  214. HprScaleInterval.hprScaleIntervalNum += 1
  215. # Create function interval
  216. FunctionInterval.__init__(self, hprScaleFunc, name = name)
  217. class PosHprScaleInterval(FunctionInterval):
  218. # PosHprScaleInterval counter
  219. posHprScaleIntervalNum = 1
  220. # Initialization
  221. def __init__(self, nodePath, pos, hpr, scale, duration = 0.0,
  222. name = None, other = None):
  223. """__init__(nodePath, pos, hpr, scale, duration, other, name)
  224. """
  225. # Create function
  226. def posHprScaleFunc(np=nodePath, pos=pos, hpr=hpr, scale=scale,
  227. other = other):
  228. if other:
  229. np.setPosHprScale(other, pos, hpr, scale)
  230. else:
  231. np.setPosHprScale(pos, hpr, scale)
  232. # Determine name
  233. if (name == None):
  234. name = ('PosHprScale-%d' %
  235. PosHprScaleInterval.posHprScaleIntervalNum)
  236. PosHprScaleInterval.posHprScaleIntervalNum += 1
  237. # Create function interval
  238. FunctionInterval.__init__(self, posHprScaleFunc, name = name)
  239. class Func(FunctionInterval):
  240. def __init__(self, *args, **kw):
  241. function = args[0]
  242. assert(callable(function))
  243. extraArgs = args[1:]
  244. kw['extraArgs'] = extraArgs
  245. FunctionInterval.__init__(self, function, **kw)
  246. """
  247. SAMPLE CODE
  248. from IntervalGlobal import *
  249. i1 = Func(base.transitions.fadeOut)
  250. i2 = Func(base.transitions.fadeIn)
  251. def caughtIt():
  252. print 'Caught here-is-an-event'
  253. class DummyAcceptor(DirectObject):
  254. pass
  255. da = DummyAcceptor()
  256. i3 = Func(da.accept, 'here-is-an-event', caughtIt)
  257. i4 = Func(messenger.send, 'here-is-an-event')
  258. i5 = Func(da.ignore, 'here-is-an-event')
  259. # Using a function
  260. def printDone():
  261. print 'done'
  262. i6 = Func(printDone)
  263. # Create track
  264. t1 = Sequence([
  265. # Fade out
  266. (0.0, i1),
  267. # Fade in
  268. (2.0, i2),
  269. # Accept event
  270. (4.0, i3),
  271. # Throw it,
  272. (5.0, i4),
  273. # Ignore event
  274. (6.0, i5),
  275. # Throw event again and see if ignore worked
  276. (7.0, i4),
  277. # Print done
  278. (8.0, i6)], name = 'demo')
  279. # Play track
  280. t1.play()
  281. ### Specifying interval start times during track construction ###
  282. # Interval start time can be specified relative to three different points:
  283. # PREVIOUS_END
  284. # PREVIOUS_START
  285. # TRACK_START
  286. startTime = 0.0
  287. def printStart():
  288. global startTime
  289. startTime = globalClock.getFrameTime()
  290. print 'Start'
  291. def printPreviousStart():
  292. global startTime
  293. currTime = globalClock.getFrameTime()
  294. print 'PREVIOUS_END %0.2f' % (currTime - startTime)
  295. def printPreviousEnd():
  296. global startTime
  297. currTime = globalClock.getFrameTime()
  298. print 'PREVIOUS_END %0.2f' % (currTime - startTime)
  299. def printTrackStart():
  300. global startTime
  301. currTime = globalClock.getFrameTime()
  302. print 'TRACK_START %0.2f' % (currTime - startTime)
  303. i1 = Func(printStart)
  304. # Just to take time
  305. i2 = LerpPosInterval(camera, 2.0, Point3(0,10,5))
  306. # This will be relative to end of camera move
  307. i3 = FunctionInterval(printPreviousEnd)
  308. # Just to take time
  309. i4 = LerpPosInterval(camera, 2.0, Point3(0,0,5))
  310. # This will be relative to the start of the camera move
  311. i5 = FunctionInterval(printPreviousStart)
  312. # This will be relative to track start
  313. i6 = FunctionInterval(printTrackStart)
  314. # Create the track, if you don't specify offset type in tuple it defaults to
  315. # relative to TRACK_START (first entry below)
  316. t2 = Track([(0.0, i1), # i1 start at t = 0, duration = 0.0
  317. (1.0, i2, TRACK_START), # i2 start at t = 1, duration = 2.0
  318. (2.0, i3, PREVIOUS_END), # i3 start at t = 5, duration = 0.0
  319. (1.0, i4, PREVIOUS_END), # i4 start at t = 6, duration = 2.0
  320. (3.0, i5, PREVIOUS_START), # i5 start at t = 9, duration = 0.0
  321. (10.0, i6, TRACK_START)], # i6 start at t = 10, duration = 0.0
  322. name = 'startTimeDemo')
  323. t2.play()
  324. smiley = loader.loadModel('models/misc/smiley')
  325. import Actor
  326. donald = Actor.Actor()
  327. donald.loadModel("phase_6/models/char/donald-wheel-1000")
  328. donald.loadAnims({"steer":"phase_6/models/char/donald-wheel-wheel"})
  329. donald.reparentTo(render)
  330. seq = Sequence(Func(donald.setPos, 0,0,0),
  331. donald.actorInterval('steer', duration=1.0),
  332. donald.posInterval(1, Point3(0,0,1)),
  333. Parallel(donald.actorInterval('steer', duration=1.0),
  334. donald.posInterval(1, Point3(0,0,0)),
  335. ),
  336. Wait(1.0),
  337. Func(base.toggleWireframe),
  338. Wait(1.0),
  339. Parallel(donald.actorInterval('steer', duration=1.0),
  340. donald.posInterval(1, Point3(0,0,-1)),
  341. Sequence(donald.hprInterval(1, Vec3(180,0,0)),
  342. donald.hprInterval(1, Vec3(0,0,0)),
  343. ),
  344. ),
  345. Func(base.toggleWireframe),
  346. Func(messenger.send, 'hello'),
  347. )
  348. """