mirror of
https://github.com/godotengine/godot.git
synced 2024-11-27 09:16:35 +08:00
Merge pull request #88301 from aaronfranke/gltf-explicit-compound-triggers
Add support for explicitly-defined compound triggers in GLTF files
This commit is contained in:
commit
cb01094ccd
@ -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()) {
|
||||
|
Loading…
Reference in New Issue
Block a user