44
55#include < godot_cpp/variant/array.hpp>
66#include < godot_cpp/variant/dictionary.hpp>
7- #include < godot_cpp/classes/physics_server2d.hpp>
8- #include < godot_cpp/classes/physics_server3d.hpp>
9- #include < godot_cpp/variant/transform2d.hpp>
10- #include < godot_cpp/variant/transform3d.hpp>
117#include < godot_cpp/variant/utility_functions.hpp>
128#include < godot_cpp/variant/variant.hpp>
139
14- #include " src/components/physics.h"
1510#include " src/components/transform.h"
1611#include " src/flecs_registry.h"
1712
18- using godot::Array;
1913using godot::Dictionary;
2014using godot::UtilityFunctions;
2115using godot::Variant;
22-
23- namespace
24- {
25- template <typename ShapesT, typename ShapeDefinitionT, typename SpaceT, typename ServerT, typename TransformT, typename InstanceT, typename BodyStateT>
26- inline bool create_physics_body (
27- flecs::entity& instance,
28- const ShapesT& body_definition,
29- const SpaceT* physics_space,
30- ServerT* physics_server,
31- const TransformT& transform,
32- BodyStateT transform_state)
33- {
34- if (!physics_server) { return false ; }
35- if (!physics_space) { return false ; }
36- if (!physics_space->space_rid .is_valid ()) { return false ; }
37- if (body_definition.shapes .empty ()) { return false ; }
38-
39- godot::RID body_rid = physics_server->body_create ();
40- physics_server->body_set_mode (body_rid, body_definition.body_mode );
41- physics_server->body_set_space (body_rid, physics_space->space_rid );
42- physics_server->body_set_collision_layer (body_rid, body_definition.collision_layer );
43- physics_server->body_set_collision_mask (body_rid, body_definition.collision_mask );
44-
45- for (const ShapeDefinitionT& shape_def : body_definition.shapes )
46- {
47- physics_server->body_add_shape (body_rid, shape_def.shape ->get_rid (), shape_def.local_transform );
48- }
49-
50- physics_server->body_set_state (body_rid, transform_state, transform);
51- instance.set <InstanceT>({ body_rid });
52- return true ;
53- }
54-
55- template <
56- typename PhysicsServerT,
57- typename PhysicsSpaceT,
58- typename PhysicsBodyShapesT,
59- typename PhysicsBodyShapeDefinitionT,
60- typename TransformT,
61- typename PhysicsBodyInstanceT,
62- typename BodyStateT>
63- inline void process_physics_for_instance (
64- flecs::iter& it,
65- flecs::entity& instance,
66- bool & physics_ready,
67- bool & warned_missing_physics,
68- bool has_spawn_transform,
69- const TransformT& spawn_transform,
70- const godot::String& prefab_name)
71- {
72- PhysicsServerT* physics_server = PhysicsServerT::get_singleton ();
73- const PhysicsSpaceT* physics_space = physics_server ? it.world ().template try_get <PhysicsSpaceT>() : nullptr ;
74- if (!physics_ready)
75- {
76- physics_ready = physics_server && physics_space && physics_space->space_rid .is_valid ();
77- }
78-
79- const PhysicsBodyShapesT* body_shapes = instance.template try_get <PhysicsBodyShapesT>();
80- if (body_shapes && !body_shapes->shapes .empty ())
81- {
82- if (!physics_ready)
83- {
84- if (!warned_missing_physics)
85- {
86- UtilityFunctions::push_warning (godot::String (" Prefab Instantiation: " ) + it.world ().template component <PhysicsBodyShapesT>().name ().c_str () + " present but physics space is unavailable." );
87- warned_missing_physics = true ;
88- }
89- return ;
90- }
91-
92- // Validate shapes before creating a body
93- for (const auto & shape_def : body_shapes->shapes )
94- {
95- if (shape_def.shape .is_null ())
96- {
97- UtilityFunctions::push_warning (godot::String (" Prefab Instantiation: " ) + it.world ().template component <PhysicsBodyShapesT>().name ().c_str () + " contains an invalid shape reference." );
98- return ; // Abort for this instance if any shape is invalid
99- }
100- }
101-
102- const TransformT* transform_component = has_spawn_transform ? &spawn_transform : instance.template try_get <TransformT>();
103- TransformT final_transform = transform_component ? *transform_component : TransformT ();
104-
105- if (!create_physics_body<PhysicsBodyShapesT, PhysicsBodyShapeDefinitionT, PhysicsSpaceT, PhysicsServerT, TransformT, PhysicsBodyInstanceT, BodyStateT>(
106- instance,
107- *body_shapes,
108- physics_space,
109- physics_server,
110- final_transform,
111- static_cast <BodyStateT>(PhysicsServerT::BODY_STATE_TRANSFORM)))
112- {
113- UtilityFunctions::push_warning (godot::String (" Prefab Instantiation: Failed to create physics body for prefab '" ) + prefab_name + " '." );
114- }
115- }
116- }
117- }
16+ using godot::Array;
11817
11918inline FlecsRegistry register_prefab_instantiation_system ([](flecs::world& world)
12019{
@@ -126,8 +25,6 @@ inline FlecsRegistry register_prefab_instantiation_system([](flecs::world& world
12625 .write <Position3D>()
12726 .write <Rotation3D>()
12827 .write <Scale3D>()
129- .write <PhysicsBodyInstance2D>()
130- .write <PhysicsBodyInstance3D>()
13128 .run ([&](flecs::iter& it)
13229 {
13330 const Dictionary* parameters = static_cast <const Dictionary*>(it.param ());
@@ -217,23 +114,9 @@ inline FlecsRegistry register_prefab_instantiation_system([](flecs::world& world
217114 has_transforms = true ;
218115 }
219116
220- godot::PhysicsServer2D* physics_server_2d = godot::PhysicsServer2D::get_singleton ();
221- const PhysicsSpace2D* physics_space_2d = physics_server_2d ? it.world ().try_get <PhysicsSpace2D>() : nullptr ;
222- bool physics_2d_ready = physics_server_2d && physics_space_2d && physics_space_2d->space_rid .is_valid ();
223- bool warned_missing_physics_2d = false ;
224-
225- godot::PhysicsServer3D* physics_server_3d = godot::PhysicsServer3D::get_singleton ();
226- const PhysicsSpace3D* physics_space_3d = physics_server_3d ? it.world ().try_get <PhysicsSpace3D>() : nullptr ;
227- bool physics_3d_ready = physics_server_3d && physics_space_3d && physics_space_3d->space_rid .is_valid ();
228- bool warned_missing_physics_3d = false ;
229-
230117 for (int instance_idx = 0 ; instance_idx < count; ++instance_idx)
231118 {
232119 flecs::entity instance = world.entity ().is_a (prefab);
233- bool has_spawn_transform_2d = false ;
234- godot::Transform2D spawn_transform_2d;
235- bool has_spawn_transform_3d = false ;
236- godot::Transform3D spawn_transform_3d;
237120 if (has_transforms) {
238121 if (transforms_are_2d) {
239122 godot::Transform2D transform = transforms_array[instance_idx];
@@ -244,9 +127,6 @@ inline FlecsRegistry register_prefab_instantiation_system([](flecs::world& world
244127 instance.set <Position2D>({ position });
245128 instance.set <Rotation2D>({ rotation });
246129 instance.set <Scale2D>({ scale });
247- instance.set <godot::Transform2D>(transform);
248- spawn_transform_2d = transform;
249- has_spawn_transform_2d = true ;
250130 }
251131 else {
252132 godot::Transform3D transform = transforms_array[instance_idx];
@@ -257,23 +137,8 @@ inline FlecsRegistry register_prefab_instantiation_system([](flecs::world& world
257137 instance.set <Position3D>({ position });
258138 instance.set <Rotation3D>({ rotation });
259139 instance.set <Scale3D>({ scale });
260- instance.set <godot::Transform3D>(transform);
261- spawn_transform_3d = transform;
262- has_spawn_transform_3d = true ;
263140 }
264141 }
265-
266- // Process 2D physics
267- process_physics_for_instance<
268- godot::PhysicsServer2D, PhysicsSpace2D, PhysicsBodyShapes2D, PhysicsBodyShape2DDefinition,
269- godot::Transform2D, PhysicsBodyInstance2D, godot::PhysicsServer2D::BodyState>(
270- it, instance, physics_2d_ready, warned_missing_physics_2d, has_spawn_transform_2d, spawn_transform_2d, prefab_name);
271-
272- // Process 3D physics
273- process_physics_for_instance<
274- godot::PhysicsServer3D, PhysicsSpace3D, PhysicsBodyShapes3D, PhysicsBodyShape3DDefinition,
275- godot::Transform3D, PhysicsBodyInstance3D, godot::PhysicsServer3D::BodyState>(
276- it, instance, physics_3d_ready, warned_missing_physics_3d, has_spawn_transform_3d, spawn_transform_3d, prefab_name);
277142 }
278143
279144 // UtilityFunctions::print(godot::String("Prefab Instantiation: spawned ") + godot::String::num_int64(count) + " instances of '" + prefab_name + "'");
0 commit comments