test_nodepath.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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