Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for explicitly-defined compound triggers in GLTF files #88301

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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);
Expand Down Expand Up @@ -361,8 +392,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);
}
Expand Down Expand Up @@ -421,6 +458,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()) {
Expand Down
Loading