unit.lua 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. -- Copyright (c) 2012-2024 Daniele Bartolini et al.
  2. -- SPDX-License-Identifier: MIT
  3. require "core/lua/class"
  4. UnitUtils = UnitUtils or {}
  5. function UnitUtils.collect_children(scene_graph, unit_id, children)
  6. local transform = SceneGraph.instance(scene_graph, unit_id)
  7. if transform == nil then return end
  8. local cur_child = SceneGraph.first_child(scene_graph, transform)
  9. while cur_child ~= nil do
  10. local child_id = SceneGraph.owner(scene_graph, cur_child)
  11. UnitUtils.collect_children(scene_graph, child_id, children)
  12. table.insert(children, child_id)
  13. cur_child = SceneGraph.next_sibling(scene_graph, cur_child)
  14. end
  15. table.insert(children, unit_id)
  16. end
  17. function UnitUtils.freeze(world, unit_id)
  18. local physics_world = World.physics_world(world)
  19. local scene_graph = World.scene_graph(world)
  20. local children = {}
  21. UnitUtils.collect_children(scene_graph, unit_id, children)
  22. for _, child_id in ipairs(children) do
  23. local actor = PhysicsWorld.actor_instance(physics_world, child_id)
  24. if actor ~= nil then
  25. PhysicsWorld.actor_set_kinematic(physics_world, actor, true)
  26. end
  27. end
  28. end
  29. function UnitUtils.destroy_tree(world, unit_id)
  30. local scene_graph = World.scene_graph(world)
  31. local children = {}
  32. UnitUtils.collect_children(scene_graph, unit_id, children)
  33. for _, child_id in ipairs(children) do
  34. World.destroy_unit(world, child_id)
  35. end
  36. end
  37. UnitBox = class(UnitBox)
  38. function UnitBox:init(world, id, unit_id, prefab)
  39. self._world = world
  40. self._rw = World.render_world(world)
  41. self._id = id
  42. self._unit_id = unit_id
  43. self._prefab = prefab
  44. self._sg = World.scene_graph(world)
  45. self._selected = false
  46. UnitUtils.freeze(world, unit_id)
  47. end
  48. function UnitBox:id()
  49. return self._id
  50. end
  51. function UnitBox:prefab()
  52. return self._prefab
  53. end
  54. function UnitBox:unit_id()
  55. return self._unit_id
  56. end
  57. function UnitBox:destroy()
  58. UnitUtils.destroy_tree(self._world, self._unit_id)
  59. end
  60. function UnitBox:local_position()
  61. local tr = SceneGraph.instance(self._sg, self._unit_id)
  62. return tr and SceneGraph.local_position(self._sg, tr) or Vector3.zero()
  63. end
  64. function UnitBox:local_rotation()
  65. local tr = SceneGraph.instance(self._sg, self._unit_id)
  66. return tr and SceneGraph.local_rotation(self._sg, tr) or Quaternion.identity()
  67. end
  68. function UnitBox:local_scale()
  69. local tr = SceneGraph.instance(self._sg, self._unit_id)
  70. return tr and SceneGraph.local_scale(self._sg, tr) or Vector3(1, 1, 1)
  71. end
  72. function UnitBox:local_pose()
  73. local tr = SceneGraph.instance(self._sg, self._unit_id)
  74. return tr and SceneGraph.local_pose(self._sg, tr) or Matrix4x4.identity()
  75. end
  76. function UnitBox:world_position()
  77. local tr = SceneGraph.instance(self._sg, self._unit_id)
  78. return tr and SceneGraph.world_position(self._sg, tr) or Vector3.zero()
  79. end
  80. function UnitBox:world_rotation()
  81. local tr = SceneGraph.instance(self._sg, self._unit_id)
  82. return tr and SceneGraph.world_rotation(self._sg, tr) or Quaternion.identity()
  83. end
  84. function UnitBox:world_scale()
  85. return Vector3(1, 1, 1)
  86. end
  87. function UnitBox:world_pose()
  88. local tr = SceneGraph.instance(self._sg, self._unit_id)
  89. return tr and SceneGraph.world_pose(self._sg, tr) or Matrix4x4.identity()
  90. end
  91. function UnitBox:set_local_position(pos)
  92. local tr = SceneGraph.instance(self._sg, self._unit_id)
  93. if tr then SceneGraph.set_local_position(self._sg, tr, pos) end
  94. end
  95. function UnitBox:set_local_rotation(rot)
  96. local tr = SceneGraph.instance(self._sg, self._unit_id)
  97. if tr then SceneGraph.set_local_rotation(self._sg, tr, rot) end
  98. end
  99. function UnitBox:set_local_scale(scale)
  100. local tr = SceneGraph.instance(self._sg, self._unit_id)
  101. if tr then SceneGraph.set_local_scale(self._sg, tr, scale) end
  102. end
  103. function UnitBox:set_local_pose(pose)
  104. local tr = SceneGraph.instance(self._sg, self._unit_id)
  105. if tr then SceneGraph.set_local_pose(self._sg, tr, pose) end
  106. end
  107. function UnitBox:on_selected(selected)
  108. self._selected = selected
  109. RenderWorld.selection(self._rw, self._unit_id, selected);
  110. end
  111. -- Returns the Oriented Bounding-Box of the unit.
  112. function UnitBox:obb()
  113. local mesh = RenderWorld.mesh_instance(self._rw, self._unit_id)
  114. if mesh then
  115. return RenderWorld.mesh_obb(self._rw, mesh)
  116. end
  117. local sprite = RenderWorld.sprite_instance(self._rw, self._unit_id)
  118. if sprite then
  119. return RenderWorld.sprite_obb(self._rw, sprite)
  120. end
  121. return Matrix4x4.identity(), Vector3(1, 1, 1)
  122. end
  123. function UnitBox:raycast(pos, dir)
  124. local mesh = RenderWorld.mesh_instance(self._rw, self._unit_id)
  125. if mesh then
  126. return RenderWorld.mesh_cast_ray(self._rw, mesh, pos, dir)
  127. end
  128. local sprite = RenderWorld.sprite_instance(self._rw, self._unit_id)
  129. if sprite then
  130. return RenderWorld.sprite_cast_ray(self._rw, sprite, pos, dir)
  131. end
  132. return -1.0
  133. end
  134. function UnitBox:draw()
  135. if self._selected then
  136. local light = RenderWorld.light_instance(self._rw, self._unit_id)
  137. if light then
  138. RenderWorld.light_debug_draw(self._rw, light, LevelEditor._lines)
  139. end
  140. end
  141. end
  142. function UnitBox:set_light(type, range, intensity, angle, color)
  143. local light = RenderWorld.light_instance(self._rw, self._unit_id)
  144. RenderWorld.light_set_type(self._rw, light, type)
  145. RenderWorld.light_set_color(self._rw, light, color)
  146. RenderWorld.light_set_range(self._rw, light, range)
  147. RenderWorld.light_set_intensity(self._rw, light, intensity)
  148. RenderWorld.light_set_spot_angle(self._rw, light, angle)
  149. end
  150. function UnitBox:set_mesh(mesh_resource, geometry, material, visible)
  151. local mesh = RenderWorld.mesh_instance(self._rw, self._unit_id)
  152. RenderWorld.mesh_set_geometry(self._rw, mesh, mesh_resource, geometry)
  153. RenderWorld.mesh_set_material(self._rw, mesh, material)
  154. RenderWorld.mesh_set_visible(self._rw, mesh, visible)
  155. end
  156. function UnitBox:set_sprite(sprite_resource_name, material, layer, depth, visible)
  157. local sprite = RenderWorld.sprite_instance(self._rw, self._unit_id)
  158. RenderWorld.sprite_set_sprite(self._rw, sprite, sprite_resource_name)
  159. RenderWorld.sprite_set_material(self._rw, sprite, material)
  160. RenderWorld.sprite_set_layer(self._rw, sprite, layer)
  161. RenderWorld.sprite_set_depth(self._rw, sprite, depth)
  162. RenderWorld.sprite_set_visible(self._rw, sprite, visible)
  163. end
  164. function UnitBox:set_camera(projection, fov, near_range, far_range)
  165. local camera = World.camera_instance(self._world, self._unit_id)
  166. World.camera_set_projection_type(self._world, camera, projection)
  167. World.camera_set_fov(self._world, camera, fov)
  168. World.camera_set_near_clip_distance(self._world, camera, near_range)
  169. World.camera_set_far_clip_distance(self._world, camera, far_range)
  170. end
  171. function UnitBox:send()
  172. Device.console_send { type = "unit_spawned"
  173. , id = self._id
  174. , name = self:prefab()
  175. , position = self:local_position()
  176. , rotation = self:local_rotation()
  177. , scale = self:local_scale()
  178. }
  179. end