test_nodepath.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. import pytest, sys
  2. def test_nodepath_empty():
  3. """Tests NodePath behavior for empty NodePaths."""
  4. from panda3d.core import NodePath, ParamNodePath
  5. import pickle
  6. empty = NodePath()
  7. assert empty.is_empty()
  8. assert not empty
  9. # Try pickling, which uses __reduce__
  10. dumped = pickle.dumps(empty)
  11. empty2 = pickle.loads(dumped)
  12. assert empty2.is_empty()
  13. assert not empty2
  14. assert empty == empty2
  15. # Test write_datagram/fillin, which are invoked when the NodePath is being
  16. # serialized indirectly, such as via ParamNodePath
  17. dumped = pickle.dumps(ParamNodePath(empty))
  18. empty2 = pickle.loads(dumped).get_value()
  19. assert empty2.is_empty()
  20. assert not empty2
  21. assert empty == empty2
  22. def test_nodepath_single():
  23. """Tests NodePath behavior for single-node NodePaths."""
  24. from panda3d.core import NodePath
  25. np = NodePath('np')
  26. assert not np.is_empty()
  27. assert np
  28. assert np.get_pos() == (0, 0, 0)
  29. assert np.get_hpr() == (0, 0, 0)
  30. assert np.get_scale() == (1, 1, 1)
  31. def test_nodepath_parent():
  32. """Tests NodePath.reparentTo()."""
  33. from panda3d.core import NodePath
  34. np1 = NodePath('np')
  35. np2 = NodePath('np')
  36. assert np1.parent is None
  37. assert np2.parent is None
  38. np1.reparentTo(np2)
  39. assert np1.parent == np2
  40. assert np2.parent is None
  41. def test_nodepath_transform_changes():
  42. """Tests that NodePath applies transform changes to its managed node."""
  43. from panda3d.core import NodePath
  44. np = NodePath('np')
  45. assert np.get_pos() == (0, 0, 0)
  46. assert np.get_hpr() == (0, 0, 0)
  47. assert np.get_scale() == (1, 1, 1)
  48. np.set_pos(1, 2, 3)
  49. assert np.get_pos() == (1, 2, 3)
  50. assert np.node().get_transform().get_pos() == (1, 2, 3)
  51. def test_nodepath_transform_composition():
  52. """Tests that NodePath composes transform states according to the path it holds."""
  53. from panda3d.core import PandaNode, NodePath, LPoint3, LVector3
  54. # Create 3 PandaNodes, and give each some interesting transform state:
  55. node1 = PandaNode('node1')
  56. node2 = PandaNode('node2')
  57. node3 = PandaNode('node3')
  58. node1.set_transform(node1.get_transform().set_pos(LPoint3(0, 0, 1)).set_hpr(LVector3(90, 0, -90)))
  59. node2.set_transform(node2.get_transform().set_pos(LPoint3(0, 1, 0)).set_hpr(LVector3(180, 180, 0)))
  60. node3.set_transform(node3.get_transform().set_pos(LPoint3(1, 0, 0)).set_hpr(LVector3(270, 0, 270)))
  61. # node3 is going to be attached under both node1 and node2 and we will
  62. # hold a path both ways:
  63. node1.add_child(node3)
  64. node2.add_child(node3)
  65. assert len(node1.children) == 1
  66. assert len(node2.children) == 1
  67. assert len(node3.children) == 0
  68. assert len(node1.parents) == 0
  69. assert len(node2.parents) == 0
  70. assert len(node3.parents) == 2
  71. # np1 is the path to node3 via node1:
  72. np1 = NodePath(node1).children[0]
  73. # np2 is the path to node3 via node2:
  74. np2 = NodePath(node2).children[0]
  75. # Both should point to node3:
  76. assert np1.node() == node3
  77. assert np2.node() == node3
  78. # However if we ask for the net transform to node3, it should compose:
  79. assert np1.get_transform(NodePath()) == node1.get_transform().compose(node3.get_transform())
  80. assert np2.get_transform(NodePath()) == node2.get_transform().compose(node3.get_transform())
  81. # If we ask for np1 RELATIVE to np2, it should compose like so:
  82. leg1 = node2.get_transform().compose(node3.get_transform())
  83. leg2 = node1.get_transform().compose(node3.get_transform())
  84. relative_transform = leg1.get_inverse().compose(leg2)
  85. assert np1.get_transform(np2).compare_to(relative_transform, True) == 0
  86. def test_nodepath_comparison():
  87. from panda3d.core import NodePath, PandaNode
  88. path = NodePath("node")
  89. # Empty NodePath equals itself
  90. assert NodePath() == NodePath()
  91. assert not (NodePath() != NodePath())
  92. assert not (NodePath() > NodePath())
  93. assert not (NodePath() < NodePath())
  94. assert NodePath().compare_to(NodePath()) == 0
  95. # Empty NodePath does not equal non-empty NodePath
  96. assert NodePath() != path
  97. assert not (NodePath() == path)
  98. assert NodePath().compare_to(path) != 0
  99. assert path != NodePath()
  100. assert not (path == NodePath())
  101. assert path.compare_to(NodePath()) != 0
  102. # Copy of NodePath equals original
  103. path2 = NodePath(path)
  104. assert path == path2
  105. assert path2 == path
  106. assert not (path != path2)
  107. assert not (path2 != path)
  108. assert not (path > path2)
  109. assert not (path < path2)
  110. assert path.compare_to(path2) == 0
  111. assert path2.compare_to(path) == 0
  112. # NodePath pointing to copy of node is not the same
  113. path2 = NodePath(path.node().make_copy())
  114. assert path != path2
  115. assert path2 != path
  116. assert not (path == path2)
  117. assert not (path2 == path)
  118. assert (path2 > path) or (path > path2)
  119. assert (path2 < path) or (path < path2)
  120. assert path.compare_to(path2) != 0
  121. assert path2.compare_to(path) != 0
  122. def test_weak_nodepath_comparison():
  123. from panda3d.core import NodePath, WeakNodePath
  124. path = NodePath("node")
  125. weak = WeakNodePath(path)
  126. assert path == weak
  127. assert weak == path
  128. assert weak <= path
  129. assert path <= weak
  130. assert weak >= path
  131. assert path >= weak
  132. assert not (path != weak)
  133. assert not (weak != path)
  134. assert not (weak > path)
  135. assert not (path > weak)
  136. assert not (weak < path)
  137. assert not (path < weak)
  138. assert hash(path) == hash(weak)
  139. assert weak.get_node_path() == path
  140. assert weak.node() == path.node()
  141. def test_nodepath_flatten_tags_identical():
  142. from panda3d.core import NodePath, PandaNode
  143. # Do flatten nodes with same tags
  144. node1 = PandaNode("node1")
  145. node1.set_tag("key", "value")
  146. node2 = PandaNode("node2")
  147. node2.set_tag("key", "value")
  148. path = NodePath("parent")
  149. path.node().add_child(node1)
  150. path.node().add_child(node2)
  151. path.flatten_strong()
  152. assert len(path.children) == 1
  153. def test_nodepath_flatten_tags_same_key():
  154. from panda3d.core import NodePath, PandaNode
  155. # Don't flatten nodes with different tag keys
  156. node1 = PandaNode("node1")
  157. node1.set_tag("key1", "value")
  158. node2 = PandaNode("node2")
  159. node2.set_tag("key2", "value")
  160. path = NodePath("parent")
  161. path.node().add_child(node1)
  162. path.node().add_child(node2)
  163. path.flatten_strong()
  164. assert len(path.children) == 2
  165. def test_nodepath_flatten_tags_same_value():
  166. from panda3d.core import NodePath, PandaNode
  167. # Don't flatten nodes with different tag values
  168. node1 = PandaNode("node1")
  169. node1.set_tag("key", "value1")
  170. node2 = PandaNode("node2")
  171. node2.set_tag("key", "value2")
  172. path = NodePath("parent")
  173. path.node().add_child(node1)
  174. path.node().add_child(node2)
  175. path.flatten_strong()
  176. assert len(path.children) == 2
  177. def test_nodepath_python_tags():
  178. from panda3d.core import NodePath
  179. path = NodePath("node")
  180. with pytest.raises(KeyError):
  181. path.python_tags["foo"]
  182. path.python_tags["foo"] = "bar"
  183. assert path.python_tags["foo"] == "bar"
  184. # Make sure reference count stays the same
  185. rc1 = sys.getrefcount(path.python_tags)
  186. rc2 = sys.getrefcount(path.python_tags)
  187. assert rc1 == rc2
  188. def test_nodepath_clear_python_tag():
  189. from panda3d.core import NodePath
  190. path = NodePath("node")
  191. assert not path.has_python_tag("a")
  192. assert not path.has_python_tag("b")
  193. assert not path.node().has_tags()
  194. path.set_python_tag("a", "value")
  195. assert path.has_python_tag("a")
  196. assert not path.has_python_tag("b")
  197. assert path.node().has_tags()
  198. path.set_python_tag("b", "value")
  199. assert path.has_python_tag("a")
  200. assert path.has_python_tag("b")
  201. assert path.node().has_tags()
  202. path.clear_python_tag("a")
  203. assert not path.has_python_tag("a")
  204. assert path.has_python_tag("b")
  205. assert path.node().has_tags()
  206. path.clear_python_tag("b")
  207. assert not path.has_python_tag("a")
  208. assert not path.has_python_tag("b")
  209. assert not path.node().has_tags()
  210. def test_nodepath_replace_texture():
  211. from panda3d.core import NodePath, Texture
  212. tex1 = Texture()
  213. tex2 = Texture()
  214. path1 = NodePath("node1")
  215. path1.set_texture(tex1)
  216. path1.replace_texture(tex1, tex2)
  217. assert path1.get_texture() == tex2
  218. path1 = NodePath("node1")
  219. path2 = path1.attach_new_node("node2")
  220. path2.set_texture(tex1)
  221. path1.replace_texture(tex1, tex2)
  222. assert not path1.has_texture()
  223. assert path2.get_texture() == tex2
  224. def test_nodepath_replace_texture_none():
  225. from panda3d.core import NodePath, Texture
  226. tex1 = Texture("tex1")
  227. path1 = NodePath("node1")
  228. assert path1.get_texture() is None
  229. path1.set_texture(tex1)
  230. assert path1.get_texture() == tex1
  231. path1.replace_texture(tex1, None)
  232. assert path1.get_texture() is None
  233. path1 = NodePath("node1")
  234. path2 = path1.attach_new_node("node2")
  235. assert path2.get_texture() is None
  236. path2.set_texture(tex1)
  237. assert path2.get_texture() == tex1
  238. path1.replace_texture(tex1, None)
  239. assert path2.get_texture() is None
  240. def test_nodepath_set_collide_owner():
  241. from panda3d.core import NodePath, CollisionNode
  242. class CustomOwner:
  243. pass
  244. owner1 = CustomOwner()
  245. owner2 = CustomOwner()
  246. owner3 = CustomOwner()
  247. root = NodePath("root")
  248. model1 = root.attach_new_node("model1")
  249. collider1 = model1.attach_new_node(CollisionNode("collider1"))
  250. collider2 = model1.attach_new_node(CollisionNode("collider2"))
  251. model2 = root.attach_new_node("model2")
  252. collider3 = model2.attach_new_node(CollisionNode("collider3"))
  253. root.set_collide_owner(owner1)
  254. assert collider1.node().owner is owner1
  255. assert collider2.node().owner is owner1
  256. assert collider3.node().owner is owner1
  257. model1.set_collide_owner(None)
  258. assert collider1.node().owner is None
  259. assert collider2.node().owner is None
  260. assert collider3.node().owner is owner1
  261. collider2.set_collide_owner(owner2)
  262. assert collider1.node().owner is None
  263. assert collider2.node().owner is owner2
  264. assert collider3.node().owner is owner1
  265. del owner1
  266. assert collider1.node().owner is None
  267. assert collider2.node().owner is owner2
  268. assert collider3.node().owner is None
  269. root.set_collide_owner(owner3)
  270. model2.set_collide_owner(owner2)
  271. assert collider1.node().owner is owner3
  272. assert collider2.node().owner is owner3
  273. assert collider3.node().owner is owner2