NodePath-extensions.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. """
  2. NodePath-extensions module: contains methods to extend functionality
  3. of the NodePath class
  4. """
  5. def id(self):
  6. """Returns the bottom node's this pointer as a unique id"""
  7. return self.getBottomArc()
  8. def getName(self):
  9. """Returns the name of the bottom node if it exists, or <noname>"""
  10. from PandaModules import *
  11. # Initialize to a default value
  12. name = '<noname>'
  13. # Get the bottom node
  14. node = self.node()
  15. # Is it a named node?, If so, see if it has a name
  16. if issubclass(node.__class__, NamedNode):
  17. namedNodeName = node.getName()
  18. # Is it not zero length?
  19. if len(namedNodeName) != 0:
  20. name = namedNodeName
  21. return name
  22. # For iterating over children
  23. def getChildrenAsList(self):
  24. """Converts a node path's child NodePathCollection into a list"""
  25. childrenList = []
  26. for childNum in range(self.getNumChildren()):
  27. childrenList.append(self.getChild(childNum))
  28. return childrenList
  29. def printChildren(self):
  30. """Prints out the children of the bottom node of a node path"""
  31. for child in self.getChildrenAsList():
  32. print child.getName()
  33. def toggleViz(self):
  34. """Toggles visibility of a nodePath"""
  35. if self.isHidden():
  36. self.show()
  37. else:
  38. self.hide()
  39. def showSiblings(self):
  40. """Show all the siblings of a node path"""
  41. for sib in self.getParent().getChildrenAsList():
  42. if sib.node() != self.node():
  43. sib.show()
  44. def hideSiblings(self):
  45. """Hide all the siblings of a node path"""
  46. for sib in self.getParent().getChildrenAsList():
  47. if sib.node() != self.node():
  48. sib.hide()
  49. def showAllDescendants(self):
  50. """Show the node path and all its children"""
  51. self.show()
  52. for child in self.getChildrenAsList():
  53. child.showAllDescendants()
  54. def isolate(self):
  55. """Show the node path and hide its siblings"""
  56. self.showAllDescendants()
  57. self.hideSiblings()
  58. def remove(self):
  59. """Remove a node path from the scene graph"""
  60. from PandaObject import *
  61. # Send message in case anyone needs to do something
  62. # before node is deleted
  63. messenger.send('preRemoveNodePath', [self])
  64. # Remove nodePath
  65. self.reparentTo(hidden)
  66. self.removeNode()
  67. def reversels(self):
  68. """Walk up a tree and print out the path to the root"""
  69. ancestry = self.getAncestry()
  70. indentString = ""
  71. for nodePath in ancestry:
  72. type = nodePath.node().getType().getName()
  73. name = nodePath.getName()
  74. print indentString + type + " " + name
  75. indentString = indentString + " "
  76. def getAncestry(self):
  77. """Get a list of a node path's ancestors"""
  78. from PandaObject import *
  79. node = self.node()
  80. if (self.hasParent()):
  81. ancestry = self.getParent().getAncestry()
  82. ancestry.append(self)
  83. return ancestry
  84. else:
  85. return [self]
  86. # private methods
  87. def __getBlend(self, blendType):
  88. """__getBlend(self, string)
  89. Return the C++ blend class corresponding to blendType string
  90. """
  91. import LerpBlendHelpers
  92. if (blendType == "easeIn"):
  93. return LerpBlendHelpers.LerpBlendHelpers.easeIn
  94. elif (blendType == "easeOut"):
  95. return LerpBlendHelpers.LerpBlendHelpers.easeOut
  96. elif (blendType == "easeInOut"):
  97. return LerpBlendHelpers.LerpBlendHelpers.easeInOut
  98. elif (blendType == "noBlend"):
  99. return LerpBlendHelpers.LerpBlendHelpers.noBlend
  100. else:
  101. raise Exception("Error: NodePath.__getBlend: Unknown blend type")
  102. def __lerp(self, functor, time, blendType, taskName=None):
  103. """__lerp(self, functor, float, string, string)
  104. Basic lerp functionality used by other lerps.
  105. Fire off a lerp. Make it a task if taskName given."""
  106. import Lerp
  107. # make the lerp
  108. lerp = Lerp.Lerp(functor, time, (self.__getBlend(blendType)))
  109. from TaskManagerGlobal import *
  110. # make the task function
  111. def lerpTaskFunc(task):
  112. import Task
  113. import ClockObject
  114. dt = ClockObject.ClockObject.getGlobalClock().getDt()
  115. task.lerp.setStepSize(dt)
  116. task.lerp.step()
  117. if (task.lerp.isDone()):
  118. return(Task.done)
  119. else:
  120. return(Task.cont)
  121. # make the lerp task
  122. lerpTask = Task.Task(lerpTaskFunc)
  123. lerpTask.lerp = lerp
  124. if (taskName == None):
  125. # don't spawn a task, return one instead
  126. return lerpTask
  127. else:
  128. # spawn the lerp task
  129. taskMgr.spawnTaskNamed(lerpTask, taskName)
  130. return lerpTask
  131. def __autoLerp(self, functor, time, blendType, taskName):
  132. """_autoLerp(self, functor, float, string, string)
  133. This lerp uses C++ to handle the stepping. Bonus is
  134. its more efficient, trade-off is there is less control"""
  135. import AutonomousLerp
  136. from ShowBaseGlobal import *
  137. # make a lerp that lives in C++ land
  138. lerp = AutonomousLerp.AutonomousLerp(functor, time,
  139. self.__getBlend(blendType),
  140. base.eventHandler)
  141. lerp.start()
  142. return lerp
  143. # user callable lerp methods
  144. def lerpColor(self, *posArgs, **keyArgs):
  145. """lerpColor(self, *positionArgs, **keywordArgs)
  146. determine which lerpColor* to call based on arguments
  147. """
  148. if (len(posArgs) == 2):
  149. return apply(self.lerpColorVBase4, posArgs, keyArgs)
  150. elif (len(posArgs) == 3):
  151. return apply(self.lerpColorVBase4VBase4, posArgs, keyArgs)
  152. elif (len(posArgs) == 5):
  153. return apply(self.lerpColorRGBA, posArgs, keyArgs)
  154. elif (len(posArgs) == 9):
  155. return apply(self.lerpColorRGBARGBA, posArgs, keyArgs)
  156. else:
  157. # bad args
  158. raise Exception("Error: NodePath.lerpColor: bad number of args")
  159. def lerpColorRGBA(self, r, g, b, a, time, blendType="noBlend",
  160. auto=None, task=None):
  161. """lerpColorRGBA(self, float, float, float, float, float,
  162. string="noBlend", string=none, string=none)
  163. """
  164. import ColorLerpFunctor
  165. # just end rgba values, use current color rgba values for start
  166. startColor = self.getColor()
  167. functor = ColorLerpFunctor.ColorLerpFunctor(self,
  168. startColor[0], startColor[1],
  169. startColor[2], startColor[3],
  170. r, g, b, a)
  171. #determine whether to use auto, spawned, or blocking lerp
  172. if (auto != None):
  173. return self.__autoLerp(functor, time, blendType, auto)
  174. elif (task != None):
  175. return self.__lerp(functor, time, blendType, task)
  176. else:
  177. return self.__lerp(functor, time, blendType)
  178. def lerpColorRGBARGBA(self, sr, sg, sb, sa, er, eg, eb, ea, time,
  179. blendType="noBlend", auto=None, task=None):
  180. """lerpColorRGBARGBA(self, float, float, float, float, float,
  181. float, float, float, float, string="noBlend", string=none, string=none)
  182. """
  183. import ColorLerpFunctor
  184. # start and end rgba values
  185. functor = ColorLerpFunctor.ColorLerpFunctor(self, sr, sg, sb, sa,
  186. er, eg, eb, ea)
  187. #determine whether to use auto, spawned, or blocking lerp
  188. if (auto != None):
  189. return self.__autoLerp(functor, time, blendType, auto)
  190. elif (task != None):
  191. return self.__lerp(functor, time, blendType, task)
  192. else:
  193. return self.__lerp(functor, time, blendType)
  194. def lerpColorVBase4(self, endColor, time, blendType="noBlend",
  195. auto=None, task=None):
  196. """lerpColorVBase4(self, VBase4, float, string="noBlend", string=none,
  197. string=none)
  198. """
  199. import ColorLerpFunctor
  200. # just end vec4, use current color for start
  201. startColor = self.getColor()
  202. functor = ColorLerpFunctor.ColorLerpFunctor(self, startColor, endColor)
  203. #determine whether to use auto, spawned, or blocking lerp
  204. if (auto != None):
  205. return self.__autoLerp(functor, time, blendType, auto)
  206. elif (task != None):
  207. return self.__lerp(functor, time, blendType, task)
  208. else:
  209. return self.__lerp(functor, time, blendType)
  210. def lerpColorVBase4VBase4(self, startColor, endColor, time,
  211. blendType="noBlend", auto=None, task=None):
  212. """lerpColorVBase4VBase4(self, VBase4, VBase4, float, string="noBlend",
  213. string=none, string=none)
  214. """
  215. import ColorLerpFunctor
  216. # start color and end vec
  217. functor = ColorLerpFunctor.ColorLerpFunctor(self, startColor, endColor)
  218. #determine whether to use auto, spawned, or blocking lerp
  219. if (auto != None):
  220. return self.__autoLerp(functor, time, blendType, auto)
  221. elif (task != None):
  222. return self.__lerp(functor, time, blendType, task)
  223. else:
  224. return self.__lerp(functor, time, blendType)
  225. def lerpHpr(self, *posArgs, **keyArgs):
  226. """lerpHpr(self, *positionArgs, **keywordArgs)
  227. Determine whether to call lerpHprHPR or lerpHprVBase3
  228. based on first argument
  229. """
  230. # check to see if lerping with
  231. # three floats or a VBase3
  232. if (len(posArgs) == 4):
  233. return apply(self.lerpHprHPR, posArgs, keyArgs)
  234. elif(len(posArgs) == 2):
  235. return apply(self.lerpHprVBase3, posArgs, keyArgs)
  236. else:
  237. # bad args
  238. raise Exception("Error: NodePath.lerpHpr: bad number of args")
  239. def lerpHprHPR(self, h, p, r, time, blendType="noBlend", auto=None,
  240. task=None, other=None):
  241. """lerpHprHPR(self, float, float, float, float, string="noBlend",
  242. string=none, string=none, NodePath=none)
  243. Perform a hpr lerp with three floats as the end point
  244. """
  245. import HprLerpFunctor
  246. # it's individual hpr components
  247. if (other != None):
  248. # lerp wrt other
  249. startHpr = self.getHpr(other)
  250. functor = HprLerpFunctor.HprLerpFunctor(self,
  251. startHpr[0], startHpr[1], startHpr[2],
  252. h, p, r, other)
  253. else:
  254. startHpr = self.getHpr()
  255. functor = HprLerpFunctor.HprLerpFunctor(self,
  256. startHpr[0], startHpr[1], startHpr[2],
  257. h, p, r)
  258. #determine whether to use auto, spawned, or blocking lerp
  259. if (auto != None):
  260. return self.__autoLerp(functor, time, blendType, auto)
  261. elif (task != None):
  262. return self.__lerp(functor, time, blendType, task)
  263. else:
  264. return self.__lerp(functor, time, blendType)
  265. def lerpHprVBase3(self, hpr, time, blendType="noBlend", auto=None,
  266. task=None, other=None):
  267. """lerpHprVBase3(self, VBase3, float, string="noBlend", string=none,
  268. string=none, NodePath=None)
  269. Perform a hpr lerp with a VBase3 as the end point
  270. """
  271. import HprLerpFunctor
  272. # it's a vbase3 hpr
  273. if (other != None):
  274. # lerp wrt other
  275. functor = HprLerpFunctor.HprLerpFunctor(self, (self.getHpr(other)),
  276. hpr, other)
  277. else:
  278. functor = HprLerpFunctor.HprLerpFunctor(self, (self.getHpr()),
  279. hpr)
  280. #determine whether to use auto, spawned, or blocking lerp
  281. if (auto != None):
  282. return self.__autoLerp(functor, time, blendType, auto)
  283. elif (task != None):
  284. return self.__lerp(functor, time, blendType, task)
  285. else:
  286. return self.__lerp(functor, time, blendType)
  287. def lerpPos(self, *posArgs, **keyArgs):
  288. """lerpPos(self, *positionArgs, **keywordArgs)
  289. Determine whether to call lerpPosXYZ or lerpPosPoint3
  290. based on the first argument
  291. """
  292. # check to see if lerping with three
  293. # floats or a Point3
  294. if (len(posArgs) == 4):
  295. return apply(self.lerpPosXYZ, posArgs, keyArgs)
  296. elif(len(posArgs) == 2):
  297. return apply(self.lerpPosPoint3, posArgs, keyArgs)
  298. else:
  299. # bad number off args
  300. raise Exception("Error: NodePath.lerpPos: bad number of args")
  301. def lerpPosXYZ(self, x, y, z, time, blendType="noBlend", auto=None,
  302. task=None, other=None):
  303. """lerpPosXYZ(self, float, float, float, float, string="noBlend",
  304. string=None, NodePath=None)
  305. Perform a pos lerp with three floats as the end point
  306. """
  307. import PosLerpFunctor
  308. if (other != None):
  309. # lerp wrt other
  310. startPos = self.getPos(other)
  311. functor = PosLerpFunctor.PosLerpFunctor(self,
  312. startPos[0], startPos[1], startPos[2],
  313. x, y, z, other)
  314. else:
  315. startPos = self.getPos()
  316. functor = PosLerpFunctor.PosLerpFunctor(self, startPos[0],
  317. startPos[1], startPos[2], x, y, z)
  318. #determine whether to use auto, spawned, or blocking lerp
  319. if (auto != None):
  320. return self.__autoLerp(functor, time, blendType, auto)
  321. elif (task != None):
  322. return self.__lerp(functor, time, blendType, task)
  323. else:
  324. return self.__lerp(functor, time, blendType)
  325. def lerpPosPoint3(self, pos, time, blendType="noBlend", auto=None,
  326. task=None, other=None):
  327. """lerpPosPoint3(self, Point3, float, string="noBlend", string=None,
  328. string=None, NodePath=None)
  329. Perform a pos lerp with a Point3 as the end point
  330. """
  331. import PosLerpFunctor
  332. if (other != None):
  333. #lerp wrt other
  334. functor = PosLerpFunctor.PosLerpFunctor(self, (self.getPos(other)),
  335. pos, other)
  336. else:
  337. functor = PosLerpFunctor.PosLerpFunctor(self, (self.getPos()), pos)
  338. #determine whether to use auto, spawned, or blocking lerp
  339. if (auto != None):
  340. return self.__autoLerp(functor, time, blendType, auto)
  341. elif (task != None):
  342. return self.__lerp(functor, time, blendType, task)
  343. else:
  344. return self.__lerp(functor, time, blendType)
  345. def lerpPosHpr(self, *posArgs, **keyArgs):
  346. """lerpPosHpr(self, *positionArgs, **keywordArgs)
  347. Determine whether to call lerpPosHprXYZHPR or lerpHprPoint3VBase3
  348. based on first argument
  349. """
  350. # check to see if lerping with
  351. # six floats or a Point3 and a VBase3
  352. if (len(posArgs) == 7):
  353. return apply(self.lerpPosHprXYZHPR, posArgs, keyArgs)
  354. elif(len(posArgs) == 3):
  355. return apply(self.lerpPosHprPoint3VBase3, posArgs, keyArgs)
  356. else:
  357. # bad number off args
  358. raise Exception("Error: NodePath.lerpPosHpr: bad number of args")
  359. def lerpPosHprPoint3VBase3(self, pos, hpr, time, blendType="noBlend",
  360. auto=None, task=None, other=None):
  361. """lerpPosHprPoint3VBase3(self, Point3, VBase3, string="noBlend",
  362. string=none, string=none, NodePath=None)
  363. """
  364. import PosHprLerpFunctor
  365. if (other != None):
  366. # lerp wrt other
  367. startPos = self.getPos(other)
  368. startHpr = self.getHpr(other)
  369. functor = PosHprLerpFunctor.PosHprLerpFunctor(self,
  370. startPos, pos,
  371. startHpr, hpr, other)
  372. else:
  373. startPos = self.getPos()
  374. startHpr = self.getHpr()
  375. functor = PosHprLerpFunctor.PosHprLerpFunctor(self,
  376. startPos, pos,
  377. startHpr, hpr)
  378. #determine whether to use auto, spawned, or blocking lerp
  379. if (auto != None):
  380. return self.__autoLerp(functor, time, blendType, auto)
  381. elif (task != None):
  382. return self.__lerp(functor, time, blendType, task)
  383. else:
  384. return self.__lerp(functor, time, blendType)
  385. def lerpPosHprXYZHPR(self, x, y, z, h, p, r, time, blendType="noBlend",
  386. auto=None, task=None, other=None):
  387. """lerpPosHpr(self, float, string="noBlend", string=none,
  388. string=none, NodePath=None)
  389. """
  390. import PosHprLerpFunctor
  391. if (other != None):
  392. # lerp wrt other
  393. startPos = self.getPos(other)
  394. startHpr = self.getHpr(other)
  395. functor = PosHprLerpFunctor.PosHprLerpFunctor(self,
  396. startPos[0], startPos[1],
  397. startPos[2], x, y, z,
  398. startHpr[0], startHpr[1],
  399. startHpr[2], h, p, r,
  400. other)
  401. else:
  402. startPos = self.getPos()
  403. startHpr = self.getHpr()
  404. functor = PosHprLerpFunctor.PosHprLerpFunctor(self,
  405. startPos[0], startPos[1],
  406. startPos[2], x, y, z,
  407. startHpr[0], startHpr[1],
  408. startHpr[2], h, p, r)
  409. #determine whether to use auto, spawned, or blocking lerp
  410. if (auto != None):
  411. return self.__autoLerp(functor, time, blendType, auto)
  412. elif (task != None):
  413. return self.__lerp(functor, time, blendType, task)
  414. else:
  415. return self.__lerp(functor, time, blendType)
  416. def lerpPosHprScale(self, pos, hpr, scale, time, blendType="noBlend",
  417. auto=None, task=None, other=None):
  418. """lerpPosHpr(self, Point3, VBase3, float, float, string="noBlend",
  419. string=none, string=none, NodePath=None)
  420. Only one case, no need for extra args. Call the appropriate lerp
  421. (auto, spawned, or blocking) based on how(if) a task name is given
  422. """
  423. import PosHprScaleLerpFunctor
  424. if (other != None):
  425. # lerp wrt other
  426. startPos = self.getPos(other)
  427. startHpr = self.getHpr(other)
  428. startScale = self.getScale(other)
  429. functor = PosHprScaleLerpFunctor.PosHprScaleLerpFunctor(self,
  430. startPos, pos,
  431. startHpr, hpr,
  432. startScale, scale, other)
  433. else:
  434. startPos = self.getPos()
  435. startHpr = self.getHpr()
  436. startScale = self.getScale()
  437. functor = PosHprScaleLerpFunctor.PosHprScaleLerpFunctor(self,
  438. startPos, pos,
  439. startHpr, hpr,
  440. startScale, scale)
  441. #determine whether to use auto, spawned, or blocking lerp
  442. if (auto != None):
  443. return self.__autoLerp(functor, time, blendType, auto)
  444. elif (task != None):
  445. return self.__lerp(functor, time, blendType, task)
  446. else:
  447. return self.__lerp(functor, time, blendType)
  448. def lerpScale(self, *posArgs, **keyArgs):
  449. """lerpSclae(self, *positionArgs, **keywordArgs)
  450. Determine whether to call lerpScaleXYZ or lerpScaleaseV3
  451. based on the first argument
  452. """
  453. # check to see if lerping with three
  454. # floats or a Point3
  455. if (len(posArgs) == 4):
  456. return apply(self.lerpScaleXYZ, posArgs, keyArgs)
  457. elif(len(posArgs) == 2):
  458. return apply(self.lerpScaleVBase3, posArgs, keyArgs)
  459. else:
  460. # bad number off args
  461. raise Exception("Error: NodePath.lerpScale: bad number of args")
  462. def lerpScaleVBase3(self, scale, time, blendType="noBlend", auto=None,
  463. task=None, other=None):
  464. """lerpPos(self, VBase3, float, string="noBlend", string=none,
  465. string=none, NodePath=None)
  466. """
  467. import ScaleLerpFunctor
  468. if (other != None):
  469. # lerp wrt other
  470. functor = ScaleLerpFunctor.ScaleLerpFunctor(self,
  471. (self.getScale(other)),
  472. scale, other)
  473. else:
  474. functor = ScaleLerpFunctor.ScaleLerpFunctor(self,
  475. (self.getScale()), scale)
  476. #determine whether to use auto, spawned, or blocking lerp
  477. if (auto != None):
  478. return self.__autoLerp(functor, time, blendType, auto)
  479. elif (task != None):
  480. return self.__lerp(functor, time, blendType, task)
  481. else:
  482. return self.__lerp(functor, time, blendType)
  483. def lerpScaleXYZ(self, sx, sy, sz, time, blendType="noBlend",
  484. auto=None, task=None, other=None):
  485. """lerpPos(self, float, float, float, float, string="noBlend",
  486. string=none, string=none, NodePath=None)
  487. """
  488. import ScaleLerpFunctor
  489. if (other != None):
  490. # lerp wrt other
  491. startScale = self.getScale(other)
  492. functor = ScaleLerpFunctor.ScaleLerpFunctor(self,
  493. startScale[0], startScale[1],
  494. startScale[2], sx, sy, sz, other)
  495. else:
  496. startScale = self.getScale()
  497. functor = ScaleLerpFunctor.ScaleLerpFunctor(self,
  498. startScale[0], startScale[1],
  499. startScale[2], sx, sy, sz)
  500. #determine whether to use auto, spawned, or blocking lerp
  501. if (auto != None):
  502. return self.__autoLerp(functor, time, blendType, auto)
  503. elif (task != None):
  504. return self.__lerp(functor, time, blendType, task)
  505. else:
  506. return self.__lerp(functor, time, blendType)