client.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #!/usr/bin/python
  2. # Ping a peer
  3. from pydrk import Api, exc, ErrorCode, HostApi, SceneNodeType, PropertyType, vertex, face, serial
  4. import sys, zmq
  5. def join(parent_path, child_name):
  6. if parent_path == "/":
  7. return f"/{child_name}"
  8. return f"{parent_path}/{child_name}"
  9. def print_tree():
  10. root_id = api.lookup_node_id("/")
  11. print_node_info(root_id)
  12. def print_node_info(parent_id, indent=0):
  13. ws = " "*4*indent
  14. for (child_name, child_id, child_type) in api.get_children(parent_id):
  15. match child_type:
  16. case SceneNodeType.ROOT:
  17. child_type = "root"
  18. case SceneNodeType.WINDOW:
  19. child_type = "window"
  20. case SceneNodeType.WINDOW_INPUT:
  21. child_type = "window_input"
  22. case SceneNodeType.KEYBOARD:
  23. child_type = "keyboard"
  24. case SceneNodeType.MOUSE:
  25. child_type = "mouse"
  26. case SceneNodeType.RENDER_LAYER:
  27. child_type = "render_layer"
  28. case SceneNodeType.RENDER_OBJECT:
  29. child_type = "render_object"
  30. case SceneNodeType.RENDER_MESH:
  31. child_type = "render_mesh"
  32. case SceneNodeType.RENDER_TEXT:
  33. child_type = "render_text"
  34. case SceneNodeType.RENDER_TEXTURE:
  35. child_type = "render_texture"
  36. case SceneNodeType.FONTS:
  37. child_type = "fonts"
  38. case SceneNodeType.FONT:
  39. child_type = "font"
  40. case SceneNodeType.LINE_POSITION:
  41. child_type = "line_position"
  42. desc = f"{ws}{child_name}:{child_id}/"
  43. desc += " "*(50 - len(desc))
  44. desc += f"[{child_type}]"
  45. print(desc)
  46. print_node_info(child_id, indent+1)
  47. for prop_name, prop_type in api.get_properties(parent_id):
  48. if prop_type == PropertyType.STR:
  49. prop_val = api.get_property(parent_id, prop_name)
  50. prop_val = f" = \"{prop_val}\""
  51. elif prop_type != PropertyType.BUFFER:
  52. prop_val = api.get_property(parent_id, prop_name)
  53. prop_val = f" = {prop_val}"
  54. else:
  55. prop_val = ""
  56. prop_type = PropertyType.to_str(prop_type)
  57. print(f"{ws}{prop_name}: {prop_type}{prop_val}")
  58. for sig in api.get_signals(parent_id):
  59. print(f"{ws}~{sig}")
  60. for slot_id, slot in api.get_slots(parent_id, sig):
  61. print(f"{ws}- '{slot}' ({slot_id})")
  62. for method_name in api.get_methods(parent_id):
  63. args, results = api.get_method(parent_id, method_name)
  64. args = [f"{name}: " + PropertyType.to_str(typ) for (name, typ) in args]
  65. results = [f"{name}: " + PropertyType.to_str(typ) for (name, typ) in results]
  66. method_str = f"{method_name}(" + ", ".join(args) + ") -> (" + ", ".join(results) + ")"
  67. print(f"{ws}{method_str}")
  68. def make_sub_socket():
  69. context = zmq.Context()
  70. socket = context.socket(zmq.SUB)
  71. socket.setsockopt(zmq.SUBSCRIBE, b'')
  72. socket.connect("tcp://localhost:9485")
  73. return socket
  74. def remove_node_recursive(node_id):
  75. for (_, child_id, _) in api.get_children(node_id):
  76. # Unlink the child
  77. api.unlink_node(child_id, node_id)
  78. # Remove the node
  79. remove_node_recursive(child_id)
  80. # Garbage collection
  81. if not api.get_parents(node_id):
  82. api.remove_node(node_id)
  83. def clear_layer(layer_path):
  84. layer_id = api.lookup_node_id("/window/layer2")
  85. if layer_id is None:
  86. return
  87. win_id = api.lookup_node_id("/window")
  88. api.unlink_node(layer_id, win_id)
  89. for (_, child_id, child_type) in api.get_children(layer_id):
  90. api.unlink_node(child_id, layer_id)
  91. if child_type == SceneNodeType.RENDER_OBJECT:
  92. remove_node_recursive(child_id)
  93. api.remove_node(layer_id)
  94. def remove_all_slots(node_path, sig):
  95. node_id = api.lookup_node_id(node_path)
  96. for slot_id, slot in api.get_slots(node_id, sig):
  97. print(f"{node_path}:{sig}(): Unregistering slot '{slot}':{slot_id}")
  98. api.unregister_slot(node_id, sig, slot_id)
  99. def register_slot(node_path, sig, tag):
  100. remove_all_slots(node_path, sig)
  101. node_id = api.lookup_node_id(node_path)
  102. api.register_slot(node_id, sig, "", tag)
  103. def get_property(node_path, prop):
  104. node_id = api.lookup_node_id(node_path)
  105. return api.get_property(node_id, prop)
  106. def set_property(node_path, prop, val):
  107. node_id = api.lookup_node_id(node_path)
  108. match val:
  109. case float():
  110. api.set_property_f32(node_id, prop, val)
  111. case int():
  112. api.set_property_u32(node_id, prop, val)
  113. def recalc_areas():
  114. print("recalc areas")
  115. w = get_property("/window", "width")
  116. h = get_property("/window", "height")
  117. set_property("/window/layer2", "rect_w", int(w))
  118. set_property("/window/layer2", "rect_h", int(h))
  119. print_tree()
  120. def garbage_collect():
  121. for node_id in api.scan_dangling():
  122. remove_node_recursive(node_id)
  123. api = Api()
  124. host = HostApi(api)
  125. print(api.hello())
  126. garbage_collect()
  127. clear_layer("/window/layer2")
  128. print("Generating scene...")
  129. subsock = make_sub_socket()
  130. register_slot("/window", "resize", b"resize")
  131. register_slot("/window/input/mouse", "button_down", b"click")
  132. register_slot("/window/input/mouse", "wheel", b"wheel")
  133. #register_slot("/window/input/mouse", "move", b"mouse")
  134. layer_id = api.add_node("layer2", SceneNodeType.RENDER_LAYER)
  135. api.add_property(layer_id, "rect_x", PropertyType.UINT32)
  136. api.add_property(layer_id, "rect_y", PropertyType.UINT32)
  137. api.add_property(layer_id, "rect_w", PropertyType.UINT32)
  138. api.add_property(layer_id, "rect_h", PropertyType.UINT32)
  139. api.add_property(layer_id, "is_visible", PropertyType.BOOL)
  140. api.set_property_bool(layer_id, "is_visible", True)
  141. win_id = api.lookup_node_id("/window")
  142. api.link_node(layer_id, win_id)
  143. if True:
  144. layer_id = api.lookup_node_id("/window/layer2")
  145. obj_id = api.add_node("obj1", SceneNodeType.RENDER_OBJECT)
  146. api.add_property(obj_id, "x", PropertyType.FLOAT32)
  147. api.add_property(obj_id, "y", PropertyType.FLOAT32)
  148. api.add_property(obj_id, "scale", PropertyType.FLOAT32)
  149. api.set_property_f32(obj_id, "scale", 1.0)
  150. mesh_id = api.add_node("mesh", SceneNodeType.RENDER_MESH)
  151. api.add_property(mesh_id, "verts", PropertyType.BUFFER)
  152. api.add_property(mesh_id, "faces", PropertyType.BUFFER)
  153. texture_id = host.load_texture("da_king", "king.png")
  154. api.link_node(texture_id, obj_id)
  155. # To preserve the ratio, we should do this when resize happens too
  156. texture_w = api.get_property(texture_id, "width")
  157. texture_h = api.get_property(texture_id, "width")
  158. texture_ratio = texture_w / texture_h
  159. screen_w = get_property("/window", "width")
  160. screen_h = get_property("/window", "height")
  161. screen_ratio = screen_w / screen_h
  162. aspect_ratio = texture_ratio / screen_ratio
  163. #api.set_property_bool("/window/layer2", "is_visible", False)
  164. # Lets add a poly - must be counterclockwise
  165. x, y = 0.25, 0.25
  166. w, h = 0.5 * aspect_ratio, 0.5
  167. vert1 = vertex(x, y, 1, 1, 1, 1, 0, 0)
  168. vert2 = vertex(x + w, y, 1, 1, 1, 1, 1, 0)
  169. vert3 = vertex(x, y + h, 1, 1, 1, 1, 0, 1)
  170. vert4 = vertex(x + w, y + h, 1, 1, 1, 1, 1, 1)
  171. api.set_property_buffer(mesh_id, "verts", vert1 + vert2 + vert3 + vert4)
  172. api.set_property_buffer(mesh_id, "faces", face(0, 2, 1) + face(1, 2, 3))
  173. api.link_node(mesh_id, obj_id)
  174. api.link_node(obj_id, layer_id)
  175. if True:
  176. layer_id = api.lookup_node_id("/window/layer2")
  177. obj_id = api.add_node("obj", SceneNodeType.RENDER_OBJECT)
  178. api.add_property(obj_id, "x", PropertyType.FLOAT32)
  179. api.add_property(obj_id, "y", PropertyType.FLOAT32)
  180. api.add_property(obj_id, "scale", PropertyType.FLOAT32)
  181. api.set_property_f32(obj_id, "scale", 1.0)
  182. # Call method
  183. text_id = host.create_text(
  184. "/font/inter-regular", "mytxt2", "hello world", 34
  185. )
  186. if text_id is None:
  187. sys.exit(-1)
  188. print("create text node id:", text_id)
  189. api.set_property_f32(obj_id, "x", 0.5)
  190. api.set_property_f32(text_id, "r", 1.0)
  191. api.set_property_f32(text_id, "g", 1.0)
  192. api.set_property_f32(text_id, "b", 1.0)
  193. api.set_property_f32(text_id, "a", 1.0)
  194. api.link_node(text_id, obj_id)
  195. api.link_node(obj_id, layer_id)
  196. # Screen init
  197. recalc_areas()
  198. print_tree()
  199. print()
  200. print("Scene created.")
  201. while True:
  202. data = subsock.recv()
  203. match data:
  204. case b"resize":
  205. recalc_areas()
  206. case b"click":
  207. x = get_property("/window/input/mouse", "x")
  208. y = get_property("/window/input/mouse", "y")
  209. print(f"mouse clicked ({x}, {y})")
  210. case b"wheel":
  211. print("mouse wheely")