From 92b243dc3c356c20e1432d0ffc89e1386a67b926 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Thu, 4 Apr 2024 03:54:33 -0700 Subject: [PATCH] Separate Shape3D resource logic in GLTFPhysicsShape --- modules/gltf/doc_classes/GLTFPhysicsBody.xml | 2 +- modules/gltf/doc_classes/GLTFPhysicsShape.xml | 16 ++++- .../gltf_document_extension_physics.cpp | 1 + .../extensions/physics/gltf_physics_shape.cpp | 65 ++++++++++++------- .../extensions/physics/gltf_physics_shape.h | 5 +- 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/modules/gltf/doc_classes/GLTFPhysicsBody.xml b/modules/gltf/doc_classes/GLTFPhysicsBody.xml index 5cfc22f6b2b..cd701e2f2f2 100644 --- a/modules/gltf/doc_classes/GLTFPhysicsBody.xml +++ b/modules/gltf/doc_classes/GLTFPhysicsBody.xml @@ -22,7 +22,7 @@ - Create a new GLTFPhysicsBody instance from the given Godot [CollisionObject3D] node. + Creates a new GLTFPhysicsBody instance from the given Godot [CollisionObject3D] node. diff --git a/modules/gltf/doc_classes/GLTFPhysicsShape.xml b/modules/gltf/doc_classes/GLTFPhysicsShape.xml index c397c660d91..a4aaf9415cf 100644 --- a/modules/gltf/doc_classes/GLTFPhysicsShape.xml +++ b/modules/gltf/doc_classes/GLTFPhysicsShape.xml @@ -23,7 +23,14 @@ - Create a new GLTFPhysicsShape instance from the given Godot [CollisionShape3D] node. + Creates a new GLTFPhysicsShape instance from the given Godot [CollisionShape3D] node. + + + + + + + Creates a new GLTFPhysicsShape instance from the given Godot [Shape3D] resource. @@ -39,6 +46,13 @@ Converts this GLTFPhysicsShape instance into a Godot [CollisionShape3D] node. + + + + + Converts this GLTFPhysicsShape instance into a Godot [Shape3D] resource. + + diff --git a/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp b/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp index c6e34cc0235..352b439332e 100644 --- a/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp +++ b/modules/gltf/extensions/physics/gltf_document_extension_physics.cpp @@ -355,6 +355,7 @@ void GLTFDocumentExtensionPhysics::convert_scene_node(Ref p_state, Re if (cast_to(p_scene_node)) { CollisionShape3D *godot_shape = Object::cast_to(p_scene_node); Ref gltf_shape = GLTFPhysicsShape::from_node(godot_shape); + ERR_FAIL_COND_MSG(gltf_shape.is_null(), "GLTF Physics: Could not convert CollisionShape3D to GLTFPhysicsShape. Does it have a valid Shape3D?"); { Ref importer_mesh = gltf_shape->get_importer_mesh(); if (importer_mesh.is_valid()) { diff --git a/modules/gltf/extensions/physics/gltf_physics_shape.cpp b/modules/gltf/extensions/physics/gltf_physics_shape.cpp index 6c9ed82a69e..6897bdbd3a5 100644 --- a/modules/gltf/extensions/physics/gltf_physics_shape.cpp +++ b/modules/gltf/extensions/physics/gltf_physics_shape.cpp @@ -46,6 +46,9 @@ void GLTFPhysicsShape::_bind_methods() { ClassDB::bind_static_method("GLTFPhysicsShape", D_METHOD("from_node", "shape_node"), &GLTFPhysicsShape::from_node); ClassDB::bind_method(D_METHOD("to_node", "cache_shapes"), &GLTFPhysicsShape::to_node, DEFVAL(false)); + ClassDB::bind_static_method("GLTFPhysicsShape", D_METHOD("from_resource", "shape_resource"), &GLTFPhysicsShape::from_resource); + ClassDB::bind_method(D_METHOD("to_resource", "cache_shapes"), &GLTFPhysicsShape::to_resource, DEFVAL(false)); + ClassDB::bind_static_method("GLTFPhysicsShape", D_METHOD("from_dictionary", "dictionary"), &GLTFPhysicsShape::from_dictionary); ClassDB::bind_method(D_METHOD("to_dictionary"), &GLTFPhysicsShape::to_dictionary); @@ -159,44 +162,57 @@ Ref _convert_hull_points_to_mesh(const Vector &p_hull_poi Ref GLTFPhysicsShape::from_node(const CollisionShape3D *p_godot_shape_node) { Ref gltf_shape; - gltf_shape.instantiate(); ERR_FAIL_NULL_V_MSG(p_godot_shape_node, gltf_shape, "Tried to create a GLTFPhysicsShape from a CollisionShape3D node, but the given node was null."); + Ref shape_resource = p_godot_shape_node->get_shape(); + ERR_FAIL_COND_V_MSG(shape_resource.is_null(), gltf_shape, "Tried to create a GLTFPhysicsShape from a CollisionShape3D node, but the given node had a null shape."); + gltf_shape = from_resource(shape_resource); + // Check if the shape is part of a trigger. Node *parent = p_godot_shape_node->get_parent(); if (cast_to(parent)) { gltf_shape->set_is_trigger(true); } - // All the code for working with the shape is below this comment. - Ref shape_resource = p_godot_shape_node->get_shape(); - ERR_FAIL_COND_V_MSG(shape_resource.is_null(), gltf_shape, "Tried to create a GLTFPhysicsShape from a CollisionShape3D node, but the given node had a null shape."); - gltf_shape->_shape_cache = shape_resource; - if (cast_to(shape_resource.ptr())) { + return gltf_shape; +} + +CollisionShape3D *GLTFPhysicsShape::to_node(bool p_cache_shapes) { + CollisionShape3D *godot_shape_node = memnew(CollisionShape3D); + to_resource(p_cache_shapes); // Sets `_shape_cache`. + godot_shape_node->set_shape(_shape_cache); + return godot_shape_node; +} + +Ref GLTFPhysicsShape::from_resource(const Ref &p_shape_resource) { + Ref gltf_shape; + gltf_shape.instantiate(); + ERR_FAIL_COND_V_MSG(p_shape_resource.is_null(), gltf_shape, "Tried to create a GLTFPhysicsShape from a Shape3D resource, but the given resource was null."); + if (cast_to(p_shape_resource.ptr())) { gltf_shape->shape_type = "box"; - Ref box = shape_resource; + Ref box = p_shape_resource; gltf_shape->set_size(box->get_size()); - } else if (cast_to(shape_resource.ptr())) { + } else if (cast_to(p_shape_resource.ptr())) { gltf_shape->shape_type = "capsule"; - Ref capsule = shape_resource; + Ref capsule = p_shape_resource; gltf_shape->set_radius(capsule->get_radius()); gltf_shape->set_height(capsule->get_height()); - } else if (cast_to(shape_resource.ptr())) { + } else if (cast_to(p_shape_resource.ptr())) { gltf_shape->shape_type = "cylinder"; - Ref cylinder = shape_resource; + Ref cylinder = p_shape_resource; gltf_shape->set_radius(cylinder->get_radius()); gltf_shape->set_height(cylinder->get_height()); - } else if (cast_to(shape_resource.ptr())) { + } else if (cast_to(p_shape_resource.ptr())) { gltf_shape->shape_type = "sphere"; - Ref sphere = shape_resource; + Ref sphere = p_shape_resource; gltf_shape->set_radius(sphere->get_radius()); - } else if (cast_to(shape_resource.ptr())) { + } else if (cast_to(p_shape_resource.ptr())) { gltf_shape->shape_type = "convex"; - Ref convex = shape_resource; + Ref convex = p_shape_resource; Vector hull_points = convex->get_points(); Ref importer_mesh = _convert_hull_points_to_mesh(hull_points); ERR_FAIL_COND_V_MSG(importer_mesh.is_null(), gltf_shape, "GLTFPhysicsShape: Failed to convert convex hull points to a mesh."); gltf_shape->set_importer_mesh(importer_mesh); - } else if (cast_to(shape_resource.ptr())) { + } else if (cast_to(p_shape_resource.ptr())) { gltf_shape->shape_type = "trimesh"; - Ref concave = shape_resource; + Ref concave = p_shape_resource; Ref importer_mesh; importer_mesh.instantiate(); Array surface_array; @@ -205,14 +221,14 @@ Ref GLTFPhysicsShape::from_node(const CollisionShape3D *p_godo importer_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, surface_array); gltf_shape->set_importer_mesh(importer_mesh); } else { - ERR_PRINT("Tried to create a GLTFPhysicsShape from a CollisionShape3D node, but the given node's shape '" + String(Variant(shape_resource)) + + ERR_PRINT("Tried to create a GLTFPhysicsShape from a Shape3D, but the given shape '" + String(Variant(p_shape_resource)) + "' had an unsupported shape type. Only BoxShape3D, CapsuleShape3D, CylinderShape3D, SphereShape3D, ConcavePolygonShape3D, and ConvexPolygonShape3D are supported."); } + gltf_shape->_shape_cache = p_shape_resource; return gltf_shape; } -CollisionShape3D *GLTFPhysicsShape::to_node(bool p_cache_shapes) { - CollisionShape3D *godot_shape_node = memnew(CollisionShape3D); +Ref GLTFPhysicsShape::to_resource(bool p_cache_shapes) { if (!p_cache_shapes || _shape_cache == nullptr) { if (shape_type == "box") { Ref box; @@ -237,19 +253,18 @@ CollisionShape3D *GLTFPhysicsShape::to_node(bool p_cache_shapes) { sphere->set_radius(radius); _shape_cache = sphere; } else if (shape_type == "convex") { - ERR_FAIL_COND_V_MSG(importer_mesh.is_null(), godot_shape_node, "GLTFPhysicsShape: Error converting convex hull shape to a node: The mesh resource is null."); + ERR_FAIL_COND_V_MSG(importer_mesh.is_null(), _shape_cache, "GLTFPhysicsShape: Error converting convex hull shape to a shape resource: The mesh resource is null."); Ref convex = importer_mesh->get_mesh()->create_convex_shape(); _shape_cache = convex; } else if (shape_type == "trimesh") { - ERR_FAIL_COND_V_MSG(importer_mesh.is_null(), godot_shape_node, "GLTFPhysicsShape: Error converting concave mesh shape to a node: The mesh resource is null."); + ERR_FAIL_COND_V_MSG(importer_mesh.is_null(), _shape_cache, "GLTFPhysicsShape: Error converting concave mesh shape to a shape resource: The mesh resource is null."); Ref concave = importer_mesh->create_trimesh_shape(); _shape_cache = concave; } else { - ERR_PRINT("GLTFPhysicsShape: Error converting to a node: Shape type '" + shape_type + "' is unknown."); + ERR_PRINT("GLTFPhysicsShape: Error converting to a shape resource: Shape type '" + shape_type + "' is unknown."); } } - godot_shape_node->set_shape(_shape_cache); - return godot_shape_node; + return _shape_cache; } Ref GLTFPhysicsShape::from_dictionary(const Dictionary p_dictionary) { diff --git a/modules/gltf/extensions/physics/gltf_physics_shape.h b/modules/gltf/extensions/physics/gltf_physics_shape.h index ec0a8931f19..a6974473eea 100644 --- a/modules/gltf/extensions/physics/gltf_physics_shape.h +++ b/modules/gltf/extensions/physics/gltf_physics_shape.h @@ -55,7 +55,7 @@ private: bool is_trigger = false; GLTFMeshIndex mesh_index = -1; Ref importer_mesh = nullptr; - // Internal only, for caching Godot shape resources. Used in `to_node`. + // Internal only, for caching Godot shape resources. Used in `to_resource` and `to_node`. Ref _shape_cache = nullptr; public: @@ -83,6 +83,9 @@ public: static Ref from_node(const CollisionShape3D *p_shape_node); CollisionShape3D *to_node(bool p_cache_shapes = false); + static Ref from_resource(const Ref &p_shape_resource); + Ref to_resource(bool p_cache_shapes = false); + static Ref from_dictionary(const Dictionary p_dictionary); Dictionary to_dictionary() const; };