summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules/gltf/extensions/physics/gltf_document_extension_physics.cpp50
1 files changed, 46 insertions, 4 deletions
diff --git a/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp b/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp
index 352b439332..7e52cde059 100644
--- a/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp
+++ b/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp
@@ -127,6 +127,11 @@ Error GLTFDocumentExtensionPhysics::parse_node_extensions(Ref<GLTFState> p_state
trigger_body->set_body_type("trigger");
p_gltf_node->set_additional_data(StringName("GLTFPhysicsBody"), trigger_body);
}
+ // If this node defines explicit member shape nodes, save this information.
+ if (node_trigger.has("nodes")) {
+ Array node_trigger_nodes = node_trigger["nodes"];
+ p_gltf_node->set_additional_data(StringName("GLTFPhysicsCompoundTriggerNodes"), node_trigger_nodes);
+ }
}
if (physics_body_ext.has("motion") || physics_body_ext.has("type")) {
p_gltf_node->set_additional_data(StringName("GLTFPhysicsBody"), GLTFPhysicsBody::from_dictionary(physics_body_ext));
@@ -241,6 +246,19 @@ Node3D *_add_physics_node_to_given_node(Node3D *p_current_node, Node3D *p_child,
return p_current_node;
}
+Array _get_ancestor_compound_trigger_nodes(Ref<GLTFState> p_state, TypedArray<GLTFNode> p_state_nodes, CollisionObject3D *p_ancestor_col_obj) {
+ GLTFNodeIndex ancestor_index = p_state->get_node_index(p_ancestor_col_obj);
+ ERR_FAIL_INDEX_V(ancestor_index, p_state_nodes.size(), Array());
+ Ref<GLTFNode> ancestor_gltf_node = p_state_nodes[ancestor_index];
+ Variant compound_trigger_nodes = ancestor_gltf_node->get_additional_data(StringName("GLTFPhysicsCompoundTriggerNodes"));
+ if (compound_trigger_nodes.is_array()) {
+ return compound_trigger_nodes;
+ }
+ Array ret;
+ ancestor_gltf_node->set_additional_data(StringName("GLTFPhysicsCompoundTriggerNodes"), ret);
+ return ret;
+}
+
Node3D *GLTFDocumentExtensionPhysics::generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) {
Ref<GLTFPhysicsBody> gltf_physics_body = p_gltf_node->get_additional_data(StringName("GLTFPhysicsBody"));
#ifndef DISABLE_DEPRECATED
@@ -269,12 +287,27 @@ Node3D *GLTFDocumentExtensionPhysics::generate_scene_node(Ref<GLTFState> p_state
#endif // DISABLE_DEPRECATED
Node3D *ret = nullptr;
CollisionObject3D *ancestor_col_obj = nullptr;
+ Ref<GLTFPhysicsShape> gltf_physics_collider_shape = p_gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShape"));
+ Ref<GLTFPhysicsShape> gltf_physics_trigger_shape = p_gltf_node->get_additional_data(StringName("GLTFPhysicsTriggerShape"));
if (gltf_physics_body.is_valid()) {
ancestor_col_obj = gltf_physics_body->to_node();
ret = ancestor_col_obj;
} else {
ancestor_col_obj = _get_ancestor_collision_object(p_scene_parent);
- if (!Object::cast_to<PhysicsBody3D>(ancestor_col_obj)) {
+ if (Object::cast_to<Area3D>(ancestor_col_obj) && gltf_physics_trigger_shape.is_valid()) {
+ // At this point, we found an ancestor Area3D node. But do we want to use it for this trigger shape?
+ TypedArray<GLTFNode> state_nodes = p_state->get_nodes();
+ GLTFNodeIndex self_index = state_nodes.find(p_gltf_node);
+ Array compound_trigger_nodes = _get_ancestor_compound_trigger_nodes(p_state, state_nodes, ancestor_col_obj);
+ // Check if the ancestor specifies compound trigger nodes, and if this node is in there.
+ // Remember that JSON does not have integers, only "number", aka double-precision floats.
+ if (compound_trigger_nodes.size() > 0 && !compound_trigger_nodes.has(double(self_index))) {
+ // If the compound trigger we found is not the intended user of
+ // this shape node, then we need to create a new Area3D node.
+ ancestor_col_obj = memnew(Area3D);
+ ret = ancestor_col_obj;
+ }
+ } else if (!Object::cast_to<PhysicsBody3D>(ancestor_col_obj)) {
if (p_gltf_node->get_additional_data(StringName("GLTFPhysicsCompoundCollider"))) {
// If the GLTF file wants this node to group solid shapes together,
// and there is no parent body, we need to create a static body.
@@ -288,8 +321,6 @@ Node3D *GLTFDocumentExtensionPhysics::generate_scene_node(Ref<GLTFState> p_state
// set above. If there is no ancestor body, we will either generate an
// Area3D or StaticBody3D implicitly, so prefer an Area3D as the base
// node for best compatibility with signal connections to this node.
- Ref<GLTFPhysicsShape> gltf_physics_collider_shape = p_gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShape"));
- Ref<GLTFPhysicsShape> gltf_physics_trigger_shape = p_gltf_node->get_additional_data(StringName("GLTFPhysicsTriggerShape"));
bool is_ancestor_col_obj_solid = Object::cast_to<PhysicsBody3D>(ancestor_col_obj);
if (is_ancestor_col_obj_solid && gltf_physics_collider_shape.is_valid()) {
Node3D *child = _generate_shape_node_and_body_if_needed(p_state, p_gltf_node, gltf_physics_collider_shape, ancestor_col_obj, false);
@@ -362,8 +393,14 @@ void GLTFDocumentExtensionPhysics::convert_scene_node(Ref<GLTFState> p_state, Re
gltf_shape->set_mesh_index(_get_or_insert_mesh_in_state(p_state, importer_mesh));
}
}
- if (cast_to<Area3D>(_get_ancestor_collision_object(p_scene_node->get_parent()))) {
+ CollisionObject3D *ancestor_col_obj = _get_ancestor_collision_object(p_scene_node->get_parent());
+ if (cast_to<Area3D>(ancestor_col_obj)) {
p_gltf_node->set_additional_data(StringName("GLTFPhysicsTriggerShape"), gltf_shape);
+ // Write explicit member shape nodes to the ancestor compound trigger node.
+ TypedArray<GLTFNode> state_nodes = p_state->get_nodes();
+ GLTFNodeIndex self_index = state_nodes.size(); // The current p_gltf_node will be inserted next.
+ Array compound_trigger_nodes = _get_ancestor_compound_trigger_nodes(p_state, p_state->get_nodes(), ancestor_col_obj);
+ compound_trigger_nodes.push_back(double(self_index));
} else {
p_gltf_node->set_additional_data(StringName("GLTFPhysicsColliderShape"), gltf_shape);
}
@@ -422,6 +459,11 @@ Error GLTFDocumentExtensionPhysics::export_node(Ref<GLTFState> p_state, Ref<GLTF
Ref<GLTFPhysicsBody> physics_body = p_gltf_node->get_additional_data(StringName("GLTFPhysicsBody"));
if (physics_body.is_valid()) {
physics_body_ext = physics_body->to_dictionary();
+ Variant compound_trigger_nodes = p_gltf_node->get_additional_data(StringName("GLTFPhysicsCompoundTriggerNodes"));
+ if (compound_trigger_nodes.is_array()) {
+ Dictionary trigger_property = physics_body_ext.get_or_add("trigger", {});
+ trigger_property["nodes"] = compound_trigger_nodes;
+ }
}
Ref<GLTFPhysicsShape> collider_shape = p_gltf_node->get_additional_data(StringName("GLTFPhysicsColliderShape"));
if (collider_shape.is_valid()) {