summaryrefslogtreecommitdiff
path: root/scene/resources
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources')
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/environment.cpp12
-rw-r--r--scene/resources/immediate_mesh.cpp17
-rw-r--r--scene/resources/material.cpp12
-rw-r--r--scene/resources/mesh.cpp5
-rw-r--r--scene/resources/primitive_meshes.cpp2
-rw-r--r--scene/resources/primitive_meshes.h2
-rw-r--r--scene/resources/resource_format_text.cpp7
-rw-r--r--scene/resources/resource_format_text.h1
-rw-r--r--scene/resources/skeleton_modification_3d.cpp151
-rw-r--r--scene/resources/skeleton_modification_3d.h79
-rw-r--r--scene/resources/skeleton_modification_3d_ccdik.cpp474
-rw-r--r--scene/resources/skeleton_modification_3d_ccdik.h114
-rw-r--r--scene/resources/skeleton_modification_3d_fabrik.cpp628
-rw-r--r--scene/resources/skeleton_modification_3d_fabrik.h124
-rw-r--r--scene/resources/skeleton_modification_3d_jiggle.cpp582
-rw-r--r--scene/resources/skeleton_modification_3d_jiggle.h138
-rw-r--r--scene/resources/skeleton_modification_3d_lookat.cpp267
-rw-r--r--scene/resources/skeleton_modification_3d_lookat.h89
-rw-r--r--scene/resources/skeleton_modification_3d_stackholder.cpp104
-rw-r--r--scene/resources/skeleton_modification_3d_stackholder.h59
-rw-r--r--scene/resources/skeleton_modification_3d_twoboneik.cpp617
-rw-r--r--scene/resources/skeleton_modification_3d_twoboneik.h118
-rw-r--r--scene/resources/skeleton_modification_stack_3d.cpp224
-rw-r--r--scene/resources/skeleton_modification_stack_3d.h91
-rw-r--r--scene/resources/tile_set.cpp1
-rw-r--r--scene/resources/visual_shader.cpp5
-rw-r--r--scene/resources/visual_shader_nodes.cpp473
-rw-r--r--scene/resources/visual_shader_nodes.h17
29 files changed, 321 insertions, 4094 deletions
diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp
index d92d4fa4a4..e51b48a4b1 100644
--- a/scene/resources/convex_polygon_shape_2d.cpp
+++ b/scene/resources/convex_polygon_shape_2d.cpp
@@ -82,7 +82,7 @@ void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) {
if (is_collision_outline_enabled()) {
RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);
// Draw the last segment as it's not drawn by `canvas_item_add_polyline()`.
- RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color, 1.0, true);
+ RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color, 1.0);
}
}
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 746f2f8f9b..8b4656414d 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -1043,6 +1043,18 @@ void Environment::_validate_property(PropertyInfo &p_property) const {
}
}
+ if (p_property.name == "ambient_light_color" || p_property.name == "ambient_light_energy") {
+ if (ambient_source == AMBIENT_SOURCE_DISABLED) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ }
+
+ if (p_property.name == "ambient_light_sky_contribution") {
+ if (ambient_source == AMBIENT_SOURCE_DISABLED || ambient_source == AMBIENT_SOURCE_COLOR) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ }
+
if (p_property.name == "fog_aerial_perspective") {
if (bg_mode != BG_SKY) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp
index 247927163b..f4a0db3930 100644
--- a/scene/resources/immediate_mesh.cpp
+++ b/scene/resources/immediate_mesh.cpp
@@ -194,25 +194,20 @@ void ImmediateMesh::surface_end() {
if (uses_normals) {
uint32_t *normal = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + normal_offset];
- Vector3 n = normals[i] * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
+ Vector2 n = normals[i].octahedron_encode();
uint32_t value = 0;
- value |= CLAMP(int(n.x * 1023.0), 0, 1023);
- value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
- value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
+ value |= (uint16_t)CLAMP(n.x * 65535, 0, 65535);
+ value |= (uint16_t)CLAMP(n.y * 65535, 0, 65535) << 16;
*normal = value;
}
if (uses_tangents) {
uint32_t *tangent = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + tangent_offset];
- Plane t = tangents[i];
+ Vector2 t = tangents[i].normal.octahedron_tangent_encode(tangents[i].d);
uint32_t value = 0;
- value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023);
- value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
- value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
- if (t.d > 0) {
- value |= 3UL << 30;
- }
+ value |= (uint16_t)CLAMP(t.x * 65535, 0, 65535);
+ value |= (uint16_t)CLAMP(t.y * 65535, 0, 65535) << 16;
*tangent = value;
}
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index d5c3f7730b..3e2a952ea7 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -791,6 +791,14 @@ void BaseMaterial3D::_update_shader() {
code += "uniform vec4 refraction_texture_channel;\n";
}
+ if (features[FEATURE_REFRACTION]) {
+ code += "uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear_mipmap;";
+ }
+
+ if (proximity_fade_enabled) {
+ code += "uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;";
+ }
+
if (features[FEATURE_NORMAL_MAPPING]) {
code += "uniform sampler2D texture_normal : hint_roughness_normal," + texfilter_str + ";\n";
code += "uniform float normal_scale : hint_range(-16,16);\n";
@@ -1228,7 +1236,7 @@ void BaseMaterial3D::_update_shader() {
code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n";
}
code += " float ref_amount = 1.0 - albedo.a * albedo_tex.a;\n";
- code += " EMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n";
+ code += " EMISSION += textureLod(screen_texture,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n";
code += " ALBEDO *= 1.0 - ref_amount;\n";
code += " ALPHA = 1.0;\n";
@@ -1246,7 +1254,7 @@ void BaseMaterial3D::_update_shader() {
}
if (proximity_fade_enabled) {
- code += " float depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n";
+ code += " float depth_tex = textureLod(depth_texture,SCREEN_UV,0.0).r;\n";
code += " vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex,1.0);\n";
code += " world_pos.xyz/=world_pos.w;\n";
code += " ALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n";
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 5e18b5df37..cedf4319f8 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -687,6 +687,7 @@ void Mesh::_bind_methods() {
BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_2D_VERTICES);
BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_DYNAMIC_UPDATE);
BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
+ BIND_BITFIELD_FLAG(ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
@@ -1555,6 +1556,7 @@ void ArrayMesh::_recompute_aabb() {
// TODO: Need to add binding to add_surface using future MeshSurfaceData object.
void ArrayMesh::add_surface(BitField<ArrayFormat> p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, const Vector<uint8_t> &p_attribute_array, const Vector<uint8_t> &p_skin_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<uint8_t> &p_blend_shape_data, const Vector<AABB> &p_bone_aabbs, const Vector<RS::SurfaceData::LOD> &p_lods) {
+ ERR_FAIL_COND(surfaces.size() == RS::MAX_MESH_SURFACES);
_create_if_empty();
Surface s;
@@ -1590,6 +1592,7 @@ void ArrayMesh::add_surface(BitField<ArrayFormat> p_format, PrimitiveType p_prim
}
void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const TypedArray<Array> &p_blend_shapes, const Dictionary &p_lods, BitField<ArrayFormat> p_flags) {
+ ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size());
ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX);
RS::SurfaceData surface;
@@ -2058,7 +2061,7 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode);
ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode);
- ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0));
ClassDB::bind_method(D_METHOD("clear_surfaces"), &ArrayMesh::clear_surfaces);
ClassDB::bind_method(D_METHOD("surface_update_vertex_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_vertex_region);
ClassDB::bind_method(D_METHOD("surface_update_attribute_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_attribute_region);
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 5ef66a22b6..86ed0001dd 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -2901,7 +2901,7 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
- Array stt;
+ TypedArray<Vector3i> stt;
if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) {
GDVIRTUAL_CALL(_structured_text_parser, st_args, txt, stt);
} else {
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 22cd12b004..e62f26b17c 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -622,7 +622,7 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const override;
public:
- GDVIRTUAL2RC(Array, _structured_text_parser, Array, String)
+ GDVIRTUAL2RC(TypedArray<Vector3i>, _structured_text_parser, Array, String)
TextMesh();
~TextMesh();
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 80b9ff3f38..2e8b4f93be 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -49,10 +49,6 @@
///
-void ResourceLoaderText::set_local_path(const String &p_local_path) {
- res_path = p_local_path;
-}
-
Ref<Resource> ResourceLoaderText::get_resource() {
return resource;
}
@@ -1846,6 +1842,9 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
List<Variant> keys;
d.get_key_list(&keys);
for (const Variant &E : keys) {
+ // Of course keys should also be cached, after all we can't prevent users from using resources as keys, right?
+ // See also ResourceFormatSaverBinaryInstance::_find_resources (when p_variant is of type Variant::DICTIONARY)
+ _find_resources(E);
Variant v = d[E];
_find_resources(v);
}
diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h
index 0f95e2fbfd..0cced3d20c 100644
--- a/scene/resources/resource_format_text.h
+++ b/scene/resources/resource_format_text.h
@@ -115,7 +115,6 @@ class ResourceLoaderText {
Ref<PackedScene> _parse_node_tag(VariantParser::ResourceParser &parser);
public:
- void set_local_path(const String &p_local_path);
Ref<Resource> get_resource();
Error load();
Error set_uid(Ref<FileAccess> p_f, ResourceUID::ID p_uid);
diff --git a/scene/resources/skeleton_modification_3d.cpp b/scene/resources/skeleton_modification_3d.cpp
deleted file mode 100644
index 92fb4bfd78..0000000000
--- a/scene/resources/skeleton_modification_3d.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "skeleton_modification_3d.h"
-#include "scene/3d/skeleton_3d.h"
-
-void SkeletonModification3D::_execute(real_t p_delta) {
- GDVIRTUAL_CALL(_execute, p_delta);
-
- if (!enabled) {
- return;
- }
-}
-
-void SkeletonModification3D::_setup_modification(SkeletonModificationStack3D *p_stack) {
- stack = p_stack;
- if (stack) {
- is_setup = true;
- } else {
- WARN_PRINT("Could not setup modification with name " + this->get_name());
- }
-
- GDVIRTUAL_CALL(_setup_modification, Ref<SkeletonModificationStack3D>(p_stack));
-}
-
-void SkeletonModification3D::set_enabled(bool p_enabled) {
- enabled = p_enabled;
-}
-
-bool SkeletonModification3D::get_enabled() {
- return enabled;
-}
-
-// Helper function. Needed for CCDIK.
-real_t SkeletonModification3D::clamp_angle(real_t p_angle, real_t p_min_bound, real_t p_max_bound, bool p_invert) {
- // Map to the 0 to 360 range (in radians though) instead of the -180 to 180 range.
- if (p_angle < 0) {
- p_angle = Math_TAU + p_angle;
- }
-
- // Make min and max in the range of 0 to 360 (in radians), and make sure they are in the right order
- if (p_min_bound < 0) {
- p_min_bound = Math_TAU + p_min_bound;
- }
- if (p_max_bound < 0) {
- p_max_bound = Math_TAU + p_max_bound;
- }
- if (p_min_bound > p_max_bound) {
- SWAP(p_min_bound, p_max_bound);
- }
-
- bool is_beyond_bounds = (p_angle < p_min_bound || p_angle > p_max_bound);
- bool is_within_bounds = (p_angle > p_min_bound && p_angle < p_max_bound);
-
- // Note: May not be the most optimal way to clamp, but it always constraints to the nearest angle.
- if ((!p_invert && is_beyond_bounds) || (p_invert && is_within_bounds)) {
- Vector2 min_bound_vec = Vector2(Math::cos(p_min_bound), Math::sin(p_min_bound));
- Vector2 max_bound_vec = Vector2(Math::cos(p_max_bound), Math::sin(p_max_bound));
- Vector2 angle_vec = Vector2(Math::cos(p_angle), Math::sin(p_angle));
-
- if (angle_vec.distance_squared_to(min_bound_vec) <= angle_vec.distance_squared_to(max_bound_vec)) {
- p_angle = p_min_bound;
- } else {
- p_angle = p_max_bound;
- }
- }
-
- return p_angle;
-}
-
-bool SkeletonModification3D::_print_execution_error(bool p_condition, String p_message) {
- // If the modification is not setup, don't bother printing the error
- if (!is_setup) {
- return p_condition;
- }
-
- if (p_condition && !execution_error_found) {
- ERR_PRINT(p_message);
- execution_error_found = true;
- }
- return p_condition;
-}
-
-Ref<SkeletonModificationStack3D> SkeletonModification3D::get_modification_stack() {
- return stack;
-}
-
-void SkeletonModification3D::set_is_setup(bool p_is_setup) {
- is_setup = p_is_setup;
-}
-
-bool SkeletonModification3D::get_is_setup() const {
- return is_setup;
-}
-
-void SkeletonModification3D::set_execution_mode(int p_mode) {
- execution_mode = p_mode;
-}
-
-int SkeletonModification3D::get_execution_mode() const {
- return execution_mode;
-}
-
-void SkeletonModification3D::_bind_methods() {
- GDVIRTUAL_BIND(_execute, "delta");
- GDVIRTUAL_BIND(_setup_modification, "modification_stack")
-
- ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &SkeletonModification3D::set_enabled);
- ClassDB::bind_method(D_METHOD("get_enabled"), &SkeletonModification3D::get_enabled);
- ClassDB::bind_method(D_METHOD("get_modification_stack"), &SkeletonModification3D::get_modification_stack);
- ClassDB::bind_method(D_METHOD("set_is_setup", "is_setup"), &SkeletonModification3D::set_is_setup);
- ClassDB::bind_method(D_METHOD("get_is_setup"), &SkeletonModification3D::get_is_setup);
- ClassDB::bind_method(D_METHOD("set_execution_mode", "execution_mode"), &SkeletonModification3D::set_execution_mode);
- ClassDB::bind_method(D_METHOD("get_execution_mode"), &SkeletonModification3D::get_execution_mode);
- ClassDB::bind_method(D_METHOD("clamp_angle", "angle", "min", "max", "invert"), &SkeletonModification3D::clamp_angle);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "execution_mode", PROPERTY_HINT_ENUM, "process,physics_process"), "set_execution_mode", "get_execution_mode");
-}
-
-SkeletonModification3D::SkeletonModification3D() {
- stack = nullptr;
- is_setup = false;
-}
diff --git a/scene/resources/skeleton_modification_3d.h b/scene/resources/skeleton_modification_3d.h
deleted file mode 100644
index 367adbd977..0000000000
--- a/scene/resources/skeleton_modification_3d.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef SKELETON_MODIFICATION_3D_H
-#define SKELETON_MODIFICATION_3D_H
-
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_stack_3d.h"
-
-class SkeletonModificationStack3D;
-
-class SkeletonModification3D : public Resource {
- GDCLASS(SkeletonModification3D, Resource);
- friend class Skeleton3D;
- friend class SkeletonModificationStack3D;
-
-protected:
- static void _bind_methods();
-
- SkeletonModificationStack3D *stack = nullptr;
- int execution_mode = 0; // 0 = process
-
- bool enabled = true;
- bool is_setup = false;
- bool execution_error_found = false;
-
- bool _print_execution_error(bool p_condition, String p_message);
-
- GDVIRTUAL1(_execute, double)
- GDVIRTUAL1(_setup_modification, Ref<SkeletonModificationStack3D>)
-
-public:
- virtual void _execute(real_t p_delta);
- virtual void _setup_modification(SkeletonModificationStack3D *p_stack);
-
- real_t clamp_angle(real_t p_angle, real_t p_min_bound, real_t p_max_bound, bool p_invert);
-
- void set_enabled(bool p_enabled);
- bool get_enabled();
-
- void set_execution_mode(int p_mode);
- int get_execution_mode() const;
-
- Ref<SkeletonModificationStack3D> get_modification_stack();
-
- void set_is_setup(bool p_setup);
- bool get_is_setup() const;
-
- SkeletonModification3D();
-};
-
-#endif // SKELETON_MODIFICATION_3D_H
diff --git a/scene/resources/skeleton_modification_3d_ccdik.cpp b/scene/resources/skeleton_modification_3d_ccdik.cpp
deleted file mode 100644
index b5c930f970..0000000000
--- a/scene/resources/skeleton_modification_3d_ccdik.cpp
+++ /dev/null
@@ -1,474 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_ccdik.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "scene/resources/skeleton_modification_3d_ccdik.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-bool SkeletonModification3DCCDIK::_set(const StringName &p_path, const Variant &p_value) {
- String path = p_path;
-
- if (path.begins_with("joint_data/")) {
- int ccdik_data_size = ccdik_data_chain.size();
- int which = path.get_slicec('/', 1).to_int();
- String what = path.get_slicec('/', 2);
- ERR_FAIL_INDEX_V(which, ccdik_data_size, false);
-
- if (what == "bone_name") {
- set_ccdik_joint_bone_name(which, p_value);
- } else if (what == "bone_index") {
- set_ccdik_joint_bone_index(which, p_value);
- } else if (what == "ccdik_axis") {
- set_ccdik_joint_ccdik_axis(which, p_value);
- } else if (what == "enable_joint_constraint") {
- set_ccdik_joint_enable_constraint(which, p_value);
- } else if (what == "joint_constraint_angle_min") {
- set_ccdik_joint_constraint_angle_min(which, Math::deg_to_rad(real_t(p_value)));
- } else if (what == "joint_constraint_angle_max") {
- set_ccdik_joint_constraint_angle_max(which, Math::deg_to_rad(real_t(p_value)));
- } else if (what == "joint_constraint_angles_invert") {
- set_ccdik_joint_constraint_invert(which, p_value);
- }
- return true;
- }
- return true;
-}
-
-bool SkeletonModification3DCCDIK::_get(const StringName &p_path, Variant &r_ret) const {
- String path = p_path;
-
- if (path.begins_with("joint_data/")) {
- const int ccdik_data_size = ccdik_data_chain.size();
- int which = path.get_slicec('/', 1).to_int();
- String what = path.get_slicec('/', 2);
- ERR_FAIL_INDEX_V(which, ccdik_data_size, false);
-
- if (what == "bone_name") {
- r_ret = get_ccdik_joint_bone_name(which);
- } else if (what == "bone_index") {
- r_ret = get_ccdik_joint_bone_index(which);
- } else if (what == "ccdik_axis") {
- r_ret = get_ccdik_joint_ccdik_axis(which);
- } else if (what == "enable_joint_constraint") {
- r_ret = get_ccdik_joint_enable_constraint(which);
- } else if (what == "joint_constraint_angle_min") {
- r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_min(which));
- } else if (what == "joint_constraint_angle_max") {
- r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_max(which));
- } else if (what == "joint_constraint_angles_invert") {
- r_ret = get_ccdik_joint_constraint_invert(which);
- }
- return true;
- }
- return true;
-}
-
-void SkeletonModification3DCCDIK::_get_property_list(List<PropertyInfo> *p_list) const {
- for (uint32_t i = 0; i < ccdik_data_chain.size(); i++) {
- String base_string = "joint_data/" + itos(i) + "/";
-
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, base_string + "bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
-
- p_list->push_back(PropertyInfo(Variant::INT, base_string + "ccdik_axis",
- PROPERTY_HINT_ENUM, "X Axis,Y Axis,Z Axis", PROPERTY_USAGE_DEFAULT));
-
- p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "enable_joint_constraint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- if (ccdik_data_chain[i].enable_constraint) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "joint_constraint_angle_min", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "joint_constraint_angle_max", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "joint_constraint_angles_invert", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- }
- }
-}
-
-void SkeletonModification3DCCDIK::_execute(real_t p_delta) {
- ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
- "Modification is not setup and therefore cannot execute!");
- if (!enabled) {
- return;
- }
-
- if (target_node_cache.is_null()) {
- _print_execution_error(true, "Target cache is out of date. Attempting to update");
- update_target_cache();
- return;
- }
- if (tip_node_cache.is_null()) {
- _print_execution_error(true, "Tip cache is out of date. Attempting to update");
- update_tip_cache();
- return;
- }
-
- // Reset the local bone overrides for CCDIK affected nodes
- for (uint32_t i = 0; i < ccdik_data_chain.size(); i++) {
- stack->skeleton->set_bone_local_pose_override(ccdik_data_chain[i].bone_idx,
- stack->skeleton->get_bone_local_pose_override(ccdik_data_chain[i].bone_idx),
- 0.0, false);
- }
-
- Node3D *node_target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
- Node3D *node_tip = Object::cast_to<Node3D>(ObjectDB::get_instance(tip_node_cache));
-
- if (_print_execution_error(!node_target || !node_target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
- return;
- }
- if (_print_execution_error(!node_tip || !node_tip->is_inside_tree(), "Tip node is not in the scene tree. Cannot execute modification!")) {
- return;
- }
-
- if (use_high_quality_solve) {
- for (uint32_t i = 0; i < ccdik_data_chain.size(); i++) {
- for (uint32_t j = i; j < ccdik_data_chain.size(); j++) {
- _execute_ccdik_joint(j, node_target, node_tip);
- }
- }
- } else {
- for (uint32_t i = 0; i < ccdik_data_chain.size(); i++) {
- _execute_ccdik_joint(i, node_target, node_tip);
- }
- }
-
- execution_error_found = false;
-}
-
-void SkeletonModification3DCCDIK::_execute_ccdik_joint(int p_joint_idx, Node3D *p_target, Node3D *p_tip) {
- CCDIK_Joint_Data ccdik_data = ccdik_data_chain[p_joint_idx];
-
- if (_print_execution_error(ccdik_data.bone_idx < 0 || ccdik_data.bone_idx > stack->skeleton->get_bone_count(),
- "CCDIK joint: bone index for joint" + itos(p_joint_idx) + " not found. Cannot execute modification!")) {
- return;
- }
-
- Transform3D bone_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->get_bone_global_pose(ccdik_data.bone_idx));
- Transform3D tip_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->world_transform_to_global_pose(p_tip->get_global_transform()));
- Transform3D target_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->world_transform_to_global_pose(p_target->get_global_transform()));
-
- if (tip_trans.origin.distance_to(target_trans.origin) <= 0.01) {
- return;
- }
-
- // Inspired (and very loosely based on) by the CCDIK algorithm made by Zalo on GitHub (https://github.com/zalo/MathUtilities)
- // Convert the 3D position to a 2D position so we can use Atan2 (via the angle function)
- // to know how much rotation we need on the given axis to place the tip at the target.
- Vector2 tip_pos_2d;
- Vector2 target_pos_2d;
- if (ccdik_data.ccdik_axis == CCDIK_Axes::AXIS_X) {
- tip_pos_2d = Vector2(tip_trans.origin.y, tip_trans.origin.z);
- target_pos_2d = Vector2(target_trans.origin.y, target_trans.origin.z);
- bone_trans.basis.rotate_local(Vector3(1, 0, 0), target_pos_2d.angle() - tip_pos_2d.angle());
- } else if (ccdik_data.ccdik_axis == CCDIK_Axes::AXIS_Y) {
- tip_pos_2d = Vector2(tip_trans.origin.z, tip_trans.origin.x);
- target_pos_2d = Vector2(target_trans.origin.z, target_trans.origin.x);
- bone_trans.basis.rotate_local(Vector3(0, 1, 0), target_pos_2d.angle() - tip_pos_2d.angle());
- } else if (ccdik_data.ccdik_axis == CCDIK_Axes::AXIS_Z) {
- tip_pos_2d = Vector2(tip_trans.origin.x, tip_trans.origin.y);
- target_pos_2d = Vector2(target_trans.origin.x, target_trans.origin.y);
- bone_trans.basis.rotate_local(Vector3(0, 0, 1), target_pos_2d.angle() - tip_pos_2d.angle());
- } else {
- // Should never happen, but...
- ERR_FAIL_MSG("CCDIK joint: Unknown axis vector passed for joint" + itos(p_joint_idx) + ". Cannot execute modification!");
- }
-
- if (ccdik_data.enable_constraint) {
- Vector3 rotation_axis;
- real_t rotation_angle;
- bone_trans.basis.get_axis_angle(rotation_axis, rotation_angle);
-
- // Note: When the axis has a negative direction, the angle is OVER 180 degrees and therefore we need to account for this
- // when constraining.
- if (ccdik_data.ccdik_axis == CCDIK_Axes::AXIS_X) {
- if (rotation_axis.x < 0) {
- rotation_angle += Math_PI;
- rotation_axis = Vector3(1, 0, 0);
- }
- } else if (ccdik_data.ccdik_axis == CCDIK_Axes::AXIS_Y) {
- if (rotation_axis.y < 0) {
- rotation_angle += Math_PI;
- rotation_axis = Vector3(0, 1, 0);
- }
- } else if (ccdik_data.ccdik_axis == CCDIK_Axes::AXIS_Z) {
- if (rotation_axis.z < 0) {
- rotation_angle += Math_PI;
- rotation_axis = Vector3(0, 0, 1);
- }
- } else {
- // Should never happen, but...
- ERR_FAIL_MSG("CCDIK joint: Unknown axis vector passed for joint" + itos(p_joint_idx) + ". Cannot execute modification!");
- }
- rotation_angle = clamp_angle(rotation_angle, ccdik_data.constraint_angle_min, ccdik_data.constraint_angle_max, ccdik_data.constraint_angles_invert);
-
- bone_trans.basis.set_axis_angle(rotation_axis, rotation_angle);
- }
-
- stack->skeleton->set_bone_local_pose_override(ccdik_data.bone_idx, bone_trans, stack->strength, true);
- stack->skeleton->force_update_bone_children_transforms(ccdik_data.bone_idx);
-}
-
-void SkeletonModification3DCCDIK::_setup_modification(SkeletonModificationStack3D *p_stack) {
- stack = p_stack;
- if (stack != nullptr) {
- is_setup = true;
- execution_error_found = false;
- update_target_cache();
- update_tip_cache();
- }
-}
-
-void SkeletonModification3DCCDIK::update_target_cache() {
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update target cache: modification is not properly setup!");
- return;
- }
-
- target_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree()) {
- if (stack->skeleton->has_node(target_node)) {
- Node *node = stack->skeleton->get_node(target_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update target cache: node is this modification's skeleton or cannot be found!");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update target cache: node is not in scene tree!");
- target_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DCCDIK::update_tip_cache() {
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update tip cache: modification is not properly setup!");
- return;
- }
-
- tip_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree()) {
- if (stack->skeleton->has_node(tip_node)) {
- Node *node = stack->skeleton->get_node(tip_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update tip cache: node is this modification's skeleton or cannot be found!");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update tip cache: node is not in scene tree!");
- tip_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DCCDIK::set_target_node(const NodePath &p_target_node) {
- target_node = p_target_node;
- update_target_cache();
-}
-
-NodePath SkeletonModification3DCCDIK::get_target_node() const {
- return target_node;
-}
-
-void SkeletonModification3DCCDIK::set_tip_node(const NodePath &p_tip_node) {
- tip_node = p_tip_node;
- update_tip_cache();
-}
-
-NodePath SkeletonModification3DCCDIK::get_tip_node() const {
- return tip_node;
-}
-
-void SkeletonModification3DCCDIK::set_use_high_quality_solve(bool p_high_quality) {
- use_high_quality_solve = p_high_quality;
-}
-
-bool SkeletonModification3DCCDIK::get_use_high_quality_solve() const {
- return use_high_quality_solve;
-}
-
-// CCDIK joint data functions
-String SkeletonModification3DCCDIK::get_ccdik_joint_bone_name(int p_joint_idx) const {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, String());
- return ccdik_data_chain[p_joint_idx].bone_name;
-}
-
-void SkeletonModification3DCCDIK::set_ccdik_joint_bone_name(int p_joint_idx, String p_bone_name) {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ccdik_data_chain[p_joint_idx].bone_name = p_bone_name;
-
- if (stack) {
- if (stack->skeleton) {
- ccdik_data_chain[p_joint_idx].bone_idx = stack->skeleton->find_bone(p_bone_name);
- }
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-int SkeletonModification3DCCDIK::get_ccdik_joint_bone_index(int p_joint_idx) const {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, -1);
- return ccdik_data_chain[p_joint_idx].bone_idx;
-}
-
-void SkeletonModification3DCCDIK::set_ccdik_joint_bone_index(int p_joint_idx, int p_bone_idx) {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
- ccdik_data_chain[p_joint_idx].bone_idx = p_bone_idx;
-
- if (stack) {
- if (stack->skeleton) {
- ccdik_data_chain[p_joint_idx].bone_name = stack->skeleton->get_bone_name(p_bone_idx);
- }
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-int SkeletonModification3DCCDIK::get_ccdik_joint_ccdik_axis(int p_joint_idx) const {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, -1);
- return ccdik_data_chain[p_joint_idx].ccdik_axis;
-}
-
-void SkeletonModification3DCCDIK::set_ccdik_joint_ccdik_axis(int p_joint_idx, int p_axis) {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ERR_FAIL_COND_MSG(p_axis < 0, "CCDIK axis is out of range: The axis mode is too low!");
- ccdik_data_chain[p_joint_idx].ccdik_axis = p_axis;
- notify_property_list_changed();
-}
-
-bool SkeletonModification3DCCDIK::get_ccdik_joint_enable_constraint(int p_joint_idx) const {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return ccdik_data_chain[p_joint_idx].enable_constraint;
-}
-
-void SkeletonModification3DCCDIK::set_ccdik_joint_enable_constraint(int p_joint_idx, bool p_enable) {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ccdik_data_chain[p_joint_idx].enable_constraint = p_enable;
- notify_property_list_changed();
-}
-
-real_t SkeletonModification3DCCDIK::get_ccdik_joint_constraint_angle_min(int p_joint_idx) const {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return ccdik_data_chain[p_joint_idx].constraint_angle_min;
-}
-
-void SkeletonModification3DCCDIK::set_ccdik_joint_constraint_angle_min(int p_joint_idx, real_t p_angle_min) {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ccdik_data_chain[p_joint_idx].constraint_angle_min = p_angle_min;
-}
-
-real_t SkeletonModification3DCCDIK::get_ccdik_joint_constraint_angle_max(int p_joint_idx) const {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return ccdik_data_chain[p_joint_idx].constraint_angle_max;
-}
-
-void SkeletonModification3DCCDIK::set_ccdik_joint_constraint_angle_max(int p_joint_idx, real_t p_angle_max) {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ccdik_data_chain[p_joint_idx].constraint_angle_max = p_angle_max;
-}
-
-bool SkeletonModification3DCCDIK::get_ccdik_joint_constraint_invert(int p_joint_idx) const {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return ccdik_data_chain[p_joint_idx].constraint_angles_invert;
-}
-
-void SkeletonModification3DCCDIK::set_ccdik_joint_constraint_invert(int p_joint_idx, bool p_invert) {
- const int bone_chain_size = ccdik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ccdik_data_chain[p_joint_idx].constraint_angles_invert = p_invert;
-}
-
-int SkeletonModification3DCCDIK::get_ccdik_data_chain_length() {
- return ccdik_data_chain.size();
-}
-void SkeletonModification3DCCDIK::set_ccdik_data_chain_length(int p_length) {
- ERR_FAIL_COND(p_length < 0);
- ccdik_data_chain.resize(p_length);
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-void SkeletonModification3DCCDIK::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification3DCCDIK::set_target_node);
- ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification3DCCDIK::get_target_node);
-
- ClassDB::bind_method(D_METHOD("set_tip_node", "tip_nodepath"), &SkeletonModification3DCCDIK::set_tip_node);
- ClassDB::bind_method(D_METHOD("get_tip_node"), &SkeletonModification3DCCDIK::get_tip_node);
-
- ClassDB::bind_method(D_METHOD("set_use_high_quality_solve", "high_quality_solve"), &SkeletonModification3DCCDIK::set_use_high_quality_solve);
- ClassDB::bind_method(D_METHOD("get_use_high_quality_solve"), &SkeletonModification3DCCDIK::get_use_high_quality_solve);
-
- // CCDIK joint data functions
- ClassDB::bind_method(D_METHOD("get_ccdik_joint_bone_name", "joint_idx"), &SkeletonModification3DCCDIK::get_ccdik_joint_bone_name);
- ClassDB::bind_method(D_METHOD("set_ccdik_joint_bone_name", "joint_idx", "bone_name"), &SkeletonModification3DCCDIK::set_ccdik_joint_bone_name);
- ClassDB::bind_method(D_METHOD("get_ccdik_joint_bone_index", "joint_idx"), &SkeletonModification3DCCDIK::get_ccdik_joint_bone_index);
- ClassDB::bind_method(D_METHOD("set_ccdik_joint_bone_index", "joint_idx", "bone_index"), &SkeletonModification3DCCDIK::set_ccdik_joint_bone_index);
- ClassDB::bind_method(D_METHOD("get_ccdik_joint_ccdik_axis", "joint_idx"), &SkeletonModification3DCCDIK::get_ccdik_joint_ccdik_axis);
- ClassDB::bind_method(D_METHOD("set_ccdik_joint_ccdik_axis", "joint_idx", "axis"), &SkeletonModification3DCCDIK::set_ccdik_joint_ccdik_axis);
- ClassDB::bind_method(D_METHOD("get_ccdik_joint_enable_joint_constraint", "joint_idx"), &SkeletonModification3DCCDIK::get_ccdik_joint_enable_constraint);
- ClassDB::bind_method(D_METHOD("set_ccdik_joint_enable_joint_constraint", "joint_idx", "enable"), &SkeletonModification3DCCDIK::set_ccdik_joint_enable_constraint);
- ClassDB::bind_method(D_METHOD("get_ccdik_joint_constraint_angle_min", "joint_idx"), &SkeletonModification3DCCDIK::get_ccdik_joint_constraint_angle_min);
- ClassDB::bind_method(D_METHOD("set_ccdik_joint_constraint_angle_min", "joint_idx", "min_angle"), &SkeletonModification3DCCDIK::set_ccdik_joint_constraint_angle_min);
- ClassDB::bind_method(D_METHOD("get_ccdik_joint_constraint_angle_max", "joint_idx"), &SkeletonModification3DCCDIK::get_ccdik_joint_constraint_angle_max);
- ClassDB::bind_method(D_METHOD("set_ccdik_joint_constraint_angle_max", "joint_idx", "max_angle"), &SkeletonModification3DCCDIK::set_ccdik_joint_constraint_angle_max);
- ClassDB::bind_method(D_METHOD("get_ccdik_joint_constraint_invert", "joint_idx"), &SkeletonModification3DCCDIK::get_ccdik_joint_constraint_invert);
- ClassDB::bind_method(D_METHOD("set_ccdik_joint_constraint_invert", "joint_idx", "invert"), &SkeletonModification3DCCDIK::set_ccdik_joint_constraint_invert);
-
- ClassDB::bind_method(D_METHOD("set_ccdik_data_chain_length", "length"), &SkeletonModification3DCCDIK::set_ccdik_data_chain_length);
- ClassDB::bind_method(D_METHOD("get_ccdik_data_chain_length"), &SkeletonModification3DCCDIK::get_ccdik_data_chain_length);
-
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "tip_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_tip_node", "get_tip_node");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "high_quality_solve", PROPERTY_HINT_NONE, ""), "set_use_high_quality_solve", "get_use_high_quality_solve");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "ccdik_data_chain_length", PROPERTY_HINT_RANGE, "0,100,1"), "set_ccdik_data_chain_length", "get_ccdik_data_chain_length");
-}
-
-SkeletonModification3DCCDIK::SkeletonModification3DCCDIK() {
- stack = nullptr;
- is_setup = false;
- enabled = true;
-}
-
-SkeletonModification3DCCDIK::~SkeletonModification3DCCDIK() {
-}
diff --git a/scene/resources/skeleton_modification_3d_ccdik.h b/scene/resources/skeleton_modification_3d_ccdik.h
deleted file mode 100644
index 30c29bb3aa..0000000000
--- a/scene/resources/skeleton_modification_3d_ccdik.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_ccdik.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef SKELETON_MODIFICATION_3D_CCDIK_H
-#define SKELETON_MODIFICATION_3D_CCDIK_H
-
-#include "core/templates/local_vector.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-class SkeletonModification3DCCDIK : public SkeletonModification3D {
- GDCLASS(SkeletonModification3DCCDIK, SkeletonModification3D);
-
-private:
- enum CCDIK_Axes {
- AXIS_X,
- AXIS_Y,
- AXIS_Z
- };
-
- struct CCDIK_Joint_Data {
- String bone_name = "";
- int bone_idx = -1;
- int ccdik_axis = 0;
-
- bool enable_constraint = false;
- real_t constraint_angle_min = 0;
- real_t constraint_angle_max = (2.0 * Math_PI);
- bool constraint_angles_invert = false;
- };
-
- LocalVector<CCDIK_Joint_Data> ccdik_data_chain;
- NodePath target_node;
- ObjectID target_node_cache;
-
- NodePath tip_node;
- ObjectID tip_node_cache;
-
- bool use_high_quality_solve = true;
-
- void update_target_cache();
- void update_tip_cache();
-
- void _execute_ccdik_joint(int p_joint_idx, Node3D *p_target, Node3D *p_tip);
-
-protected:
- static void _bind_methods();
- bool _get(const StringName &p_path, Variant &r_ret) const;
- bool _set(const StringName &p_path, const Variant &p_value);
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
-public:
- virtual void _execute(real_t p_delta) override;
- virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
-
- void set_target_node(const NodePath &p_target_node);
- NodePath get_target_node() const;
-
- void set_tip_node(const NodePath &p_tip_node);
- NodePath get_tip_node() const;
-
- void set_use_high_quality_solve(bool p_solve);
- bool get_use_high_quality_solve() const;
-
- String get_ccdik_joint_bone_name(int p_joint_idx) const;
- void set_ccdik_joint_bone_name(int p_joint_idx, String p_bone_name);
- int get_ccdik_joint_bone_index(int p_joint_idx) const;
- void set_ccdik_joint_bone_index(int p_joint_idx, int p_bone_idx);
- int get_ccdik_joint_ccdik_axis(int p_joint_idx) const;
- void set_ccdik_joint_ccdik_axis(int p_joint_idx, int p_axis);
- bool get_ccdik_joint_enable_constraint(int p_joint_idx) const;
- void set_ccdik_joint_enable_constraint(int p_joint_idx, bool p_enable);
- real_t get_ccdik_joint_constraint_angle_min(int p_joint_idx) const;
- void set_ccdik_joint_constraint_angle_min(int p_joint_idx, real_t p_angle_min);
- real_t get_ccdik_joint_constraint_angle_max(int p_joint_idx) const;
- void set_ccdik_joint_constraint_angle_max(int p_joint_idx, real_t p_angle_max);
- bool get_ccdik_joint_constraint_invert(int p_joint_idx) const;
- void set_ccdik_joint_constraint_invert(int p_joint_idx, bool p_invert);
-
- int get_ccdik_data_chain_length();
- void set_ccdik_data_chain_length(int p_new_length);
-
- SkeletonModification3DCCDIK();
- ~SkeletonModification3DCCDIK();
-};
-
-#endif // SKELETON_MODIFICATION_3D_CCDIK_H
diff --git a/scene/resources/skeleton_modification_3d_fabrik.cpp b/scene/resources/skeleton_modification_3d_fabrik.cpp
deleted file mode 100644
index 9fb7ade155..0000000000
--- a/scene/resources/skeleton_modification_3d_fabrik.cpp
+++ /dev/null
@@ -1,628 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_fabrik.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "scene/resources/skeleton_modification_3d_fabrik.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-bool SkeletonModification3DFABRIK::_set(const StringName &p_path, const Variant &p_value) {
- String path = p_path;
-
- if (path.begins_with("joint_data/")) {
- int fabrik_data_size = fabrik_data_chain.size();
- int which = path.get_slicec('/', 1).to_int();
- String what = path.get_slicec('/', 2);
- ERR_FAIL_INDEX_V(which, fabrik_data_size, false);
-
- if (what == "bone_name") {
- set_fabrik_joint_bone_name(which, p_value);
- } else if (what == "bone_index") {
- set_fabrik_joint_bone_index(which, p_value);
- } else if (what == "length") {
- set_fabrik_joint_length(which, p_value);
- } else if (what == "magnet_position") {
- set_fabrik_joint_magnet(which, p_value);
- } else if (what == "auto_calculate_length") {
- set_fabrik_joint_auto_calculate_length(which, p_value);
- } else if (what == "use_tip_node") {
- set_fabrik_joint_use_tip_node(which, p_value);
- } else if (what == "tip_node") {
- set_fabrik_joint_tip_node(which, p_value);
- } else if (what == "use_target_basis") {
- set_fabrik_joint_use_target_basis(which, p_value);
- } else if (what == "roll") {
- set_fabrik_joint_roll(which, Math::deg_to_rad(real_t(p_value)));
- }
- return true;
- }
- return true;
-}
-
-bool SkeletonModification3DFABRIK::_get(const StringName &p_path, Variant &r_ret) const {
- String path = p_path;
-
- if (path.begins_with("joint_data/")) {
- const int fabrik_data_size = fabrik_data_chain.size();
- int which = path.get_slicec('/', 1).to_int();
- String what = path.get_slicec('/', 2);
- ERR_FAIL_INDEX_V(which, fabrik_data_size, false);
-
- if (what == "bone_name") {
- r_ret = get_fabrik_joint_bone_name(which);
- } else if (what == "bone_index") {
- r_ret = get_fabrik_joint_bone_index(which);
- } else if (what == "length") {
- r_ret = get_fabrik_joint_length(which);
- } else if (what == "magnet_position") {
- r_ret = get_fabrik_joint_magnet(which);
- } else if (what == "auto_calculate_length") {
- r_ret = get_fabrik_joint_auto_calculate_length(which);
- } else if (what == "use_tip_node") {
- r_ret = get_fabrik_joint_use_tip_node(which);
- } else if (what == "tip_node") {
- r_ret = get_fabrik_joint_tip_node(which);
- } else if (what == "use_target_basis") {
- r_ret = get_fabrik_joint_use_target_basis(which);
- } else if (what == "roll") {
- r_ret = Math::rad_to_deg(get_fabrik_joint_roll(which));
- }
- return true;
- }
- return true;
-}
-
-void SkeletonModification3DFABRIK::_get_property_list(List<PropertyInfo> *p_list) const {
- for (uint32_t i = 0; i < fabrik_data_chain.size(); i++) {
- String base_string = "joint_data/" + itos(i) + "/";
-
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, base_string + "bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "roll", PROPERTY_HINT_RANGE, "-360,360,0.01", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "auto_calculate_length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
-
- if (!fabrik_data_chain[i].auto_calculate_length) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- } else {
- p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "use_tip_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- if (fabrik_data_chain[i].use_tip_node) {
- p_list->push_back(PropertyInfo(Variant::NODE_PATH, base_string + "tip_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D", PROPERTY_USAGE_DEFAULT));
- }
- }
-
- // Cannot apply magnet to the origin of the chain, as it will not do anything.
- if (i > 0) {
- p_list->push_back(PropertyInfo(Variant::VECTOR3, base_string + "magnet_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- }
- // Only give the override basis option on the last bone in the chain, so only include it for the last bone.
- if (i == fabrik_data_chain.size() - 1) {
- p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "use_target_basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- }
- }
-}
-
-void SkeletonModification3DFABRIK::_execute(real_t p_delta) {
- ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
- "Modification is not setup and therefore cannot execute!");
- if (!enabled) {
- return;
- }
-
- if (target_node_cache.is_null()) {
- _print_execution_error(true, "Target cache is out of date. Attempting to update...");
- update_target_cache();
- return;
- }
-
- if (_print_execution_error(fabrik_data_chain.size() <= 1, "FABRIK requires at least two joints to operate. Cannot execute modification!")) {
- return;
- }
-
- Node3D *node_target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
- if (_print_execution_error(!node_target || !node_target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
- return;
- }
-
- // Make sure the transform cache is the correct size
- if (fabrik_transforms.size() != fabrik_data_chain.size()) {
- fabrik_transforms.resize(fabrik_data_chain.size());
- }
-
- // Verify that all joints have a valid bone ID, and that all bone lengths are zero or more
- // Also, while we are here, apply magnet positions.
- for (uint32_t i = 0; i < fabrik_data_chain.size(); i++) {
- if (_print_execution_error(fabrik_data_chain[i].bone_idx < 0, "FABRIK Joint " + itos(i) + " has an invalid bone ID. Cannot execute!")) {
- return;
- }
-
- if (fabrik_data_chain[i].length < 0 && fabrik_data_chain[i].auto_calculate_length) {
- fabrik_joint_auto_calculate_length(i);
- }
- if (_print_execution_error(fabrik_data_chain[i].length < 0, "FABRIK Joint " + itos(i) + " has an invalid joint length. Cannot execute!")) {
- return;
- }
- fabrik_transforms[i] = stack->skeleton->get_bone_global_pose(fabrik_data_chain[i].bone_idx);
-
- // Apply magnet positions:
- if (stack->skeleton->get_bone_parent(fabrik_data_chain[i].bone_idx) >= 0) {
- int parent_bone_idx = stack->skeleton->get_bone_parent(fabrik_data_chain[i].bone_idx);
- Transform3D conversion_transform = (stack->skeleton->get_bone_global_pose(parent_bone_idx));
- fabrik_transforms[i].origin += conversion_transform.basis.xform_inv(fabrik_data_chain[i].magnet_position);
- } else {
- fabrik_transforms[i].origin += fabrik_data_chain[i].magnet_position;
- }
- }
- Transform3D origin_global_pose_trans = stack->skeleton->get_bone_global_pose_no_override(fabrik_data_chain[0].bone_idx);
-
- target_global_pose = stack->skeleton->world_transform_to_global_pose(node_target->get_global_transform());
- origin_global_pose = origin_global_pose_trans;
-
- final_joint_idx = fabrik_data_chain.size() - 1;
- real_t target_distance = fabrik_transforms[final_joint_idx].origin.distance_to(target_global_pose.origin);
- chain_iterations = 0;
-
- while (target_distance > chain_tolerance) {
- chain_backwards();
- chain_forwards();
-
- // update the target distance
- target_distance = fabrik_transforms[final_joint_idx].origin.distance_to(target_global_pose.origin);
-
- // update chain iterations
- chain_iterations += 1;
- if (chain_iterations >= chain_max_iterations) {
- break;
- }
- }
- chain_apply();
-
- execution_error_found = false;
-}
-
-void SkeletonModification3DFABRIK::chain_backwards() {
- int final_bone_idx = fabrik_data_chain[final_joint_idx].bone_idx;
- Transform3D final_joint_trans = fabrik_transforms[final_joint_idx];
-
- // Get the direction the final bone is facing in.
- stack->skeleton->update_bone_rest_forward_vector(final_bone_idx);
- Transform3D final_bone_direction_trans = final_joint_trans.looking_at(target_global_pose.origin, Vector3(0, 1, 0));
- final_bone_direction_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(final_bone_idx, final_bone_direction_trans.basis);
- Vector3 direction = final_bone_direction_trans.basis.xform(stack->skeleton->get_bone_axis_forward_vector(final_bone_idx)).normalized();
-
- // If set to override, then use the target's Basis rather than the bone's
- if (fabrik_data_chain[final_joint_idx].use_target_basis) {
- direction = target_global_pose.basis.xform(stack->skeleton->get_bone_axis_forward_vector(final_bone_idx)).normalized();
- }
-
- // set the position of the final joint to the target position
- final_joint_trans.origin = target_global_pose.origin - (direction * fabrik_data_chain[final_joint_idx].length);
- fabrik_transforms[final_joint_idx] = final_joint_trans;
-
- // for all other joints, move them towards the target
- int i = final_joint_idx;
- while (i >= 1) {
- Transform3D next_bone_trans = fabrik_transforms[i];
- i -= 1;
- Transform3D current_trans = fabrik_transforms[i];
-
- real_t length = fabrik_data_chain[i].length / (current_trans.origin.distance_to(next_bone_trans.origin));
- current_trans.origin = next_bone_trans.origin.lerp(current_trans.origin, length);
-
- // Save the result
- fabrik_transforms[i] = current_trans;
- }
-}
-
-void SkeletonModification3DFABRIK::chain_forwards() {
- // Set root at the initial position.
- Transform3D root_transform = fabrik_transforms[0];
-
- root_transform.origin = origin_global_pose.origin;
- fabrik_transforms[0] = origin_global_pose;
-
- for (uint32_t i = 0; i < fabrik_data_chain.size() - 1; i++) {
- Transform3D current_trans = fabrik_transforms[i];
- Transform3D next_bone_trans = fabrik_transforms[i + 1];
-
- real_t length = fabrik_data_chain[i].length / (next_bone_trans.origin.distance_to(current_trans.origin));
- next_bone_trans.origin = current_trans.origin.lerp(next_bone_trans.origin, length);
-
- // Save the result
- fabrik_transforms[i + 1] = next_bone_trans;
- }
-}
-
-void SkeletonModification3DFABRIK::chain_apply() {
- for (uint32_t i = 0; i < fabrik_data_chain.size(); i++) {
- int current_bone_idx = fabrik_data_chain[i].bone_idx;
- Transform3D current_trans = fabrik_transforms[i];
-
- // If this is the last bone in the chain...
- if (i == fabrik_data_chain.size() - 1) {
- if (fabrik_data_chain[i].use_target_basis == false) { // Point to target...
- // Get the forward direction that the basis is facing in right now.
- stack->skeleton->update_bone_rest_forward_vector(current_bone_idx);
- Vector3 forward_vector = stack->skeleton->get_bone_axis_forward_vector(current_bone_idx);
- // Rotate the bone towards the target:
- current_trans.basis.rotate_to_align(forward_vector, current_trans.origin.direction_to(target_global_pose.origin));
- current_trans.basis.rotate_local(forward_vector, fabrik_data_chain[i].roll);
- } else { // Use the target's Basis...
- current_trans.basis = target_global_pose.basis.orthonormalized().scaled(current_trans.basis.get_scale());
- }
- } else { // every other bone in the chain...
- Transform3D next_trans = fabrik_transforms[i + 1];
-
- // Get the forward direction that the basis is facing in right now.
- stack->skeleton->update_bone_rest_forward_vector(current_bone_idx);
- Vector3 forward_vector = stack->skeleton->get_bone_axis_forward_vector(current_bone_idx);
- // Rotate the bone towards the next bone in the chain:
- current_trans.basis.rotate_to_align(forward_vector, current_trans.origin.direction_to(next_trans.origin));
- current_trans.basis.rotate_local(forward_vector, fabrik_data_chain[i].roll);
- }
- stack->skeleton->set_bone_local_pose_override(current_bone_idx, stack->skeleton->global_pose_to_local_pose(current_bone_idx, current_trans), stack->strength, true);
- }
-
- // Update all the bones so the next modification has up-to-date data.
- stack->skeleton->force_update_all_bone_transforms();
-}
-
-void SkeletonModification3DFABRIK::_setup_modification(SkeletonModificationStack3D *p_stack) {
- stack = p_stack;
- if (stack != nullptr) {
- is_setup = true;
- execution_error_found = false;
- update_target_cache();
-
- for (uint32_t i = 0; i < fabrik_data_chain.size(); i++) {
- update_joint_tip_cache(i);
- }
- }
-}
-
-void SkeletonModification3DFABRIK::update_target_cache() {
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update target cache: modification is not properly setup!");
- return;
- }
- target_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree() && target_node.is_empty() == false) {
- if (stack->skeleton->has_node(target_node)) {
- Node *node = stack->skeleton->get_node(target_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update target cache: node is this modification's skeleton or cannot be found!");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update target cache: node is not in the scene tree!");
- target_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DFABRIK::update_joint_tip_cache(int p_joint_idx) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_MSG(p_joint_idx, bone_chain_size, "FABRIK joint not found");
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update tip cache: modification is not properly setup!");
- return;
- }
- fabrik_data_chain[p_joint_idx].tip_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree() && fabrik_data_chain[p_joint_idx].tip_node.is_empty() == false) {
- if (stack->skeleton->has_node(fabrik_data_chain[p_joint_idx].tip_node)) {
- Node *node = stack->skeleton->get_node(fabrik_data_chain[p_joint_idx].tip_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update tip cache for joint " + itos(p_joint_idx) + ": node is this modification's skeleton or cannot be found!");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update tip cache for joint " + itos(p_joint_idx) + ": node is not in scene tree!");
- fabrik_data_chain[p_joint_idx].tip_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DFABRIK::set_target_node(const NodePath &p_target_node) {
- target_node = p_target_node;
- update_target_cache();
-}
-
-NodePath SkeletonModification3DFABRIK::get_target_node() const {
- return target_node;
-}
-
-int SkeletonModification3DFABRIK::get_fabrik_data_chain_length() {
- return fabrik_data_chain.size();
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_data_chain_length(int p_length) {
- ERR_FAIL_COND(p_length < 0);
- fabrik_data_chain.resize(p_length);
- fabrik_transforms.resize(p_length);
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-real_t SkeletonModification3DFABRIK::get_chain_tolerance() {
- return chain_tolerance;
-}
-
-void SkeletonModification3DFABRIK::set_chain_tolerance(real_t p_tolerance) {
- ERR_FAIL_COND_MSG(p_tolerance <= 0, "FABRIK chain tolerance must be more than zero!");
- chain_tolerance = p_tolerance;
-}
-
-int SkeletonModification3DFABRIK::get_chain_max_iterations() {
- return chain_max_iterations;
-}
-void SkeletonModification3DFABRIK::set_chain_max_iterations(int p_iterations) {
- ERR_FAIL_COND_MSG(p_iterations <= 0, "FABRIK chain iterations must be at least one. Set enabled to false to disable the FABRIK chain.");
- chain_max_iterations = p_iterations;
-}
-
-// FABRIK joint data functions
-String SkeletonModification3DFABRIK::get_fabrik_joint_bone_name(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, String());
- return fabrik_data_chain[p_joint_idx].bone_name;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_bone_name(int p_joint_idx, String p_bone_name) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- fabrik_data_chain[p_joint_idx].bone_name = p_bone_name;
-
- if (stack) {
- if (stack->skeleton) {
- fabrik_data_chain[p_joint_idx].bone_idx = stack->skeleton->find_bone(p_bone_name);
- }
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-int SkeletonModification3DFABRIK::get_fabrik_joint_bone_index(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, -1);
- return fabrik_data_chain[p_joint_idx].bone_idx;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_bone_index(int p_joint_idx, int p_bone_idx) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
- fabrik_data_chain[p_joint_idx].bone_idx = p_bone_idx;
-
- if (stack) {
- if (stack->skeleton) {
- fabrik_data_chain[p_joint_idx].bone_name = stack->skeleton->get_bone_name(p_bone_idx);
- }
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-real_t SkeletonModification3DFABRIK::get_fabrik_joint_length(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, -1);
- return fabrik_data_chain[p_joint_idx].length;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_length(int p_joint_idx, real_t p_bone_length) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ERR_FAIL_COND_MSG(p_bone_length < 0, "FABRIK joint length cannot be less than zero!");
-
- if (!is_setup) {
- fabrik_data_chain[p_joint_idx].length = p_bone_length;
- return;
- }
-
- if (fabrik_data_chain[p_joint_idx].auto_calculate_length) {
- WARN_PRINT("FABRIK Length not set: auto calculate length is enabled for this joint!");
- fabrik_joint_auto_calculate_length(p_joint_idx);
- } else {
- fabrik_data_chain[p_joint_idx].length = p_bone_length;
- }
-
- execution_error_found = false;
-}
-
-Vector3 SkeletonModification3DFABRIK::get_fabrik_joint_magnet(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, Vector3());
- return fabrik_data_chain[p_joint_idx].magnet_position;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_magnet(int p_joint_idx, Vector3 p_magnet) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- fabrik_data_chain[p_joint_idx].magnet_position = p_magnet;
-}
-
-bool SkeletonModification3DFABRIK::get_fabrik_joint_auto_calculate_length(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return fabrik_data_chain[p_joint_idx].auto_calculate_length;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_auto_calculate_length(int p_joint_idx, bool p_auto_calculate) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- fabrik_data_chain[p_joint_idx].auto_calculate_length = p_auto_calculate;
- fabrik_joint_auto_calculate_length(p_joint_idx);
- notify_property_list_changed();
-}
-
-void SkeletonModification3DFABRIK::fabrik_joint_auto_calculate_length(int p_joint_idx) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- if (!fabrik_data_chain[p_joint_idx].auto_calculate_length) {
- return;
- }
-
- if (!stack || !stack->skeleton || !is_setup) {
- _print_execution_error(true, "Cannot auto calculate joint length: modification is not properly setup!");
- return;
- }
- ERR_FAIL_INDEX_MSG(fabrik_data_chain[p_joint_idx].bone_idx, stack->skeleton->get_bone_count(),
- "Bone for joint " + itos(p_joint_idx) + " is not set or points to an unknown bone!");
-
- if (fabrik_data_chain[p_joint_idx].use_tip_node) { // Use the tip node to update joint length.
-
- update_joint_tip_cache(p_joint_idx);
-
- Node3D *tip_node = Object::cast_to<Node3D>(ObjectDB::get_instance(fabrik_data_chain[p_joint_idx].tip_node_cache));
- ERR_FAIL_COND_MSG(!tip_node, "Tip node for joint " + itos(p_joint_idx) + "is not a Node3D-based node. Cannot calculate length...");
- ERR_FAIL_COND_MSG(!tip_node->is_inside_tree(), "Tip node for joint " + itos(p_joint_idx) + "is not in the scene tree. Cannot calculate length...");
-
- Transform3D node_trans = tip_node->get_global_transform();
- node_trans = stack->skeleton->world_transform_to_global_pose(node_trans);
- //node_trans = stack->skeleton->global_pose_to_local_pose(fabrik_data_chain[p_joint_idx].bone_idx, node_trans);
- //fabrik_data_chain[p_joint_idx].length = node_trans.origin.length();
-
- fabrik_data_chain[p_joint_idx].length = stack->skeleton->get_bone_global_pose(fabrik_data_chain[p_joint_idx].bone_idx).origin.distance_to(node_trans.origin);
-
- } else { // Use child bone(s) to update joint length, if possible
- Vector<int> bone_children = stack->skeleton->get_bone_children(fabrik_data_chain[p_joint_idx].bone_idx);
- if (bone_children.size() <= 0) {
- ERR_FAIL_MSG("Cannot calculate length for joint " + itos(p_joint_idx) + "joint uses leaf bone. \nPlease manually set the bone length or use a tip node!");
- return;
- }
-
- Transform3D bone_trans = stack->skeleton->get_bone_global_pose(fabrik_data_chain[p_joint_idx].bone_idx);
-
- real_t final_length = 0;
- for (int i = 0; i < bone_children.size(); i++) {
- Transform3D child_transform = stack->skeleton->get_bone_global_pose(bone_children[i]);
- final_length += bone_trans.origin.distance_to(child_transform.origin);
- //final_length += stack->skeleton->global_pose_to_local_pose(fabrik_data_chain[p_joint_idx].bone_idx, child_transform).origin.length();
- }
- fabrik_data_chain[p_joint_idx].length = final_length / bone_children.size();
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-bool SkeletonModification3DFABRIK::get_fabrik_joint_use_tip_node(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return fabrik_data_chain[p_joint_idx].use_tip_node;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_use_tip_node(int p_joint_idx, bool p_use_tip_node) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- fabrik_data_chain[p_joint_idx].use_tip_node = p_use_tip_node;
- notify_property_list_changed();
-}
-
-NodePath SkeletonModification3DFABRIK::get_fabrik_joint_tip_node(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, NodePath());
- return fabrik_data_chain[p_joint_idx].tip_node;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_tip_node(int p_joint_idx, NodePath p_tip_node) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- fabrik_data_chain[p_joint_idx].tip_node = p_tip_node;
- update_joint_tip_cache(p_joint_idx);
-}
-
-bool SkeletonModification3DFABRIK::get_fabrik_joint_use_target_basis(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return fabrik_data_chain[p_joint_idx].use_target_basis;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_use_target_basis(int p_joint_idx, bool p_use_target_basis) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- fabrik_data_chain[p_joint_idx].use_target_basis = p_use_target_basis;
-}
-
-real_t SkeletonModification3DFABRIK::get_fabrik_joint_roll(int p_joint_idx) const {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, 0.0);
- return fabrik_data_chain[p_joint_idx].roll;
-}
-
-void SkeletonModification3DFABRIK::set_fabrik_joint_roll(int p_joint_idx, real_t p_roll) {
- const int bone_chain_size = fabrik_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- fabrik_data_chain[p_joint_idx].roll = p_roll;
-}
-
-void SkeletonModification3DFABRIK::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification3DFABRIK::set_target_node);
- ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification3DFABRIK::get_target_node);
- ClassDB::bind_method(D_METHOD("set_fabrik_data_chain_length", "length"), &SkeletonModification3DFABRIK::set_fabrik_data_chain_length);
- ClassDB::bind_method(D_METHOD("get_fabrik_data_chain_length"), &SkeletonModification3DFABRIK::get_fabrik_data_chain_length);
- ClassDB::bind_method(D_METHOD("set_chain_tolerance", "tolerance"), &SkeletonModification3DFABRIK::set_chain_tolerance);
- ClassDB::bind_method(D_METHOD("get_chain_tolerance"), &SkeletonModification3DFABRIK::get_chain_tolerance);
- ClassDB::bind_method(D_METHOD("set_chain_max_iterations", "max_iterations"), &SkeletonModification3DFABRIK::set_chain_max_iterations);
- ClassDB::bind_method(D_METHOD("get_chain_max_iterations"), &SkeletonModification3DFABRIK::get_chain_max_iterations);
-
- // FABRIK joint data functions
- ClassDB::bind_method(D_METHOD("get_fabrik_joint_bone_name", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_bone_name);
- ClassDB::bind_method(D_METHOD("set_fabrik_joint_bone_name", "joint_idx", "bone_name"), &SkeletonModification3DFABRIK::set_fabrik_joint_bone_name);
- ClassDB::bind_method(D_METHOD("get_fabrik_joint_bone_index", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_bone_index);
- ClassDB::bind_method(D_METHOD("set_fabrik_joint_bone_index", "joint_idx", "bone_index"), &SkeletonModification3DFABRIK::set_fabrik_joint_bone_index);
- ClassDB::bind_method(D_METHOD("get_fabrik_joint_length", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_length);
- ClassDB::bind_method(D_METHOD("set_fabrik_joint_length", "joint_idx", "length"), &SkeletonModification3DFABRIK::set_fabrik_joint_length);
- ClassDB::bind_method(D_METHOD("get_fabrik_joint_magnet", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_magnet);
- ClassDB::bind_method(D_METHOD("set_fabrik_joint_magnet", "joint_idx", "magnet_position"), &SkeletonModification3DFABRIK::set_fabrik_joint_magnet);
- ClassDB::bind_method(D_METHOD("get_fabrik_joint_auto_calculate_length", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_auto_calculate_length);
- ClassDB::bind_method(D_METHOD("set_fabrik_joint_auto_calculate_length", "joint_idx", "auto_calculate_length"), &SkeletonModification3DFABRIK::set_fabrik_joint_auto_calculate_length);
- ClassDB::bind_method(D_METHOD("fabrik_joint_auto_calculate_length", "joint_idx"), &SkeletonModification3DFABRIK::fabrik_joint_auto_calculate_length);
- ClassDB::bind_method(D_METHOD("get_fabrik_joint_use_tip_node", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_use_tip_node);
- ClassDB::bind_method(D_METHOD("set_fabrik_joint_use_tip_node", "joint_idx", "use_tip_node"), &SkeletonModification3DFABRIK::set_fabrik_joint_use_tip_node);
- ClassDB::bind_method(D_METHOD("get_fabrik_joint_tip_node", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_tip_node);
- ClassDB::bind_method(D_METHOD("set_fabrik_joint_tip_node", "joint_idx", "tip_node"), &SkeletonModification3DFABRIK::set_fabrik_joint_tip_node);
- ClassDB::bind_method(D_METHOD("get_fabrik_joint_use_target_basis", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_use_target_basis);
- ClassDB::bind_method(D_METHOD("set_fabrik_joint_use_target_basis", "joint_idx", "use_target_basis"), &SkeletonModification3DFABRIK::set_fabrik_joint_use_target_basis);
-
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "fabrik_data_chain_length", PROPERTY_HINT_RANGE, "0,100,1"), "set_fabrik_data_chain_length", "get_fabrik_data_chain_length");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "chain_tolerance", PROPERTY_HINT_RANGE, "0,100,0.001"), "set_chain_tolerance", "get_chain_tolerance");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "chain_max_iterations", PROPERTY_HINT_RANGE, "1,50,1"), "set_chain_max_iterations", "get_chain_max_iterations");
-}
-
-SkeletonModification3DFABRIK::SkeletonModification3DFABRIK() {
- stack = nullptr;
- is_setup = false;
- enabled = true;
-}
-
-SkeletonModification3DFABRIK::~SkeletonModification3DFABRIK() {
-}
diff --git a/scene/resources/skeleton_modification_3d_fabrik.h b/scene/resources/skeleton_modification_3d_fabrik.h
deleted file mode 100644
index c834658093..0000000000
--- a/scene/resources/skeleton_modification_3d_fabrik.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_fabrik.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef SKELETON_MODIFICATION_3D_FABRIK_H
-#define SKELETON_MODIFICATION_3D_FABRIK_H
-
-#include "core/templates/local_vector.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-class SkeletonModification3DFABRIK : public SkeletonModification3D {
- GDCLASS(SkeletonModification3DFABRIK, SkeletonModification3D);
-
-private:
- struct FABRIK_Joint_Data {
- String bone_name = "";
- int bone_idx = -1;
- real_t length = -1;
- Vector3 magnet_position = Vector3(0, 0, 0);
-
- bool auto_calculate_length = true;
- bool use_tip_node = false;
- NodePath tip_node;
- ObjectID tip_node_cache;
-
- bool use_target_basis = false;
- real_t roll = 0;
- };
-
- LocalVector<FABRIK_Joint_Data> fabrik_data_chain;
- LocalVector<Transform3D> fabrik_transforms;
-
- NodePath target_node;
- ObjectID target_node_cache;
-
- real_t chain_tolerance = 0.01;
- int chain_max_iterations = 10;
- int chain_iterations = 0;
-
- void update_target_cache();
- void update_joint_tip_cache(int p_joint_idx);
-
- int final_joint_idx = 0;
- Transform3D target_global_pose;
- Transform3D origin_global_pose;
-
- void chain_backwards();
- void chain_forwards();
- void chain_apply();
-
-protected:
- static void _bind_methods();
- bool _get(const StringName &p_path, Variant &r_ret) const;
- bool _set(const StringName &p_path, const Variant &p_value);
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
-public:
- virtual void _execute(real_t p_delta) override;
- virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
-
- void set_target_node(const NodePath &p_target_node);
- NodePath get_target_node() const;
-
- int get_fabrik_data_chain_length();
- void set_fabrik_data_chain_length(int p_new_length);
-
- real_t get_chain_tolerance();
- void set_chain_tolerance(real_t p_tolerance);
-
- int get_chain_max_iterations();
- void set_chain_max_iterations(int p_iterations);
-
- String get_fabrik_joint_bone_name(int p_joint_idx) const;
- void set_fabrik_joint_bone_name(int p_joint_idx, String p_bone_name);
- int get_fabrik_joint_bone_index(int p_joint_idx) const;
- void set_fabrik_joint_bone_index(int p_joint_idx, int p_bone_idx);
- real_t get_fabrik_joint_length(int p_joint_idx) const;
- void set_fabrik_joint_length(int p_joint_idx, real_t p_bone_length);
- Vector3 get_fabrik_joint_magnet(int p_joint_idx) const;
- void set_fabrik_joint_magnet(int p_joint_idx, Vector3 p_magnet);
- bool get_fabrik_joint_auto_calculate_length(int p_joint_idx) const;
- void set_fabrik_joint_auto_calculate_length(int p_joint_idx, bool p_auto_calculate);
- void fabrik_joint_auto_calculate_length(int p_joint_idx);
- bool get_fabrik_joint_use_tip_node(int p_joint_idx) const;
- void set_fabrik_joint_use_tip_node(int p_joint_idx, bool p_use_tip_node);
- NodePath get_fabrik_joint_tip_node(int p_joint_idx) const;
- void set_fabrik_joint_tip_node(int p_joint_idx, NodePath p_tip_node);
- bool get_fabrik_joint_use_target_basis(int p_joint_idx) const;
- void set_fabrik_joint_use_target_basis(int p_joint_idx, bool p_use_basis);
- real_t get_fabrik_joint_roll(int p_joint_idx) const;
- void set_fabrik_joint_roll(int p_joint_idx, real_t p_roll);
-
- SkeletonModification3DFABRIK();
- ~SkeletonModification3DFABRIK();
-};
-
-#endif // SKELETON_MODIFICATION_3D_FABRIK_H
diff --git a/scene/resources/skeleton_modification_3d_jiggle.cpp b/scene/resources/skeleton_modification_3d_jiggle.cpp
deleted file mode 100644
index 2cfc7fb10f..0000000000
--- a/scene/resources/skeleton_modification_3d_jiggle.cpp
+++ /dev/null
@@ -1,582 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_jiggle.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "scene/resources/skeleton_modification_3d_jiggle.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-bool SkeletonModification3DJiggle::_set(const StringName &p_path, const Variant &p_value) {
- String path = p_path;
-
- if (path.begins_with("joint_data/")) {
- const int jiggle_size = jiggle_data_chain.size();
- int which = path.get_slicec('/', 1).to_int();
- String what = path.get_slicec('/', 2);
- ERR_FAIL_INDEX_V(which, jiggle_size, false);
-
- if (what == "bone_name") {
- set_jiggle_joint_bone_name(which, p_value);
- } else if (what == "bone_index") {
- set_jiggle_joint_bone_index(which, p_value);
- } else if (what == "override_defaults") {
- set_jiggle_joint_override(which, p_value);
- } else if (what == "stiffness") {
- set_jiggle_joint_stiffness(which, p_value);
- } else if (what == "mass") {
- set_jiggle_joint_mass(which, p_value);
- } else if (what == "damping") {
- set_jiggle_joint_damping(which, p_value);
- } else if (what == "use_gravity") {
- set_jiggle_joint_use_gravity(which, p_value);
- } else if (what == "gravity") {
- set_jiggle_joint_gravity(which, p_value);
- } else if (what == "roll") {
- set_jiggle_joint_roll(which, Math::deg_to_rad(real_t(p_value)));
- }
- return true;
- } else {
- if (path == "use_colliders") {
- set_use_colliders(p_value);
- } else if (path == "collision_mask") {
- set_collision_mask(p_value);
- }
- return true;
- }
- return true;
-}
-
-bool SkeletonModification3DJiggle::_get(const StringName &p_path, Variant &r_ret) const {
- String path = p_path;
-
- if (path.begins_with("joint_data/")) {
- const int jiggle_size = jiggle_data_chain.size();
- int which = path.get_slicec('/', 1).to_int();
- String what = path.get_slicec('/', 2);
- ERR_FAIL_INDEX_V(which, jiggle_size, false);
-
- if (what == "bone_name") {
- r_ret = get_jiggle_joint_bone_name(which);
- } else if (what == "bone_index") {
- r_ret = get_jiggle_joint_bone_index(which);
- } else if (what == "override_defaults") {
- r_ret = get_jiggle_joint_override(which);
- } else if (what == "stiffness") {
- r_ret = get_jiggle_joint_stiffness(which);
- } else if (what == "mass") {
- r_ret = get_jiggle_joint_mass(which);
- } else if (what == "damping") {
- r_ret = get_jiggle_joint_damping(which);
- } else if (what == "use_gravity") {
- r_ret = get_jiggle_joint_use_gravity(which);
- } else if (what == "gravity") {
- r_ret = get_jiggle_joint_gravity(which);
- } else if (what == "roll") {
- r_ret = Math::rad_to_deg(get_jiggle_joint_roll(which));
- }
- return true;
- } else {
- if (path == "use_colliders") {
- r_ret = get_use_colliders();
- } else if (path == "collision_mask") {
- r_ret = get_collision_mask();
- }
- return true;
- }
- return true;
-}
-
-void SkeletonModification3DJiggle::_get_property_list(List<PropertyInfo> *p_list) const {
- p_list->push_back(PropertyInfo(Variant::BOOL, "use_colliders", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- if (use_colliders) {
- p_list->push_back(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS, "", PROPERTY_USAGE_DEFAULT));
- }
-
- for (uint32_t i = 0; i < jiggle_data_chain.size(); i++) {
- String base_string = "joint_data/" + itos(i) + "/";
-
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, base_string + "bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "roll", PROPERTY_HINT_RANGE, "-360,360,0.01", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "override_defaults", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
-
- if (jiggle_data_chain[i].override_defaults) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "stiffness", PROPERTY_HINT_RANGE, "0, 1000, 0.01", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "mass", PROPERTY_HINT_RANGE, "0, 1000, 0.01", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "damping", PROPERTY_HINT_RANGE, "0, 1, 0.01", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "use_gravity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- if (jiggle_data_chain[i].use_gravity) {
- p_list->push_back(PropertyInfo(Variant::VECTOR3, base_string + "gravity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- }
- }
- }
-}
-
-void SkeletonModification3DJiggle::_execute(real_t p_delta) {
- ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
- "Modification is not setup and therefore cannot execute!");
- if (!enabled) {
- return;
- }
- if (target_node_cache.is_null()) {
- _print_execution_error(true, "Target cache is out of date. Attempting to update...");
- update_cache();
- return;
- }
- Node3D *target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
- _print_execution_error(!target || !target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!");
-
- for (uint32_t i = 0; i < jiggle_data_chain.size(); i++) {
- _execute_jiggle_joint(i, target, p_delta);
- }
-
- execution_error_found = false;
-}
-
-void SkeletonModification3DJiggle::_execute_jiggle_joint(int p_joint_idx, Node3D *p_target, real_t p_delta) {
- // Adopted from: https://wiki.unity3d.com/index.php/JiggleBone
- // With modifications by TwistedTwigleg.
-
- if (jiggle_data_chain[p_joint_idx].bone_idx <= -2) {
- jiggle_data_chain[p_joint_idx].bone_idx = stack->skeleton->find_bone(jiggle_data_chain[p_joint_idx].bone_name);
- }
- if (_print_execution_error(
- jiggle_data_chain[p_joint_idx].bone_idx < 0 || jiggle_data_chain[p_joint_idx].bone_idx > stack->skeleton->get_bone_count(),
- "Jiggle joint " + itos(p_joint_idx) + " bone index is invalid. Cannot execute modification!")) {
- return;
- }
-
- Transform3D bone_local_pos = stack->skeleton->get_bone_local_pose_override(jiggle_data_chain[p_joint_idx].bone_idx);
- if (bone_local_pos == Transform3D()) {
- bone_local_pos = stack->skeleton->get_bone_pose(jiggle_data_chain[p_joint_idx].bone_idx);
- }
-
- Transform3D new_bone_trans = stack->skeleton->local_pose_to_global_pose(jiggle_data_chain[p_joint_idx].bone_idx, bone_local_pos);
- Vector3 target_position = stack->skeleton->world_transform_to_global_pose(p_target->get_global_transform()).origin;
-
- jiggle_data_chain[p_joint_idx].force = (target_position - jiggle_data_chain[p_joint_idx].dynamic_position) * jiggle_data_chain[p_joint_idx].stiffness * p_delta;
-
- if (jiggle_data_chain[p_joint_idx].use_gravity) {
- Vector3 gravity_to_apply = new_bone_trans.basis.inverse().xform(jiggle_data_chain[p_joint_idx].gravity);
- jiggle_data_chain[p_joint_idx].force += gravity_to_apply * p_delta;
- }
-
- jiggle_data_chain[p_joint_idx].acceleration = jiggle_data_chain[p_joint_idx].force / jiggle_data_chain[p_joint_idx].mass;
- jiggle_data_chain[p_joint_idx].velocity += jiggle_data_chain[p_joint_idx].acceleration * (1 - jiggle_data_chain[p_joint_idx].damping);
-
- jiggle_data_chain[p_joint_idx].dynamic_position += jiggle_data_chain[p_joint_idx].velocity + jiggle_data_chain[p_joint_idx].force;
- jiggle_data_chain[p_joint_idx].dynamic_position += new_bone_trans.origin - jiggle_data_chain[p_joint_idx].last_position;
- jiggle_data_chain[p_joint_idx].last_position = new_bone_trans.origin;
-
- // Collision detection/response
- if (use_colliders) {
- if (execution_mode == SkeletonModificationStack3D::EXECUTION_MODE::execution_mode_physics_process) {
- Ref<World3D> world_3d = stack->skeleton->get_world_3d();
- ERR_FAIL_COND(world_3d.is_null());
- PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world_3d->get_space());
- PhysicsDirectSpaceState3D::RayResult ray_result;
-
- // Convert to world transforms, which is what the physics server needs
- Transform3D new_bone_trans_world = stack->skeleton->global_pose_to_world_transform(new_bone_trans);
- Transform3D dynamic_position_world = stack->skeleton->global_pose_to_world_transform(Transform3D(Basis(), jiggle_data_chain[p_joint_idx].dynamic_position));
-
- PhysicsDirectSpaceState3D::RayParameters ray_params;
- ray_params.from = new_bone_trans_world.origin;
- ray_params.to = dynamic_position_world.get_origin();
- ray_params.collision_mask = collision_mask;
-
- bool ray_hit = space_state->intersect_ray(ray_params, ray_result);
-
- if (ray_hit) {
- jiggle_data_chain[p_joint_idx].dynamic_position = jiggle_data_chain[p_joint_idx].last_noncollision_position;
- jiggle_data_chain[p_joint_idx].acceleration = Vector3(0, 0, 0);
- jiggle_data_chain[p_joint_idx].velocity = Vector3(0, 0, 0);
- } else {
- jiggle_data_chain[p_joint_idx].last_noncollision_position = jiggle_data_chain[p_joint_idx].dynamic_position;
- }
-
- } else {
- WARN_PRINT_ONCE("Jiggle modifier: You cannot detect colliders without the stack mode being set to _physics_process!");
- }
- }
-
- // Get the forward direction that the basis is facing in right now.
- stack->skeleton->update_bone_rest_forward_vector(jiggle_data_chain[p_joint_idx].bone_idx);
- Vector3 forward_vector = stack->skeleton->get_bone_axis_forward_vector(jiggle_data_chain[p_joint_idx].bone_idx);
-
- // Rotate the bone using the dynamic position!
- new_bone_trans.basis.rotate_to_align(forward_vector, new_bone_trans.origin.direction_to(jiggle_data_chain[p_joint_idx].dynamic_position));
-
- // Roll
- new_bone_trans.basis.rotate_local(forward_vector, jiggle_data_chain[p_joint_idx].roll);
-
- new_bone_trans = stack->skeleton->global_pose_to_local_pose(jiggle_data_chain[p_joint_idx].bone_idx, new_bone_trans);
- stack->skeleton->set_bone_local_pose_override(jiggle_data_chain[p_joint_idx].bone_idx, new_bone_trans, stack->strength, true);
- stack->skeleton->force_update_bone_children_transforms(jiggle_data_chain[p_joint_idx].bone_idx);
-}
-
-void SkeletonModification3DJiggle::_update_jiggle_joint_data() {
- for (uint32_t i = 0; i < jiggle_data_chain.size(); i++) {
- if (!jiggle_data_chain[i].override_defaults) {
- set_jiggle_joint_stiffness(i, stiffness);
- set_jiggle_joint_mass(i, mass);
- set_jiggle_joint_damping(i, damping);
- set_jiggle_joint_use_gravity(i, use_gravity);
- set_jiggle_joint_gravity(i, gravity);
- }
- }
-}
-
-void SkeletonModification3DJiggle::_setup_modification(SkeletonModificationStack3D *p_stack) {
- stack = p_stack;
-
- if (stack) {
- is_setup = true;
- execution_error_found = false;
-
- if (stack->skeleton) {
- for (uint32_t i = 0; i < jiggle_data_chain.size(); i++) {
- int bone_idx = jiggle_data_chain[i].bone_idx;
- if (bone_idx > 0 && bone_idx < stack->skeleton->get_bone_count()) {
- jiggle_data_chain[i].dynamic_position = stack->skeleton->local_pose_to_global_pose(bone_idx, stack->skeleton->get_bone_local_pose_override(bone_idx)).origin;
- }
- }
- }
-
- update_cache();
- }
-}
-
-void SkeletonModification3DJiggle::update_cache() {
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update target cache: modification is not properly setup!");
- return;
- }
-
- target_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree()) {
- if (stack->skeleton->has_node(target_node)) {
- Node *node = stack->skeleton->get_node(target_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update target cache: node is this modification's skeleton or cannot be found!");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update target cache: node is not in the scene tree!");
- target_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DJiggle::set_target_node(const NodePath &p_target_node) {
- target_node = p_target_node;
- update_cache();
-}
-
-NodePath SkeletonModification3DJiggle::get_target_node() const {
- return target_node;
-}
-
-void SkeletonModification3DJiggle::set_stiffness(real_t p_stiffness) {
- ERR_FAIL_COND_MSG(p_stiffness < 0, "Stiffness cannot be set to a negative value!");
- stiffness = p_stiffness;
- _update_jiggle_joint_data();
-}
-
-real_t SkeletonModification3DJiggle::get_stiffness() const {
- return stiffness;
-}
-
-void SkeletonModification3DJiggle::set_mass(real_t p_mass) {
- ERR_FAIL_COND_MSG(p_mass < 0, "Mass cannot be set to a negative value!");
- mass = p_mass;
- _update_jiggle_joint_data();
-}
-
-real_t SkeletonModification3DJiggle::get_mass() const {
- return mass;
-}
-
-void SkeletonModification3DJiggle::set_damping(real_t p_damping) {
- ERR_FAIL_COND_MSG(p_damping < 0, "Damping cannot be set to a negative value!");
- ERR_FAIL_COND_MSG(p_damping > 1, "Damping cannot be more than one!");
- damping = p_damping;
- _update_jiggle_joint_data();
-}
-
-real_t SkeletonModification3DJiggle::get_damping() const {
- return damping;
-}
-
-void SkeletonModification3DJiggle::set_use_gravity(bool p_use_gravity) {
- use_gravity = p_use_gravity;
- _update_jiggle_joint_data();
-}
-
-bool SkeletonModification3DJiggle::get_use_gravity() const {
- return use_gravity;
-}
-
-void SkeletonModification3DJiggle::set_gravity(Vector3 p_gravity) {
- gravity = p_gravity;
- _update_jiggle_joint_data();
-}
-
-Vector3 SkeletonModification3DJiggle::get_gravity() const {
- return gravity;
-}
-
-void SkeletonModification3DJiggle::set_use_colliders(bool p_use_collider) {
- use_colliders = p_use_collider;
- notify_property_list_changed();
-}
-
-bool SkeletonModification3DJiggle::get_use_colliders() const {
- return use_colliders;
-}
-
-void SkeletonModification3DJiggle::set_collision_mask(int p_mask) {
- collision_mask = p_mask;
-}
-
-int SkeletonModification3DJiggle::get_collision_mask() const {
- return collision_mask;
-}
-
-// Jiggle joint data functions
-int SkeletonModification3DJiggle::get_jiggle_data_chain_length() {
- return jiggle_data_chain.size();
-}
-
-void SkeletonModification3DJiggle::set_jiggle_data_chain_length(int p_length) {
- ERR_FAIL_COND(p_length < 0);
- jiggle_data_chain.resize(p_length);
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_bone_name(int p_joint_idx, String p_name) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
-
- jiggle_data_chain[p_joint_idx].bone_name = p_name;
- if (stack && stack->skeleton) {
- jiggle_data_chain[p_joint_idx].bone_idx = stack->skeleton->find_bone(p_name);
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-String SkeletonModification3DJiggle::get_jiggle_joint_bone_name(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, "");
- return jiggle_data_chain[p_joint_idx].bone_name;
-}
-
-int SkeletonModification3DJiggle::get_jiggle_joint_bone_index(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, -1);
- return jiggle_data_chain[p_joint_idx].bone_idx;
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_bone_index(int p_joint_idx, int p_bone_idx) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
- jiggle_data_chain[p_joint_idx].bone_idx = p_bone_idx;
-
- if (stack) {
- if (stack->skeleton) {
- jiggle_data_chain[p_joint_idx].bone_name = stack->skeleton->get_bone_name(p_bone_idx);
- }
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_override(int p_joint_idx, bool p_override) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- jiggle_data_chain[p_joint_idx].override_defaults = p_override;
- _update_jiggle_joint_data();
- notify_property_list_changed();
-}
-
-bool SkeletonModification3DJiggle::get_jiggle_joint_override(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return jiggle_data_chain[p_joint_idx].override_defaults;
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_stiffness(int p_joint_idx, real_t p_stiffness) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_COND_MSG(p_stiffness < 0, "Stiffness cannot be set to a negative value!");
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- jiggle_data_chain[p_joint_idx].stiffness = p_stiffness;
-}
-
-real_t SkeletonModification3DJiggle::get_jiggle_joint_stiffness(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, -1);
- return jiggle_data_chain[p_joint_idx].stiffness;
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_mass(int p_joint_idx, real_t p_mass) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_COND_MSG(p_mass < 0, "Mass cannot be set to a negative value!");
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- jiggle_data_chain[p_joint_idx].mass = p_mass;
-}
-
-real_t SkeletonModification3DJiggle::get_jiggle_joint_mass(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, -1);
- return jiggle_data_chain[p_joint_idx].mass;
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_damping(int p_joint_idx, real_t p_damping) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_COND_MSG(p_damping < 0, "Damping cannot be set to a negative value!");
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- jiggle_data_chain[p_joint_idx].damping = p_damping;
-}
-
-real_t SkeletonModification3DJiggle::get_jiggle_joint_damping(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, -1);
- return jiggle_data_chain[p_joint_idx].damping;
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_use_gravity(int p_joint_idx, bool p_use_gravity) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- jiggle_data_chain[p_joint_idx].use_gravity = p_use_gravity;
- notify_property_list_changed();
-}
-
-bool SkeletonModification3DJiggle::get_jiggle_joint_use_gravity(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, false);
- return jiggle_data_chain[p_joint_idx].use_gravity;
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_gravity(int p_joint_idx, Vector3 p_gravity) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- jiggle_data_chain[p_joint_idx].gravity = p_gravity;
-}
-
-Vector3 SkeletonModification3DJiggle::get_jiggle_joint_gravity(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, Vector3(0, 0, 0));
- return jiggle_data_chain[p_joint_idx].gravity;
-}
-
-void SkeletonModification3DJiggle::set_jiggle_joint_roll(int p_joint_idx, real_t p_roll) {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
- jiggle_data_chain[p_joint_idx].roll = p_roll;
-}
-
-real_t SkeletonModification3DJiggle::get_jiggle_joint_roll(int p_joint_idx) const {
- const int bone_chain_size = jiggle_data_chain.size();
- ERR_FAIL_INDEX_V(p_joint_idx, bone_chain_size, 0.0);
- return jiggle_data_chain[p_joint_idx].roll;
-}
-
-void SkeletonModification3DJiggle::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification3DJiggle::set_target_node);
- ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification3DJiggle::get_target_node);
-
- ClassDB::bind_method(D_METHOD("set_jiggle_data_chain_length", "length"), &SkeletonModification3DJiggle::set_jiggle_data_chain_length);
- ClassDB::bind_method(D_METHOD("get_jiggle_data_chain_length"), &SkeletonModification3DJiggle::get_jiggle_data_chain_length);
-
- ClassDB::bind_method(D_METHOD("set_stiffness", "stiffness"), &SkeletonModification3DJiggle::set_stiffness);
- ClassDB::bind_method(D_METHOD("get_stiffness"), &SkeletonModification3DJiggle::get_stiffness);
- ClassDB::bind_method(D_METHOD("set_mass", "mass"), &SkeletonModification3DJiggle::set_mass);
- ClassDB::bind_method(D_METHOD("get_mass"), &SkeletonModification3DJiggle::get_mass);
- ClassDB::bind_method(D_METHOD("set_damping", "damping"), &SkeletonModification3DJiggle::set_damping);
- ClassDB::bind_method(D_METHOD("get_damping"), &SkeletonModification3DJiggle::get_damping);
- ClassDB::bind_method(D_METHOD("set_use_gravity", "use_gravity"), &SkeletonModification3DJiggle::set_use_gravity);
- ClassDB::bind_method(D_METHOD("get_use_gravity"), &SkeletonModification3DJiggle::get_use_gravity);
- ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &SkeletonModification3DJiggle::set_gravity);
- ClassDB::bind_method(D_METHOD("get_gravity"), &SkeletonModification3DJiggle::get_gravity);
-
- ClassDB::bind_method(D_METHOD("set_use_colliders", "use_colliders"), &SkeletonModification3DJiggle::set_use_colliders);
- ClassDB::bind_method(D_METHOD("get_use_colliders"), &SkeletonModification3DJiggle::get_use_colliders);
- ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &SkeletonModification3DJiggle::set_collision_mask);
- ClassDB::bind_method(D_METHOD("get_collision_mask"), &SkeletonModification3DJiggle::get_collision_mask);
-
- // Jiggle joint data functions
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_bone_name", "joint_idx", "name"), &SkeletonModification3DJiggle::set_jiggle_joint_bone_name);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_bone_name", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_bone_name);
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_bone_index", "joint_idx", "bone_idx"), &SkeletonModification3DJiggle::set_jiggle_joint_bone_index);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_bone_index", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_bone_index);
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_override", "joint_idx", "override"), &SkeletonModification3DJiggle::set_jiggle_joint_override);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_override", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_override);
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_stiffness", "joint_idx", "stiffness"), &SkeletonModification3DJiggle::set_jiggle_joint_stiffness);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_stiffness", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_stiffness);
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_mass", "joint_idx", "mass"), &SkeletonModification3DJiggle::set_jiggle_joint_mass);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_mass", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_mass);
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_damping", "joint_idx", "damping"), &SkeletonModification3DJiggle::set_jiggle_joint_damping);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_damping", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_damping);
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_use_gravity", "joint_idx", "use_gravity"), &SkeletonModification3DJiggle::set_jiggle_joint_use_gravity);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_use_gravity", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_use_gravity);
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_gravity", "joint_idx", "gravity"), &SkeletonModification3DJiggle::set_jiggle_joint_gravity);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_gravity", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_gravity);
- ClassDB::bind_method(D_METHOD("set_jiggle_joint_roll", "joint_idx", "roll"), &SkeletonModification3DJiggle::set_jiggle_joint_roll);
- ClassDB::bind_method(D_METHOD("get_jiggle_joint_roll", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_roll);
-
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "jiggle_data_chain_length", PROPERTY_HINT_RANGE, "0,100,1"), "set_jiggle_data_chain_length", "get_jiggle_data_chain_length");
- ADD_GROUP("Default Joint Settings", "");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness"), "set_stiffness", "get_stiffness");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0, 1, 0.01"), "set_damping", "get_damping");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_gravity"), "set_use_gravity", "get_use_gravity");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity");
- ADD_GROUP("", "");
-}
-
-SkeletonModification3DJiggle::SkeletonModification3DJiggle() {
- stack = nullptr;
- is_setup = false;
- jiggle_data_chain = Vector<Jiggle_Joint_Data>();
- stiffness = 3;
- mass = 0.75;
- damping = 0.75;
- use_gravity = false;
- gravity = Vector3(0, -6.0, 0);
- enabled = true;
-}
-
-SkeletonModification3DJiggle::~SkeletonModification3DJiggle() {
-}
diff --git a/scene/resources/skeleton_modification_3d_jiggle.h b/scene/resources/skeleton_modification_3d_jiggle.h
deleted file mode 100644
index cca620a72d..0000000000
--- a/scene/resources/skeleton_modification_3d_jiggle.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_jiggle.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef SKELETON_MODIFICATION_3D_JIGGLE_H
-#define SKELETON_MODIFICATION_3D_JIGGLE_H
-
-#include "core/templates/local_vector.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-class SkeletonModification3DJiggle : public SkeletonModification3D {
- GDCLASS(SkeletonModification3DJiggle, SkeletonModification3D);
-
-private:
- struct Jiggle_Joint_Data {
- String bone_name = "";
- int bone_idx = -1;
-
- bool override_defaults = false;
- real_t stiffness = 3;
- real_t mass = 0.75;
- real_t damping = 0.75;
- bool use_gravity = false;
- Vector3 gravity = Vector3(0, -6.0, 0);
- real_t roll = 0;
-
- Vector3 cached_rotation = Vector3(0, 0, 0);
- Vector3 force = Vector3(0, 0, 0);
- Vector3 acceleration = Vector3(0, 0, 0);
- Vector3 velocity = Vector3(0, 0, 0);
- Vector3 last_position = Vector3(0, 0, 0);
- Vector3 dynamic_position = Vector3(0, 0, 0);
-
- Vector3 last_noncollision_position = Vector3(0, 0, 0);
- };
-
- NodePath target_node;
- ObjectID target_node_cache;
- LocalVector<Jiggle_Joint_Data> jiggle_data_chain;
-
- real_t stiffness = 3;
- real_t mass = 0.75;
- real_t damping = 0.75;
- bool use_gravity = false;
- Vector3 gravity = Vector3(0, -6.0, 0);
-
- bool use_colliders = false;
- uint32_t collision_mask = 1;
-
- void update_cache();
- void _execute_jiggle_joint(int p_joint_idx, Node3D *p_target, real_t p_delta);
- void _update_jiggle_joint_data();
-
-protected:
- static void _bind_methods();
- bool _get(const StringName &p_path, Variant &r_ret) const;
- bool _set(const StringName &p_path, const Variant &p_value);
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
-public:
- virtual void _execute(real_t p_delta) override;
- virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
-
- void set_target_node(const NodePath &p_target_node);
- NodePath get_target_node() const;
-
- void set_stiffness(real_t p_stiffness);
- real_t get_stiffness() const;
- void set_mass(real_t p_mass);
- real_t get_mass() const;
- void set_damping(real_t p_damping);
- real_t get_damping() const;
-
- void set_use_gravity(bool p_use_gravity);
- bool get_use_gravity() const;
- void set_gravity(Vector3 p_gravity);
- Vector3 get_gravity() const;
-
- void set_use_colliders(bool p_use_colliders);
- bool get_use_colliders() const;
- void set_collision_mask(int p_mask);
- int get_collision_mask() const;
-
- int get_jiggle_data_chain_length();
- void set_jiggle_data_chain_length(int p_new_length);
-
- void set_jiggle_joint_bone_name(int p_joint_idx, String p_name);
- String get_jiggle_joint_bone_name(int p_joint_idx) const;
- void set_jiggle_joint_bone_index(int p_joint_idx, int p_idx);
- int get_jiggle_joint_bone_index(int p_joint_idx) const;
-
- void set_jiggle_joint_override(int p_joint_idx, bool p_override);
- bool get_jiggle_joint_override(int p_joint_idx) const;
- void set_jiggle_joint_stiffness(int p_joint_idx, real_t p_stiffness);
- real_t get_jiggle_joint_stiffness(int p_joint_idx) const;
- void set_jiggle_joint_mass(int p_joint_idx, real_t p_mass);
- real_t get_jiggle_joint_mass(int p_joint_idx) const;
- void set_jiggle_joint_damping(int p_joint_idx, real_t p_damping);
- real_t get_jiggle_joint_damping(int p_joint_idx) const;
- void set_jiggle_joint_use_gravity(int p_joint_idx, bool p_use_gravity);
- bool get_jiggle_joint_use_gravity(int p_joint_idx) const;
- void set_jiggle_joint_gravity(int p_joint_idx, Vector3 p_gravity);
- Vector3 get_jiggle_joint_gravity(int p_joint_idx) const;
- void set_jiggle_joint_roll(int p_joint_idx, real_t p_roll);
- real_t get_jiggle_joint_roll(int p_joint_idx) const;
-
- SkeletonModification3DJiggle();
- ~SkeletonModification3DJiggle();
-};
-
-#endif // SKELETON_MODIFICATION_3D_JIGGLE_H
diff --git a/scene/resources/skeleton_modification_3d_lookat.cpp b/scene/resources/skeleton_modification_3d_lookat.cpp
deleted file mode 100644
index 57eedeb64e..0000000000
--- a/scene/resources/skeleton_modification_3d_lookat.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_lookat.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "scene/resources/skeleton_modification_3d_lookat.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-bool SkeletonModification3DLookAt::_set(const StringName &p_path, const Variant &p_value) {
- if (p_path == "lock_rotation_to_plane") {
- set_lock_rotation_to_plane(p_value);
- } else if (p_path == "lock_rotation_plane") {
- set_lock_rotation_plane(p_value);
- } else if (p_path == "additional_rotation") {
- Vector3 tmp = p_value;
- tmp.x = Math::deg_to_rad(tmp.x);
- tmp.y = Math::deg_to_rad(tmp.y);
- tmp.z = Math::deg_to_rad(tmp.z);
- set_additional_rotation(tmp);
- }
-
- return true;
-}
-
-bool SkeletonModification3DLookAt::_get(const StringName &p_path, Variant &r_ret) const {
- if (p_path == "lock_rotation_to_plane") {
- r_ret = get_lock_rotation_to_plane();
- } else if (p_path == "lock_rotation_plane") {
- r_ret = get_lock_rotation_plane();
- } else if (p_path == "additional_rotation") {
- Vector3 tmp = get_additional_rotation();
- tmp.x = Math::rad_to_deg(tmp.x);
- tmp.y = Math::rad_to_deg(tmp.y);
- tmp.z = Math::rad_to_deg(tmp.z);
- r_ret = tmp;
- }
-
- return true;
-}
-
-void SkeletonModification3DLookAt::_get_property_list(List<PropertyInfo> *p_list) const {
- p_list->push_back(PropertyInfo(Variant::BOOL, "lock_rotation_to_plane", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- if (lock_rotation_to_plane) {
- p_list->push_back(PropertyInfo(Variant::INT, "lock_rotation_plane", PROPERTY_HINT_ENUM, "X plane,Y plane,Z plane", PROPERTY_USAGE_DEFAULT));
- }
- p_list->push_back(PropertyInfo(Variant::VECTOR3, "additional_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
-}
-
-void SkeletonModification3DLookAt::_execute(real_t p_delta) {
- ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
- "Modification is not setup and therefore cannot execute!");
- if (!enabled) {
- return;
- }
-
- if (target_node_cache.is_null()) {
- _print_execution_error(true, "Target cache is out of date. Attempting to update...");
- update_cache();
- return;
- }
-
- if (bone_idx <= -2) {
- bone_idx = stack->skeleton->find_bone(bone_name);
- }
-
- Node3D *target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
- if (_print_execution_error(!target || !target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
- return;
- }
- if (_print_execution_error(bone_idx <= -1, "Bone index is invalid. Cannot execute modification!")) {
- return;
- }
- Transform3D new_bone_trans = stack->skeleton->get_bone_local_pose_override(bone_idx);
- if (new_bone_trans == Transform3D()) {
- new_bone_trans = stack->skeleton->get_bone_pose(bone_idx);
- }
- Vector3 target_pos = stack->skeleton->global_pose_to_local_pose(bone_idx, stack->skeleton->world_transform_to_global_pose(target->get_global_transform())).origin;
-
- // Lock the rotation to a plane relative to the bone by changing the target position
- if (lock_rotation_to_plane) {
- if (lock_rotation_plane == ROTATION_PLANE::ROTATION_PLANE_X) {
- target_pos.x = new_bone_trans.origin.x;
- } else if (lock_rotation_plane == ROTATION_PLANE::ROTATION_PLANE_Y) {
- target_pos.y = new_bone_trans.origin.y;
- } else if (lock_rotation_plane == ROTATION_PLANE::ROTATION_PLANE_Z) {
- target_pos.z = new_bone_trans.origin.z;
- }
- }
-
- // Look at the target!
- new_bone_trans = new_bone_trans.looking_at(target_pos, Vector3(0, 1, 0));
- // Convert from Z-forward to whatever direction the bone faces.
- stack->skeleton->update_bone_rest_forward_vector(bone_idx);
- new_bone_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(bone_idx, new_bone_trans.basis);
-
- // Apply additional rotation
- new_bone_trans.basis.rotate_local(Vector3(1, 0, 0), additional_rotation.x);
- new_bone_trans.basis.rotate_local(Vector3(0, 1, 0), additional_rotation.y);
- new_bone_trans.basis.rotate_local(Vector3(0, 0, 1), additional_rotation.z);
-
- stack->skeleton->set_bone_local_pose_override(bone_idx, new_bone_trans, stack->strength, true);
- stack->skeleton->force_update_bone_children_transforms(bone_idx);
-
- // If we completed it successfully, then we can set execution_error_found to false
- execution_error_found = false;
-}
-
-void SkeletonModification3DLookAt::_setup_modification(SkeletonModificationStack3D *p_stack) {
- stack = p_stack;
-
- if (stack != nullptr) {
- is_setup = true;
- execution_error_found = false;
- update_cache();
- }
-}
-
-void SkeletonModification3DLookAt::set_bone_name(String p_name) {
- bone_name = p_name;
- if (stack) {
- if (stack->skeleton) {
- bone_idx = stack->skeleton->find_bone(bone_name);
- }
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-String SkeletonModification3DLookAt::get_bone_name() const {
- return bone_name;
-}
-
-int SkeletonModification3DLookAt::get_bone_index() const {
- return bone_idx;
-}
-
-void SkeletonModification3DLookAt::set_bone_index(int p_bone_idx) {
- ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
- bone_idx = p_bone_idx;
-
- if (stack) {
- if (stack->skeleton) {
- bone_name = stack->skeleton->get_bone_name(p_bone_idx);
- }
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-void SkeletonModification3DLookAt::update_cache() {
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update target cache: modification is not properly setup!");
- return;
- }
-
- target_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree()) {
- if (stack->skeleton->has_node(target_node)) {
- Node *node = stack->skeleton->get_node(target_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update target cache: Node is this modification's skeleton or cannot be found!");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update target cache: Node is not in the scene tree!");
- target_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DLookAt::set_target_node(const NodePath &p_target_node) {
- target_node = p_target_node;
- update_cache();
-}
-
-NodePath SkeletonModification3DLookAt::get_target_node() const {
- return target_node;
-}
-
-Vector3 SkeletonModification3DLookAt::get_additional_rotation() const {
- return additional_rotation;
-}
-
-void SkeletonModification3DLookAt::set_additional_rotation(Vector3 p_offset) {
- additional_rotation = p_offset;
-}
-
-bool SkeletonModification3DLookAt::get_lock_rotation_to_plane() const {
- return lock_rotation_plane;
-}
-
-void SkeletonModification3DLookAt::set_lock_rotation_to_plane(bool p_lock_rotation) {
- lock_rotation_to_plane = p_lock_rotation;
- notify_property_list_changed();
-}
-
-int SkeletonModification3DLookAt::get_lock_rotation_plane() const {
- return lock_rotation_plane;
-}
-
-void SkeletonModification3DLookAt::set_lock_rotation_plane(int p_plane) {
- lock_rotation_plane = p_plane;
-}
-
-void SkeletonModification3DLookAt::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_bone_name", "name"), &SkeletonModification3DLookAt::set_bone_name);
- ClassDB::bind_method(D_METHOD("get_bone_name"), &SkeletonModification3DLookAt::get_bone_name);
-
- ClassDB::bind_method(D_METHOD("set_bone_index", "bone_idx"), &SkeletonModification3DLookAt::set_bone_index);
- ClassDB::bind_method(D_METHOD("get_bone_index"), &SkeletonModification3DLookAt::get_bone_index);
-
- ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification3DLookAt::set_target_node);
- ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification3DLookAt::get_target_node);
-
- ClassDB::bind_method(D_METHOD("set_additional_rotation", "additional_rotation"), &SkeletonModification3DLookAt::set_additional_rotation);
- ClassDB::bind_method(D_METHOD("get_additional_rotation"), &SkeletonModification3DLookAt::get_additional_rotation);
-
- ClassDB::bind_method(D_METHOD("set_lock_rotation_to_plane", "lock_to_plane"), &SkeletonModification3DLookAt::set_lock_rotation_to_plane);
- ClassDB::bind_method(D_METHOD("get_lock_rotation_to_plane"), &SkeletonModification3DLookAt::get_lock_rotation_to_plane);
- ClassDB::bind_method(D_METHOD("set_lock_rotation_plane", "plane"), &SkeletonModification3DLookAt::set_lock_rotation_plane);
- ClassDB::bind_method(D_METHOD("get_lock_rotation_plane"), &SkeletonModification3DLookAt::get_lock_rotation_plane);
-
- ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bone_name"), "set_bone_name", "get_bone_name");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_index"), "set_bone_index", "get_bone_index");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
-}
-
-SkeletonModification3DLookAt::SkeletonModification3DLookAt() {
- stack = nullptr;
- is_setup = false;
- bone_name = "";
- bone_idx = -2;
- additional_rotation = Vector3();
- lock_rotation_to_plane = false;
- enabled = true;
-}
-
-SkeletonModification3DLookAt::~SkeletonModification3DLookAt() {
-}
diff --git a/scene/resources/skeleton_modification_3d_lookat.h b/scene/resources/skeleton_modification_3d_lookat.h
deleted file mode 100644
index 9a25ac530d..0000000000
--- a/scene/resources/skeleton_modification_3d_lookat.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_lookat.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef SKELETON_MODIFICATION_3D_LOOKAT_H
-#define SKELETON_MODIFICATION_3D_LOOKAT_H
-
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-class SkeletonModification3DLookAt : public SkeletonModification3D {
- GDCLASS(SkeletonModification3DLookAt, SkeletonModification3D);
-
-private:
- String bone_name = "";
- int bone_idx = -1;
- NodePath target_node;
- ObjectID target_node_cache;
-
- Vector3 additional_rotation = Vector3(1, 0, 0);
- bool lock_rotation_to_plane = false;
- int lock_rotation_plane = ROTATION_PLANE_X;
-
- void update_cache();
-
-protected:
- static void _bind_methods();
- bool _get(const StringName &p_path, Variant &r_ret) const;
- bool _set(const StringName &p_path, const Variant &p_value);
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
-public:
- enum ROTATION_PLANE {
- ROTATION_PLANE_X,
- ROTATION_PLANE_Y,
- ROTATION_PLANE_Z
- };
-
- virtual void _execute(real_t p_delta) override;
- virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
-
- void set_bone_name(String p_name);
- String get_bone_name() const;
-
- void set_bone_index(int p_idx);
- int get_bone_index() const;
-
- void set_target_node(const NodePath &p_target_node);
- NodePath get_target_node() const;
-
- void set_additional_rotation(Vector3 p_offset);
- Vector3 get_additional_rotation() const;
-
- void set_lock_rotation_to_plane(bool p_lock_to_plane);
- bool get_lock_rotation_to_plane() const;
- void set_lock_rotation_plane(int p_plane);
- int get_lock_rotation_plane() const;
-
- SkeletonModification3DLookAt();
- ~SkeletonModification3DLookAt();
-};
-
-#endif // SKELETON_MODIFICATION_3D_LOOKAT_H
diff --git a/scene/resources/skeleton_modification_3d_stackholder.cpp b/scene/resources/skeleton_modification_3d_stackholder.cpp
deleted file mode 100644
index 1598badb30..0000000000
--- a/scene/resources/skeleton_modification_3d_stackholder.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_stackholder.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "scene/resources/skeleton_modification_3d_stackholder.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-bool SkeletonModification3DStackHolder::_set(const StringName &p_path, const Variant &p_value) {
- String path = p_path;
-
- if (path == "held_modification_stack") {
- set_held_modification_stack(p_value);
- }
- return true;
-}
-
-bool SkeletonModification3DStackHolder::_get(const StringName &p_path, Variant &r_ret) const {
- String path = p_path;
-
- if (path == "held_modification_stack") {
- r_ret = get_held_modification_stack();
- }
- return true;
-}
-
-void SkeletonModification3DStackHolder::_get_property_list(List<PropertyInfo> *p_list) const {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "held_modification_stack", PROPERTY_HINT_RESOURCE_TYPE, "SkeletonModificationStack3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
-}
-
-void SkeletonModification3DStackHolder::_execute(real_t p_delta) {
- ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
- "Modification is not setup and therefore cannot execute!");
-
- if (held_modification_stack.is_valid()) {
- held_modification_stack->execute(p_delta, execution_mode);
- }
-}
-
-void SkeletonModification3DStackHolder::_setup_modification(SkeletonModificationStack3D *p_stack) {
- stack = p_stack;
-
- if (stack != nullptr) {
- is_setup = true;
-
- if (held_modification_stack.is_valid()) {
- held_modification_stack->set_skeleton(stack->get_skeleton());
- held_modification_stack->setup();
- }
- }
-}
-
-void SkeletonModification3DStackHolder::set_held_modification_stack(Ref<SkeletonModificationStack3D> p_held_stack) {
- held_modification_stack = p_held_stack;
-
- if (is_setup && held_modification_stack.is_valid()) {
- held_modification_stack->set_skeleton(stack->get_skeleton());
- held_modification_stack->setup();
- }
-}
-
-Ref<SkeletonModificationStack3D> SkeletonModification3DStackHolder::get_held_modification_stack() const {
- return held_modification_stack;
-}
-
-void SkeletonModification3DStackHolder::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_held_modification_stack", "held_modification_stack"), &SkeletonModification3DStackHolder::set_held_modification_stack);
- ClassDB::bind_method(D_METHOD("get_held_modification_stack"), &SkeletonModification3DStackHolder::get_held_modification_stack);
-}
-
-SkeletonModification3DStackHolder::SkeletonModification3DStackHolder() {
- stack = nullptr;
- is_setup = false;
- enabled = true;
-}
-
-SkeletonModification3DStackHolder::~SkeletonModification3DStackHolder() {
-}
diff --git a/scene/resources/skeleton_modification_3d_stackholder.h b/scene/resources/skeleton_modification_3d_stackholder.h
deleted file mode 100644
index da39044f97..0000000000
--- a/scene/resources/skeleton_modification_3d_stackholder.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_stackholder.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef SKELETON_MODIFICATION_3D_STACKHOLDER_H
-#define SKELETON_MODIFICATION_3D_STACKHOLDER_H
-
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-class SkeletonModification3DStackHolder : public SkeletonModification3D {
- GDCLASS(SkeletonModification3DStackHolder, SkeletonModification3D);
-
-protected:
- static void _bind_methods();
- bool _get(const StringName &p_path, Variant &r_ret) const;
- bool _set(const StringName &p_path, const Variant &p_value);
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
-public:
- Ref<SkeletonModificationStack3D> held_modification_stack;
-
- virtual void _execute(real_t p_delta) override;
- virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
-
- void set_held_modification_stack(Ref<SkeletonModificationStack3D> p_held_stack);
- Ref<SkeletonModificationStack3D> get_held_modification_stack() const;
-
- SkeletonModification3DStackHolder();
- ~SkeletonModification3DStackHolder();
-};
-
-#endif // SKELETON_MODIFICATION_3D_STACKHOLDER_H
diff --git a/scene/resources/skeleton_modification_3d_twoboneik.cpp b/scene/resources/skeleton_modification_3d_twoboneik.cpp
deleted file mode 100644
index 7d5b4d2b55..0000000000
--- a/scene/resources/skeleton_modification_3d_twoboneik.cpp
+++ /dev/null
@@ -1,617 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_twoboneik.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "scene/resources/skeleton_modification_3d_twoboneik.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-bool SkeletonModification3DTwoBoneIK::_set(const StringName &p_path, const Variant &p_value) {
- String path = p_path;
-
- if (path == "use_tip_node") {
- set_use_tip_node(p_value);
- } else if (path == "tip_node") {
- set_tip_node(p_value);
- } else if (path == "auto_calculate_joint_length") {
- set_auto_calculate_joint_length(p_value);
- } else if (path == "use_pole_node") {
- set_use_pole_node(p_value);
- } else if (path == "pole_node") {
- set_pole_node(p_value);
- } else if (path == "joint_one_length") {
- set_joint_one_length(p_value);
- } else if (path == "joint_two_length") {
- set_joint_two_length(p_value);
- } else if (path == "joint_one/bone_name") {
- set_joint_one_bone_name(p_value);
- } else if (path == "joint_one/bone_idx") {
- set_joint_one_bone_idx(p_value);
- } else if (path == "joint_one/roll") {
- set_joint_one_roll(Math::deg_to_rad(real_t(p_value)));
- } else if (path == "joint_two/bone_name") {
- set_joint_two_bone_name(p_value);
- } else if (path == "joint_two/bone_idx") {
- set_joint_two_bone_idx(p_value);
- } else if (path == "joint_two/roll") {
- set_joint_two_roll(Math::deg_to_rad(real_t(p_value)));
- }
-
- return true;
-}
-
-bool SkeletonModification3DTwoBoneIK::_get(const StringName &p_path, Variant &r_ret) const {
- String path = p_path;
-
- if (path == "use_tip_node") {
- r_ret = get_use_tip_node();
- } else if (path == "tip_node") {
- r_ret = get_tip_node();
- } else if (path == "auto_calculate_joint_length") {
- r_ret = get_auto_calculate_joint_length();
- } else if (path == "use_pole_node") {
- r_ret = get_use_pole_node();
- } else if (path == "pole_node") {
- r_ret = get_pole_node();
- } else if (path == "joint_one_length") {
- r_ret = get_joint_one_length();
- } else if (path == "joint_two_length") {
- r_ret = get_joint_two_length();
- } else if (path == "joint_one/bone_name") {
- r_ret = get_joint_one_bone_name();
- } else if (path == "joint_one/bone_idx") {
- r_ret = get_joint_one_bone_idx();
- } else if (path == "joint_one/roll") {
- r_ret = Math::rad_to_deg(get_joint_one_roll());
- } else if (path == "joint_two/bone_name") {
- r_ret = get_joint_two_bone_name();
- } else if (path == "joint_two/bone_idx") {
- r_ret = get_joint_two_bone_idx();
- } else if (path == "joint_two/roll") {
- r_ret = Math::rad_to_deg(get_joint_two_roll());
- }
-
- return true;
-}
-
-void SkeletonModification3DTwoBoneIK::_get_property_list(List<PropertyInfo> *p_list) const {
- p_list->push_back(PropertyInfo(Variant::BOOL, "use_tip_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- if (use_tip_node) {
- p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tip_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D", PROPERTY_USAGE_DEFAULT));
- }
-
- p_list->push_back(PropertyInfo(Variant::BOOL, "auto_calculate_joint_length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- if (!auto_calculate_joint_length) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_one_length", PROPERTY_HINT_RANGE, "-1, 10000, 0.001", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_two_length", PROPERTY_HINT_RANGE, "-1, 10000, 0.001", PROPERTY_USAGE_DEFAULT));
- }
-
- p_list->push_back(PropertyInfo(Variant::BOOL, "use_pole_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- if (use_pole_node) {
- p_list->push_back(PropertyInfo(Variant::NODE_PATH, "pole_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D", PROPERTY_USAGE_DEFAULT));
- }
-
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, "joint_one/bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::INT, "joint_one/bone_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_one/roll", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
-
- p_list->push_back(PropertyInfo(Variant::STRING_NAME, "joint_two/bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::INT, "joint_two/bone_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
- p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_two/roll", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
-}
-
-void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
- ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
- "Modification is not setup and therefore cannot execute!");
-
- if (!enabled) {
- return;
- }
-
- if (_print_execution_error(joint_one_bone_idx < 0 || joint_two_bone_idx < 0,
- "One (or more) of the bones in the modification have invalid bone indexes. Cannot execute modification!")) {
- return;
- }
-
- if (target_node_cache.is_null()) {
- _print_execution_error(true, "Target cache is out of date. Attempting to update...");
- update_cache_target();
- return;
- }
-
- // Update joint lengths (if needed)
- if (auto_calculate_joint_length && (joint_one_length < 0 || joint_two_length < 0)) {
- calculate_joint_lengths();
- }
-
- // Adopted from the links below:
- // http://theorangeduck.com/page/simple-two-joint
- // https://www.alanzucconi.com/2018/05/02/ik-2d-2/
- // With modifications by TwistedTwigleg
- Node3D *target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
- if (_print_execution_error(!target || !target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
- return;
- }
- Transform3D target_trans = stack->skeleton->world_transform_to_global_pose(target->get_global_transform());
-
- Transform3D bone_one_trans;
- Transform3D bone_two_trans;
-
- // Make the first joint look at the pole, and the second look at the target. That way, the
- // TwoBoneIK solver has to really only handle extension/contraction, which should make it align with the pole.
- if (use_pole_node) {
- if (pole_node_cache.is_null()) {
- _print_execution_error(true, "Pole cache is out of date. Attempting to update...");
- update_cache_pole();
- return;
- }
-
- Node3D *pole = Object::cast_to<Node3D>(ObjectDB::get_instance(pole_node_cache));
- if (_print_execution_error(!pole || !pole->is_inside_tree(), "Pole node is not in the scene tree. Cannot execute modification!")) {
- return;
- }
- Transform3D pole_trans = stack->skeleton->world_transform_to_global_pose(pole->get_global_transform());
-
- Transform3D bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx);
- if (bone_one_local_pos == Transform3D()) {
- bone_one_local_pos = stack->skeleton->get_bone_pose(joint_one_bone_idx);
- }
- Transform3D bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx);
- if (bone_two_local_pos == Transform3D()) {
- bone_two_local_pos = stack->skeleton->get_bone_pose(joint_two_bone_idx);
- }
-
- bone_one_trans = stack->skeleton->local_pose_to_global_pose(joint_one_bone_idx, bone_one_local_pos);
- bone_one_trans = bone_one_trans.looking_at(pole_trans.origin, Vector3(0, 1, 0));
- bone_one_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(joint_one_bone_idx, bone_one_trans.basis);
- stack->skeleton->update_bone_rest_forward_vector(joint_one_bone_idx);
- bone_one_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_one_bone_idx), joint_one_roll);
- stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, stack->skeleton->global_pose_to_local_pose(joint_one_bone_idx, bone_one_trans), stack->strength, true);
- stack->skeleton->force_update_bone_children_transforms(joint_one_bone_idx);
-
- bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, bone_two_local_pos);
- bone_two_trans = bone_two_trans.looking_at(target_trans.origin, Vector3(0, 1, 0));
- bone_two_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(joint_two_bone_idx, bone_two_trans.basis);
- stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
- bone_two_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx), joint_two_roll);
- stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans), stack->strength, true);
- stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx);
- } else {
- Transform3D bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx);
- if (bone_one_local_pos == Transform3D()) {
- bone_one_local_pos = stack->skeleton->get_bone_pose(joint_one_bone_idx);
- }
- Transform3D bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx);
- if (bone_two_local_pos == Transform3D()) {
- bone_two_local_pos = stack->skeleton->get_bone_pose(joint_two_bone_idx);
- }
-
- bone_one_trans = stack->skeleton->local_pose_to_global_pose(joint_one_bone_idx, bone_one_local_pos);
- bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, bone_two_local_pos);
- }
-
- Transform3D bone_two_tip_trans;
- if (use_tip_node) {
- if (tip_node_cache.is_null()) {
- _print_execution_error(true, "Tip cache is out of date. Attempting to update...");
- update_cache_tip();
- return;
- }
- Node3D *tip = Object::cast_to<Node3D>(ObjectDB::get_instance(tip_node_cache));
- if (_print_execution_error(!tip || !tip->is_inside_tree(), "Tip node is not in the scene tree. Cannot execute modification!")) {
- return;
- }
- bone_two_tip_trans = stack->skeleton->world_transform_to_global_pose(tip->get_global_transform());
- } else {
- stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
- bone_two_tip_trans = bone_two_trans;
- bone_two_tip_trans.origin += bone_two_trans.basis.xform(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx)).normalized() * joint_two_length;
- }
-
- real_t joint_one_to_target_length = bone_one_trans.origin.distance_to(target_trans.origin);
- if (joint_one_length + joint_two_length < joint_one_to_target_length) {
- // Set the target *just* out of reach to straighten the bones
- joint_one_to_target_length = joint_one_length + joint_two_length + 0.01;
- } else if (joint_one_to_target_length < joint_one_length) {
- // Place the target in reach so the solver doesn't do crazy things
- joint_one_to_target_length = joint_one_length;
- }
-
- // Get the square lengths for all three sides of the triangle we'll use to calculate the angles
- real_t sqr_one_length = joint_one_length * joint_one_length;
- real_t sqr_two_length = joint_two_length * joint_two_length;
- real_t sqr_three_length = joint_one_to_target_length * joint_one_to_target_length;
-
- // Calculate the angles for the first joint using the law of cosigns
- real_t ac_ab_0 = Math::acos(CLAMP(bone_two_tip_trans.origin.direction_to(bone_one_trans.origin).dot(bone_two_trans.origin.direction_to(bone_one_trans.origin)), -1, 1));
- real_t ac_at_0 = Math::acos(CLAMP(bone_one_trans.origin.direction_to(bone_two_tip_trans.origin).dot(bone_one_trans.origin.direction_to(target_trans.origin)), -1, 1));
- real_t ac_ab_1 = Math::acos(CLAMP((sqr_two_length - sqr_one_length - sqr_three_length) / (-2.0 * joint_one_length * joint_one_to_target_length), -1, 1));
-
- // Calculate the angles of rotation. Angle 0 is the extension/contraction axis, while angle 1 is the rotation axis to align the triangle to the target
- Vector3 axis_0 = bone_one_trans.origin.direction_to(bone_two_tip_trans.origin).cross(bone_one_trans.origin.direction_to(bone_two_trans.origin));
- Vector3 axis_1 = bone_one_trans.origin.direction_to(bone_two_tip_trans.origin).cross(bone_one_trans.origin.direction_to(target_trans.origin));
-
- // Make a quaternion with the delta rotation needed to rotate the first joint into alignment and apply it to the transform.
- Quaternion bone_one_quat = bone_one_trans.basis.get_rotation_quaternion();
- Quaternion rot_0 = Quaternion(bone_one_quat.inverse().xform(axis_0).normalized(), (ac_ab_1 - ac_ab_0));
- Quaternion rot_2 = Quaternion(bone_one_quat.inverse().xform(axis_1).normalized(), ac_at_0);
- bone_one_trans.basis.set_quaternion(bone_one_quat * (rot_0 * rot_2));
-
- stack->skeleton->update_bone_rest_forward_vector(joint_one_bone_idx);
- bone_one_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_one_bone_idx), joint_one_roll);
-
- // Apply the rotation to the first joint
- bone_one_trans = stack->skeleton->global_pose_to_local_pose(joint_one_bone_idx, bone_one_trans);
- bone_one_trans.origin = Vector3(0, 0, 0);
- stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, bone_one_trans, stack->strength, true);
- stack->skeleton->force_update_bone_children_transforms(joint_one_bone_idx);
-
- if (use_pole_node) {
- // Update bone_two_trans so its at the latest position, with the rotation of bone_one_trans taken into account, then look at the target.
- bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx));
- stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
- Vector3 forward_vector = stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx);
- bone_two_trans.basis.rotate_to_align(forward_vector, bone_two_trans.origin.direction_to(target_trans.origin));
-
- stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
- bone_two_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx), joint_two_roll);
-
- bone_two_trans = stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans);
- stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength, true);
- stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx);
- } else {
- // Calculate the angles for the second joint using the law of cosigns, make a quaternion with the delta rotation needed to rotate the joint into
- // alignment, and then apply it to the second joint.
- real_t ba_bc_0 = Math::acos(CLAMP(bone_two_trans.origin.direction_to(bone_one_trans.origin).dot(bone_two_trans.origin.direction_to(bone_two_tip_trans.origin)), -1, 1));
- real_t ba_bc_1 = Math::acos(CLAMP((sqr_three_length - sqr_one_length - sqr_two_length) / (-2.0 * joint_one_length * joint_two_length), -1, 1));
- Quaternion bone_two_quat = bone_two_trans.basis.get_rotation_quaternion();
- Quaternion rot_1 = Quaternion(bone_two_quat.inverse().xform(axis_0).normalized(), (ba_bc_1 - ba_bc_0));
- bone_two_trans.basis.set_quaternion(bone_two_quat * rot_1);
-
- stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
- bone_two_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx), joint_two_roll);
-
- bone_two_trans = stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans);
- bone_two_trans.origin = Vector3(0, 0, 0);
- stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength, true);
- stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx);
- }
-}
-
-void SkeletonModification3DTwoBoneIK::_setup_modification(SkeletonModificationStack3D *p_stack) {
- stack = p_stack;
-
- if (stack != nullptr) {
- is_setup = true;
- execution_error_found = false;
- update_cache_target();
- update_cache_tip();
- }
-}
-
-void SkeletonModification3DTwoBoneIK::update_cache_target() {
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update target cache: modification is not properly setup!");
- return;
- }
-
- target_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree() && target_node.is_empty() == false) {
- if (stack->skeleton->has_node(target_node)) {
- Node *node = stack->skeleton->get_node(target_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update target cache: Target node is this modification's skeleton or cannot be found. Cannot execute modification");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update target cache: Target node is not in the scene tree. Cannot execute modification!");
- target_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DTwoBoneIK::update_cache_tip() {
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update tip cache: modification is not properly setup!");
- return;
- }
-
- tip_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree()) {
- if (stack->skeleton->has_node(tip_node)) {
- Node *node = stack->skeleton->get_node(tip_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update tip cache: Tip node is this modification's skeleton or cannot be found!");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update tip cache: Tip node is not in the scene tree. Cannot execute modification!");
- tip_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DTwoBoneIK::update_cache_pole() {
- if (!is_setup || !stack) {
- _print_execution_error(true, "Cannot update pole cache: modification is not properly setup!");
- return;
- }
-
- pole_node_cache = ObjectID();
- if (stack->skeleton) {
- if (stack->skeleton->is_inside_tree()) {
- if (stack->skeleton->has_node(pole_node)) {
- Node *node = stack->skeleton->get_node(pole_node);
- ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
- "Cannot update pole cache: Pole node is this modification's skeleton or cannot be found!");
- ERR_FAIL_COND_MSG(!node->is_inside_tree(),
- "Cannot update pole cache: Pole node is not in the scene tree. Cannot execute modification!");
- pole_node_cache = node->get_instance_id();
-
- execution_error_found = false;
- }
- }
- }
-}
-
-void SkeletonModification3DTwoBoneIK::set_target_node(const NodePath &p_target_node) {
- target_node = p_target_node;
- update_cache_target();
-}
-
-NodePath SkeletonModification3DTwoBoneIK::get_target_node() const {
- return target_node;
-}
-
-void SkeletonModification3DTwoBoneIK::set_use_tip_node(const bool p_use_tip_node) {
- use_tip_node = p_use_tip_node;
- notify_property_list_changed();
-}
-
-bool SkeletonModification3DTwoBoneIK::get_use_tip_node() const {
- return use_tip_node;
-}
-
-void SkeletonModification3DTwoBoneIK::set_tip_node(const NodePath &p_tip_node) {
- tip_node = p_tip_node;
- update_cache_tip();
-}
-
-NodePath SkeletonModification3DTwoBoneIK::get_tip_node() const {
- return tip_node;
-}
-
-void SkeletonModification3DTwoBoneIK::set_use_pole_node(const bool p_use_pole_node) {
- use_pole_node = p_use_pole_node;
- notify_property_list_changed();
-}
-
-bool SkeletonModification3DTwoBoneIK::get_use_pole_node() const {
- return use_pole_node;
-}
-
-void SkeletonModification3DTwoBoneIK::set_pole_node(const NodePath &p_pole_node) {
- pole_node = p_pole_node;
- update_cache_pole();
-}
-
-NodePath SkeletonModification3DTwoBoneIK::get_pole_node() const {
- return pole_node;
-}
-
-void SkeletonModification3DTwoBoneIK::set_auto_calculate_joint_length(bool p_calculate) {
- auto_calculate_joint_length = p_calculate;
- if (p_calculate) {
- calculate_joint_lengths();
- }
- notify_property_list_changed();
-}
-
-bool SkeletonModification3DTwoBoneIK::get_auto_calculate_joint_length() const {
- return auto_calculate_joint_length;
-}
-
-void SkeletonModification3DTwoBoneIK::calculate_joint_lengths() {
- if (!is_setup) {
- return; // fail silently, as we likely just loaded the scene.
- }
- ERR_FAIL_COND_MSG(!stack || stack->skeleton == nullptr,
- "Modification is not setup and therefore cannot calculate joint lengths!");
- ERR_FAIL_COND_MSG(joint_one_bone_idx <= -1 || joint_two_bone_idx <= -1,
- "One of the bones in the TwoBoneIK modification are not set! Cannot calculate joint lengths!");
-
- Transform3D bone_one_rest_trans = stack->skeleton->get_bone_global_pose(joint_one_bone_idx);
- Transform3D bone_two_rest_trans = stack->skeleton->get_bone_global_pose(joint_two_bone_idx);
-
- joint_one_length = bone_one_rest_trans.origin.distance_to(bone_two_rest_trans.origin);
-
- if (use_tip_node) {
- if (tip_node_cache.is_null()) {
- update_cache_tip();
- WARN_PRINT("Tip cache is out of date. Updating...");
- }
-
- Node3D *tip = Object::cast_to<Node3D>(ObjectDB::get_instance(tip_node_cache));
- if (tip) {
- Transform3D bone_tip_trans = stack->skeleton->world_transform_to_global_pose(tip->get_global_transform());
- joint_two_length = bone_two_rest_trans.origin.distance_to(bone_tip_trans.origin);
- }
- } else {
- // Attempt to use children bones to get the length
- Vector<int> bone_two_children = stack->skeleton->get_bone_children(joint_two_bone_idx);
- if (bone_two_children.size() > 0) {
- joint_two_length = 0;
- for (int i = 0; i < bone_two_children.size(); i++) {
- joint_two_length += bone_two_rest_trans.origin.distance_to(
- stack->skeleton->get_bone_global_pose(bone_two_children[i]).origin);
- }
- joint_two_length = joint_two_length / bone_two_children.size();
- } else {
- WARN_PRINT("TwoBoneIK modification: Cannot auto calculate length for joint 2! Auto setting the length to 1...");
- joint_two_length = 1.0;
- }
- }
- execution_error_found = false;
-}
-
-void SkeletonModification3DTwoBoneIK::set_joint_one_bone_name(String p_bone_name) {
- joint_one_bone_name = p_bone_name;
- if (stack && stack->skeleton) {
- joint_one_bone_idx = stack->skeleton->find_bone(p_bone_name);
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-String SkeletonModification3DTwoBoneIK::get_joint_one_bone_name() const {
- return joint_one_bone_name;
-}
-
-void SkeletonModification3DTwoBoneIK::set_joint_one_bone_idx(int p_bone_idx) {
- joint_one_bone_idx = p_bone_idx;
- if (stack && stack->skeleton) {
- joint_one_bone_name = stack->skeleton->get_bone_name(p_bone_idx);
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-int SkeletonModification3DTwoBoneIK::get_joint_one_bone_idx() const {
- return joint_one_bone_idx;
-}
-
-void SkeletonModification3DTwoBoneIK::set_joint_one_length(real_t p_length) {
- joint_one_length = p_length;
-}
-
-real_t SkeletonModification3DTwoBoneIK::get_joint_one_length() const {
- return joint_one_length;
-}
-
-void SkeletonModification3DTwoBoneIK::set_joint_two_bone_name(String p_bone_name) {
- joint_two_bone_name = p_bone_name;
- if (stack && stack->skeleton) {
- joint_two_bone_idx = stack->skeleton->find_bone(p_bone_name);
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-String SkeletonModification3DTwoBoneIK::get_joint_two_bone_name() const {
- return joint_two_bone_name;
-}
-
-void SkeletonModification3DTwoBoneIK::set_joint_two_bone_idx(int p_bone_idx) {
- joint_two_bone_idx = p_bone_idx;
- if (stack && stack->skeleton) {
- joint_two_bone_name = stack->skeleton->get_bone_name(p_bone_idx);
- }
- execution_error_found = false;
- notify_property_list_changed();
-}
-
-int SkeletonModification3DTwoBoneIK::get_joint_two_bone_idx() const {
- return joint_two_bone_idx;
-}
-
-void SkeletonModification3DTwoBoneIK::set_joint_two_length(real_t p_length) {
- joint_two_length = p_length;
-}
-
-real_t SkeletonModification3DTwoBoneIK::get_joint_two_length() const {
- return joint_two_length;
-}
-
-void SkeletonModification3DTwoBoneIK::set_joint_one_roll(real_t p_roll) {
- joint_one_roll = p_roll;
-}
-
-real_t SkeletonModification3DTwoBoneIK::get_joint_one_roll() const {
- return joint_one_roll;
-}
-
-void SkeletonModification3DTwoBoneIK::set_joint_two_roll(real_t p_roll) {
- joint_two_roll = p_roll;
-}
-
-real_t SkeletonModification3DTwoBoneIK::get_joint_two_roll() const {
- return joint_two_roll;
-}
-
-void SkeletonModification3DTwoBoneIK::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification3DTwoBoneIK::set_target_node);
- ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification3DTwoBoneIK::get_target_node);
-
- ClassDB::bind_method(D_METHOD("set_use_pole_node", "use_pole_node"), &SkeletonModification3DTwoBoneIK::set_use_pole_node);
- ClassDB::bind_method(D_METHOD("get_use_pole_node"), &SkeletonModification3DTwoBoneIK::get_use_pole_node);
- ClassDB::bind_method(D_METHOD("set_pole_node", "pole_nodepath"), &SkeletonModification3DTwoBoneIK::set_pole_node);
- ClassDB::bind_method(D_METHOD("get_pole_node"), &SkeletonModification3DTwoBoneIK::get_pole_node);
-
- ClassDB::bind_method(D_METHOD("set_use_tip_node", "use_tip_node"), &SkeletonModification3DTwoBoneIK::set_use_tip_node);
- ClassDB::bind_method(D_METHOD("get_use_tip_node"), &SkeletonModification3DTwoBoneIK::get_use_tip_node);
- ClassDB::bind_method(D_METHOD("set_tip_node", "tip_nodepath"), &SkeletonModification3DTwoBoneIK::set_tip_node);
- ClassDB::bind_method(D_METHOD("get_tip_node"), &SkeletonModification3DTwoBoneIK::get_tip_node);
-
- ClassDB::bind_method(D_METHOD("set_auto_calculate_joint_length", "auto_calculate_joint_length"), &SkeletonModification3DTwoBoneIK::set_auto_calculate_joint_length);
- ClassDB::bind_method(D_METHOD("get_auto_calculate_joint_length"), &SkeletonModification3DTwoBoneIK::get_auto_calculate_joint_length);
-
- ClassDB::bind_method(D_METHOD("set_joint_one_bone_name", "bone_name"), &SkeletonModification3DTwoBoneIK::set_joint_one_bone_name);
- ClassDB::bind_method(D_METHOD("get_joint_one_bone_name"), &SkeletonModification3DTwoBoneIK::get_joint_one_bone_name);
- ClassDB::bind_method(D_METHOD("set_joint_one_bone_idx", "bone_idx"), &SkeletonModification3DTwoBoneIK::set_joint_one_bone_idx);
- ClassDB::bind_method(D_METHOD("get_joint_one_bone_idx"), &SkeletonModification3DTwoBoneIK::get_joint_one_bone_idx);
- ClassDB::bind_method(D_METHOD("set_joint_one_length", "bone_length"), &SkeletonModification3DTwoBoneIK::set_joint_one_length);
- ClassDB::bind_method(D_METHOD("get_joint_one_length"), &SkeletonModification3DTwoBoneIK::get_joint_one_length);
-
- ClassDB::bind_method(D_METHOD("set_joint_two_bone_name", "bone_name"), &SkeletonModification3DTwoBoneIK::set_joint_two_bone_name);
- ClassDB::bind_method(D_METHOD("get_joint_two_bone_name"), &SkeletonModification3DTwoBoneIK::get_joint_two_bone_name);
- ClassDB::bind_method(D_METHOD("set_joint_two_bone_idx", "bone_idx"), &SkeletonModification3DTwoBoneIK::set_joint_two_bone_idx);
- ClassDB::bind_method(D_METHOD("get_joint_two_bone_idx"), &SkeletonModification3DTwoBoneIK::get_joint_two_bone_idx);
- ClassDB::bind_method(D_METHOD("set_joint_two_length", "bone_length"), &SkeletonModification3DTwoBoneIK::set_joint_two_length);
- ClassDB::bind_method(D_METHOD("get_joint_two_length"), &SkeletonModification3DTwoBoneIK::get_joint_two_length);
-
- ClassDB::bind_method(D_METHOD("set_joint_one_roll", "roll"), &SkeletonModification3DTwoBoneIK::set_joint_one_roll);
- ClassDB::bind_method(D_METHOD("get_joint_one_roll"), &SkeletonModification3DTwoBoneIK::get_joint_one_roll);
- ClassDB::bind_method(D_METHOD("set_joint_two_roll", "roll"), &SkeletonModification3DTwoBoneIK::set_joint_two_roll);
- ClassDB::bind_method(D_METHOD("get_joint_two_roll"), &SkeletonModification3DTwoBoneIK::get_joint_two_roll);
-
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
- ADD_GROUP("", "");
-}
-
-SkeletonModification3DTwoBoneIK::SkeletonModification3DTwoBoneIK() {
- stack = nullptr;
- is_setup = false;
-}
-
-SkeletonModification3DTwoBoneIK::~SkeletonModification3DTwoBoneIK() {
-}
diff --git a/scene/resources/skeleton_modification_3d_twoboneik.h b/scene/resources/skeleton_modification_3d_twoboneik.h
deleted file mode 100644
index 57481e0181..0000000000
--- a/scene/resources/skeleton_modification_3d_twoboneik.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_3d_twoboneik.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef SKELETON_MODIFICATION_3D_TWOBONEIK_H
-#define SKELETON_MODIFICATION_3D_TWOBONEIK_H
-
-#include "scene/3d/skeleton_3d.h"
-#include "scene/resources/skeleton_modification_3d.h"
-
-class SkeletonModification3DTwoBoneIK : public SkeletonModification3D {
- GDCLASS(SkeletonModification3DTwoBoneIK, SkeletonModification3D);
-
-private:
- NodePath target_node;
- ObjectID target_node_cache;
-
- bool use_tip_node = false;
- NodePath tip_node;
- ObjectID tip_node_cache;
-
- bool use_pole_node = false;
- NodePath pole_node;
- ObjectID pole_node_cache;
-
- String joint_one_bone_name = "";
- int joint_one_bone_idx = -1;
- String joint_two_bone_name = "";
- int joint_two_bone_idx = -1;
-
- bool auto_calculate_joint_length = false;
- real_t joint_one_length = -1;
- real_t joint_two_length = -1;
-
- real_t joint_one_roll = 0;
- real_t joint_two_roll = 0;
-
- void update_cache_target();
- void update_cache_tip();
- void update_cache_pole();
-
-protected:
- static void _bind_methods();
- bool _get(const StringName &p_path, Variant &r_ret) const;
- bool _set(const StringName &p_path, const Variant &p_value);
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
-public:
- virtual void _execute(real_t p_delta) override;
- virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
-
- void set_target_node(const NodePath &p_target_node);
- NodePath get_target_node() const;
-
- void set_use_tip_node(const bool p_use_tip_node);
- bool get_use_tip_node() const;
- void set_tip_node(const NodePath &p_tip_node);
- NodePath get_tip_node() const;
-
- void set_use_pole_node(const bool p_use_pole_node);
- bool get_use_pole_node() const;
- void set_pole_node(const NodePath &p_pole_node);
- NodePath get_pole_node() const;
-
- void set_auto_calculate_joint_length(bool p_calculate);
- bool get_auto_calculate_joint_length() const;
- void calculate_joint_lengths();
-
- void set_joint_one_bone_name(String p_bone_name);
- String get_joint_one_bone_name() const;
- void set_joint_one_bone_idx(int p_bone_idx);
- int get_joint_one_bone_idx() const;
- void set_joint_one_length(real_t p_length);
- real_t get_joint_one_length() const;
-
- void set_joint_two_bone_name(String p_bone_name);
- String get_joint_two_bone_name() const;
- void set_joint_two_bone_idx(int p_bone_idx);
- int get_joint_two_bone_idx() const;
- void set_joint_two_length(real_t p_length);
- real_t get_joint_two_length() const;
-
- void set_joint_one_roll(real_t p_roll);
- real_t get_joint_one_roll() const;
- void set_joint_two_roll(real_t p_roll);
- real_t get_joint_two_roll() const;
-
- SkeletonModification3DTwoBoneIK();
- ~SkeletonModification3DTwoBoneIK();
-};
-
-#endif // SKELETON_MODIFICATION_3D_TWOBONEIK_H
diff --git a/scene/resources/skeleton_modification_stack_3d.cpp b/scene/resources/skeleton_modification_stack_3d.cpp
deleted file mode 100644
index 32708e198a..0000000000
--- a/scene/resources/skeleton_modification_stack_3d.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_stack_3d.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "skeleton_modification_stack_3d.h"
-#include "scene/3d/skeleton_3d.h"
-
-///////////////////////////////////////
-// ModificationStack3D
-///////////////////////////////////////
-
-void SkeletonModificationStack3D::_get_property_list(List<PropertyInfo> *p_list) const {
- for (uint32_t i = 0; i < modifications.size(); i++) {
- p_list->push_back(
- PropertyInfo(Variant::OBJECT, "modifications/" + itos(i),
- PROPERTY_HINT_RESOURCE_TYPE,
- "SkeletonModification3D",
- PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
- }
-}
-
-bool SkeletonModificationStack3D::_set(const StringName &p_path, const Variant &p_value) {
- String path = p_path;
-
- if (path.begins_with("modifications/")) {
- int mod_idx = path.get_slicec('/', 1).to_int();
- set_modification(mod_idx, p_value);
- return true;
- }
- return true;
-}
-
-bool SkeletonModificationStack3D::_get(const StringName &p_path, Variant &r_ret) const {
- String path = p_path;
-
- if (path.begins_with("modifications/")) {
- int mod_idx = path.get_slicec('/', 1).to_int();
- r_ret = get_modification(mod_idx);
- return true;
- }
- return true;
-}
-
-void SkeletonModificationStack3D::setup() {
- if (is_setup) {
- return;
- }
-
- if (skeleton != nullptr) {
- is_setup = true;
- for (uint32_t i = 0; i < modifications.size(); i++) {
- if (!modifications[i].is_valid()) {
- continue;
- }
- modifications[i]->_setup_modification(this);
- }
- } else {
- WARN_PRINT("Cannot setup SkeletonModificationStack3D: no skeleton set!");
- }
-}
-
-void SkeletonModificationStack3D::execute(real_t p_delta, int p_execution_mode) {
- ERR_FAIL_COND_MSG(!is_setup || skeleton == nullptr || is_queued_for_deletion(),
- "Modification stack is not properly setup and therefore cannot execute!");
-
- if (!skeleton->is_inside_tree()) {
- ERR_PRINT_ONCE("Skeleton is not inside SceneTree! Cannot execute modification!");
- return;
- }
-
- if (!enabled) {
- return;
- }
-
- for (uint32_t i = 0; i < modifications.size(); i++) {
- if (!modifications[i].is_valid()) {
- continue;
- }
-
- if (modifications[i]->get_execution_mode() == p_execution_mode) {
- modifications[i]->_execute(p_delta);
- }
- }
-}
-
-void SkeletonModificationStack3D::enable_all_modifications(bool p_enabled) {
- for (uint32_t i = 0; i < modifications.size(); i++) {
- if (!modifications[i].is_valid()) {
- continue;
- }
- modifications[i]->set_enabled(p_enabled);
- }
-}
-
-Ref<SkeletonModification3D> SkeletonModificationStack3D::get_modification(int p_mod_idx) const {
- const int modifications_size = modifications.size();
- ERR_FAIL_INDEX_V(p_mod_idx, modifications_size, nullptr);
- return modifications[p_mod_idx];
-}
-
-void SkeletonModificationStack3D::add_modification(Ref<SkeletonModification3D> p_mod) {
- ERR_FAIL_NULL(p_mod);
- p_mod->_setup_modification(this);
- modifications.push_back(p_mod);
-}
-
-void SkeletonModificationStack3D::delete_modification(int p_mod_idx) {
- const int modifications_size = modifications.size();
- ERR_FAIL_INDEX(p_mod_idx, modifications_size);
- modifications.remove_at(p_mod_idx);
-}
-
-void SkeletonModificationStack3D::set_modification(int p_mod_idx, Ref<SkeletonModification3D> p_mod) {
- const int modifications_size = modifications.size();
- ERR_FAIL_INDEX(p_mod_idx, modifications_size);
-
- if (p_mod == nullptr) {
- modifications.remove_at(p_mod_idx);
- } else {
- p_mod->_setup_modification(this);
- modifications[p_mod_idx] = p_mod;
- }
-}
-
-void SkeletonModificationStack3D::set_modification_count(int p_count) {
- ERR_FAIL_COND_MSG(p_count < 0, "Modification count cannot be less than zero.");
- modifications.resize(p_count);
- notify_property_list_changed();
-}
-
-int SkeletonModificationStack3D::get_modification_count() const {
- return modifications.size();
-}
-
-void SkeletonModificationStack3D::set_skeleton(Skeleton3D *p_skeleton) {
- skeleton = p_skeleton;
-}
-
-Skeleton3D *SkeletonModificationStack3D::get_skeleton() const {
- return skeleton;
-}
-
-bool SkeletonModificationStack3D::get_is_setup() const {
- return is_setup;
-}
-
-void SkeletonModificationStack3D::set_enabled(bool p_enabled) {
- enabled = p_enabled;
-
- if (!enabled && is_setup && skeleton != nullptr) {
- skeleton->clear_bones_local_pose_override();
- }
-}
-
-bool SkeletonModificationStack3D::get_enabled() const {
- return enabled;
-}
-
-void SkeletonModificationStack3D::set_strength(real_t p_strength) {
- ERR_FAIL_COND_MSG(p_strength < 0, "Strength cannot be less than zero!");
- ERR_FAIL_COND_MSG(p_strength > 1, "Strength cannot be more than one!");
- strength = p_strength;
-}
-
-real_t SkeletonModificationStack3D::get_strength() const {
- return strength;
-}
-
-void SkeletonModificationStack3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("setup"), &SkeletonModificationStack3D::setup);
- ClassDB::bind_method(D_METHOD("execute", "delta", "execution_mode"), &SkeletonModificationStack3D::execute);
-
- ClassDB::bind_method(D_METHOD("enable_all_modifications", "enabled"), &SkeletonModificationStack3D::enable_all_modifications);
- ClassDB::bind_method(D_METHOD("get_modification", "mod_idx"), &SkeletonModificationStack3D::get_modification);
- ClassDB::bind_method(D_METHOD("add_modification", "modification"), &SkeletonModificationStack3D::add_modification);
- ClassDB::bind_method(D_METHOD("delete_modification", "mod_idx"), &SkeletonModificationStack3D::delete_modification);
- ClassDB::bind_method(D_METHOD("set_modification", "mod_idx", "modification"), &SkeletonModificationStack3D::set_modification);
-
- ClassDB::bind_method(D_METHOD("set_modification_count", "count"), &SkeletonModificationStack3D::set_modification_count);
- ClassDB::bind_method(D_METHOD("get_modification_count"), &SkeletonModificationStack3D::get_modification_count);
-
- ClassDB::bind_method(D_METHOD("get_is_setup"), &SkeletonModificationStack3D::get_is_setup);
-
- ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &SkeletonModificationStack3D::set_enabled);
- ClassDB::bind_method(D_METHOD("get_enabled"), &SkeletonModificationStack3D::get_enabled);
-
- ClassDB::bind_method(D_METHOD("set_strength", "strength"), &SkeletonModificationStack3D::set_strength);
- ClassDB::bind_method(D_METHOD("get_strength"), &SkeletonModificationStack3D::get_strength);
-
- ClassDB::bind_method(D_METHOD("get_skeleton"), &SkeletonModificationStack3D::get_skeleton);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0, 1, 0.001"), "set_strength", "get_strength");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Modifications,modifications/"), "set_modification_count", "get_modification_count");
-}
-
-SkeletonModificationStack3D::SkeletonModificationStack3D() {
-}
diff --git a/scene/resources/skeleton_modification_stack_3d.h b/scene/resources/skeleton_modification_stack_3d.h
deleted file mode 100644
index fd490c49e9..0000000000
--- a/scene/resources/skeleton_modification_stack_3d.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/**************************************************************************/
-/* skeleton_modification_stack_3d.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#ifndef SKELETON_MODIFICATION_STACK_3D_H
-#define SKELETON_MODIFICATION_STACK_3D_H
-
-#include "core/templates/local_vector.h"
-#include "scene/3d/skeleton_3d.h"
-
-class Skeleton3D;
-class SkeletonModification3D;
-
-class SkeletonModificationStack3D : public Resource {
- GDCLASS(SkeletonModificationStack3D, Resource);
- friend class Skeleton3D;
- friend class SkeletonModification3D;
-
-protected:
- static void _bind_methods();
- virtual void _get_property_list(List<PropertyInfo> *p_list) const;
- virtual bool _set(const StringName &p_path, const Variant &p_value);
- virtual bool _get(const StringName &p_path, Variant &r_ret) const;
-
-public:
- Skeleton3D *skeleton = nullptr;
- bool is_setup = false;
- bool enabled = false;
- real_t strength = 1.0;
-
- enum EXECUTION_MODE {
- execution_mode_process,
- execution_mode_physics_process,
- };
-
- LocalVector<Ref<SkeletonModification3D>> modifications = LocalVector<Ref<SkeletonModification3D>>();
- int modifications_count = 0;
-
- virtual void setup();
- virtual void execute(real_t p_delta, int p_execution_mode);
-
- void enable_all_modifications(bool p_enable);
- Ref<SkeletonModification3D> get_modification(int p_mod_idx) const;
- void add_modification(Ref<SkeletonModification3D> p_mod);
- void delete_modification(int p_mod_idx);
- void set_modification(int p_mod_idx, Ref<SkeletonModification3D> p_mod);
-
- void set_modification_count(int p_count);
- int get_modification_count() const;
-
- void set_skeleton(Skeleton3D *p_skeleton);
- Skeleton3D *get_skeleton() const;
-
- bool get_is_setup() const;
-
- void set_enabled(bool p_enabled);
- bool get_enabled() const;
-
- void set_strength(real_t p_strength);
- real_t get_strength() const;
-
- SkeletonModificationStack3D();
-};
-
-#endif // SKELETON_MODIFICATION_STACK_3D_H
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 4043b73b71..94e78fc3aa 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -473,6 +473,7 @@ void TileSet::_compute_next_source_id() {
int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source_id_override) {
ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), TileSet::INVALID_SOURCE);
ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), TileSet::INVALID_SOURCE, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
+ ERR_FAIL_COND_V_MSG(p_atlas_source_id_override < 0 && p_atlas_source_id_override != TileSet::INVALID_SOURCE, TileSet::INVALID_SOURCE, vformat("Provided source ID %d is not valid. Negative source IDs are not allowed.", p_atlas_source_id_override));
int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id;
sources[new_source_id] = p_tile_set_source;
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 4c99563a91..1cbeaae428 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -399,7 +399,6 @@ void VisualShaderNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "expanded_output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_output_ports_expanded", "_get_output_ports_expanded");
- ADD_SIGNAL(MethodInfo("editor_refresh_request"));
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR);
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_INT);
@@ -2734,9 +2733,6 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "front_facing", "FRONT_FACING" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_roughness_texture", "NORMAL_ROUGHNESS_TEXTURE" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "depth_texture", "DEPTH_TEXTURE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
@@ -2799,7 +2795,6 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_texture", "NORMAL_TEXTURE" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "specular_shininess", "SPECULAR_SHININESS" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 432d5a5b59..e78d9b924d 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -756,141 +756,157 @@ Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_t
}
String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- if (source == SOURCE_TEXTURE) {
- String u = "uniform sampler2D " + make_unique_id(p_type, p_id, "tex");
- switch (texture_type) {
- case TYPE_DATA:
- break;
- case TYPE_COLOR:
- u += " : source_color";
- break;
- case TYPE_NORMAL_MAP:
- u += " : hint_normal";
- break;
- default:
- break;
- }
- return u + ";\n";
+ String code;
+
+ switch (source) {
+ case SOURCE_TEXTURE: {
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "tex");
+ switch (texture_type) {
+ case TYPE_DATA: {
+ } break;
+ case TYPE_COLOR: {
+ code += " : source_color";
+ } break;
+ case TYPE_NORMAL_MAP: {
+ code += " : hint_normal";
+ } break;
+ default: {
+ } break;
+ }
+ code += ";\n";
+ } break;
+ case SOURCE_SCREEN: {
+ if ((p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, "screen_tex") + " : hint_screen_texture;\n";
+ }
+ } break;
+ case SOURCE_DEPTH:
+ case SOURCE_3D_NORMAL:
+ case SOURCE_ROUGHNESS: {
+ if (p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
+ String sampler_name = "";
+ String hint = " : ";
+ if (source == SOURCE_DEPTH) {
+ sampler_name = "depth_tex";
+ hint += "hint_depth_texture;\n";
+ } else {
+ sampler_name = source == SOURCE_ROUGHNESS ? "roughness_tex" : "normal_roughness_tex";
+ hint += "hint_normal_roughness_texture;\n";
+ }
+ code += "uniform sampler2D " + make_unique_id(p_type, p_id, sampler_name) + hint;
+ }
+ } break;
+ default: {
+ } break;
}
- return String();
+ return code;
}
String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String default_uv;
if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
- default_uv = "UV";
+ if (source == SOURCE_SCREEN) {
+ default_uv = "SCREEN_UV";
+ } else {
+ default_uv = "UV";
+ }
} else {
default_uv = "vec2(0.0)";
}
String code;
- if (source == SOURCE_TEXTURE) {
- String id = make_unique_id(p_type, p_id, "tex");
- if (p_input_vars[0].is_empty()) { // Use UV by default.
+ String uv = p_input_vars[0].is_empty() ? default_uv : p_input_vars[0];
+
+ switch (source) {
+ case SOURCE_PORT:
+ case SOURCE_TEXTURE: {
+ String id;
+ if (source == SOURCE_PORT) {
+ id = p_input_vars[2];
+ if (id.is_empty()) {
+ break;
+ }
+ } else { // SOURCE_TEXTURE
+ id = make_unique_id(p_type, p_id, "tex");
+ }
if (p_input_vars[1].is_empty()) {
- code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
} else {
- code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
- }
- return code;
- }
-
- if (source == SOURCE_PORT) {
- String id = p_input_vars[2];
- if (id.is_empty()) {
- code += " " + p_output_vars[0] + " = vec4(0.0);\n";
- } else {
- if (p_input_vars[0].is_empty()) { // Use UV by default.
+ return code;
+ } break;
+ case SOURCE_SCREEN: {
+ if ((p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
+ String id = make_unique_id(p_type, p_id, "screen_tex");
if (p_input_vars[1].is_empty()) {
- code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
} else {
- code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
- }
- }
- return code;
- }
-
- if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
- if (p_input_vars[0].is_empty() || p_for_preview) { // Use UV by default.
- if (p_input_vars[1].is_empty()) {
- code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0);\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
+ return code;
}
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", 0.0);\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
- }
- return code;
- }
+ } break;
+ case SOURCE_2D_NORMAL:
+ case SOURCE_2D_TEXTURE: {
+ if (p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
+ String id = source == SOURCE_2D_TEXTURE ? "TEXTURE" : "NORMAL_TEXTURE";
- if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
- if (p_input_vars[0].is_empty()) { // Use UV by default.
- if (p_input_vars[1].is_empty()) {
- code += " " + p_output_vars[0] + " = texture(TEXTURE, " + default_uv + ");\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
+ if (p_input_vars[1].is_empty()) {
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
+ } else {
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
+ }
+ return code;
}
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " " + p_output_vars[0] + " = texture(TEXTURE, " + p_input_vars[0] + ");\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
- }
- return code;
- }
+ } break;
+ case SOURCE_3D_NORMAL:
+ case SOURCE_ROUGHNESS:
+ case SOURCE_DEPTH: {
+ if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
+ String var_name = "";
+ String sampler_name = "";
+
+ switch (source) {
+ case SOURCE_DEPTH: {
+ var_name = "_depth";
+ sampler_name = "depth_tex";
+ } break;
+ case SOURCE_ROUGHNESS: {
+ var_name = "_roughness";
+ sampler_name = "roughness_tex";
+ } break;
+ case SOURCE_3D_NORMAL: {
+ var_name = "_normal";
+ sampler_name = "normal_roughness_tex";
+ } break;
+ default: {
+ } break;
+ }
- if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
- if (p_input_vars[0].is_empty()) { // Use UV by default.
- if (p_input_vars[1].is_empty()) {
- code += " " + p_output_vars[0] + " = texture(NORMAL_TEXTURE, " + default_uv + ");\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
- }
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " " + p_output_vars[0] + " = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
- }
- return code;
- }
+ String id = make_unique_id(p_type, p_id, sampler_name);
+ String type = source == SOURCE_3D_NORMAL ? "vec3" : "float";
+ String components = source == SOURCE_3D_NORMAL ? "rgb" : "r";
- if (source == SOURCE_DEPTH) {
- if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
- code += " {\n";
- if (p_input_vars[0].is_empty()) { // Use UV by default.
+ code += " {\n";
if (p_input_vars[1].is_empty()) {
- code += " float _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n";
+ code += " " + type + " " + var_name + " = texture(" + id + ", " + uv + ")." + components + ";\n";
} else {
- code += " float _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n";
+ code += " " + type + " " + var_name + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ")." + components + ";\n";
}
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " float _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n";
- } else {
- code += " float _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n";
- }
+ if (source == SOURCE_3D_NORMAL) {
+ code += " " + p_output_vars[0] + " = vec4(" + var_name + ", 1.0);\n";
+ } else {
+ code += " " + p_output_vars[0] + " = vec4(" + var_name + ", " + var_name + ", " + var_name + ", 1.0);\n";
+ }
+ code += " }\n";
- code += " " + p_output_vars[0] + " = vec4(_depth, _depth, _depth, 1.0);\n";
- code += " }\n";
- return code;
- }
+ return code;
+ }
+ } break;
+ default: {
+ } break;
}
code += " " + p_output_vars[0] + " = vec4(0.0);\n";
@@ -921,12 +937,17 @@ void VisualShaderNodeTexture::set_source(Source p_source) {
case SOURCE_PORT:
simple_decl = false;
break;
+ case SOURCE_3D_NORMAL:
+ simple_decl = false;
+ break;
+ case SOURCE_ROUGHNESS:
+ simple_decl = false;
+ break;
default:
break;
}
source = p_source;
emit_changed();
- emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeTexture::Source VisualShaderNodeTexture::get_source() const {
@@ -970,31 +991,34 @@ String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::T
return RTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'.");
}
- if (source == SOURCE_TEXTURE) {
- return String(); // all good
- }
-
- if (source == SOURCE_PORT) {
- return String(); // all good
- }
-
- if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
- return String(); // all good
- }
-
- if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
- return String(); // all good
- }
-
- if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM) {
- return String(); // all good
- }
-
- if (source == SOURCE_DEPTH && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
- if (get_output_port_for_preview() == 0) { // DEPTH_TEXTURE is not supported in preview(canvas_item) shader
- return RTR("Invalid source for preview.");
- }
- return String(); // all good
+ switch (source) {
+ case SOURCE_TEXTURE:
+ case SOURCE_PORT: {
+ return String(); // All good.
+ } break;
+ case SOURCE_SCREEN: {
+ if ((p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
+ return String(); // All good.
+ }
+ } break;
+ case SOURCE_2D_NORMAL:
+ case SOURCE_2D_TEXTURE: {
+ if (p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
+ return String(); // All good.
+ }
+ } break;
+ case SOURCE_3D_NORMAL:
+ case SOURCE_ROUGHNESS:
+ case SOURCE_DEPTH: {
+ if (p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
+ if (get_output_port_for_preview() == 0) { // Not supported in preview(canvas_item) shader.
+ return RTR("Invalid source for preview.");
+ }
+ return String(); // All good.
+ }
+ } break;
+ default: {
+ } break;
}
return RTR("Invalid source for shader.");
@@ -1010,7 +1034,7 @@ void VisualShaderNodeTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_texture_type", "value"), &VisualShaderNodeTexture::set_texture_type);
ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeTexture::get_texture_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,Screen,Texture2D,NormalMap2D,Depth,SamplerPort"), "set_source", "get_source");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,Screen,Texture2D,NormalMap2D,Depth,SamplerPort,Normal3D,Roughness"), "set_source", "get_source");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map"), "set_texture_type", "get_texture_type");
@@ -1020,6 +1044,8 @@ void VisualShaderNodeTexture::_bind_methods() {
BIND_ENUM_CONSTANT(SOURCE_2D_NORMAL);
BIND_ENUM_CONSTANT(SOURCE_DEPTH);
BIND_ENUM_CONSTANT(SOURCE_PORT);
+ BIND_ENUM_CONSTANT(SOURCE_3D_NORMAL);
+ BIND_ENUM_CONSTANT(SOURCE_ROUGHNESS);
BIND_ENUM_CONSTANT(SOURCE_MAX);
BIND_ENUM_CONSTANT(TYPE_DATA);
@@ -1260,6 +1286,17 @@ bool VisualShaderNodeSample3D::is_input_port_default(int p_port, Shader::Mode p_
}
String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ String id;
+ if (source == SOURCE_TEXTURE) {
+ id = make_unique_id(p_type, p_id, "tex3d");
+ } else { // SOURCE_PORT
+ id = p_input_vars[2];
+ if (id.is_empty()) {
+ code += " " + p_output_vars[0] + " = vec4(0.0);\n";
+ return code;
+ }
+ }
String default_uv;
if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
default_uv = "vec3(UV, 0.0)";
@@ -1267,33 +1304,12 @@ String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader
default_uv = "vec3(0.0)";
}
- String code;
- if (source == SOURCE_TEXTURE || source == SOURCE_PORT) {
- String id;
- if (source == SOURCE_TEXTURE) {
- id = make_unique_id(p_type, p_id, "tex3d");
- } else {
- id = p_input_vars[2];
- }
- if (!id.is_empty()) {
- if (p_input_vars[0].is_empty()) { // Use UV by default.
- if (p_input_vars[1].is_empty()) {
- code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
- }
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
- }
- } else {
- code += " " + p_output_vars[0] + " = vec4(0.0);\n";
- }
- return code;
+ String uv = p_input_vars[0].is_empty() ? default_uv : p_input_vars[0];
+ if (p_input_vars[1].is_empty()) {
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
+ } else {
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
- code += " " + p_output_vars[0] + " = vec4(0.0);\n";
return code;
}
@@ -1304,7 +1320,6 @@ void VisualShaderNodeSample3D::set_source(Source p_source) {
}
source = p_source;
emit_changed();
- emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeSample3D::Source VisualShaderNodeSample3D::get_source() const {
@@ -1326,14 +1341,7 @@ String VisualShaderNodeSample3D::get_warning(Shader::Mode p_mode, VisualShader::
if (is_input_port_connected(2) && source != SOURCE_PORT) {
return RTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'.");
}
-
- if (source == SOURCE_TEXTURE) {
- return String(); // all good
- }
- if (source == SOURCE_PORT) {
- return String(); // all good
- }
- return RTR("Invalid source for shader.");
+ return String();
}
VisualShaderNodeSample3D::VisualShaderNodeSample3D() {
@@ -1539,42 +1547,33 @@ String VisualShaderNodeCubemap::generate_global(Shader::Mode p_mode, VisualShade
}
String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- String default_uv;
- if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
- default_uv = "vec3(UV, 0.0)";
- } else {
- default_uv = "vec3(0.0)";
- }
-
String code;
String id;
+
if (source == SOURCE_TEXTURE) {
id = make_unique_id(p_type, p_id, "cube");
- } else if (source == SOURCE_PORT) {
+ } else { // SOURCE_PORT
id = p_input_vars[2];
- } else {
- return code;
+ if (id.is_empty()) {
+ code += " " + p_output_vars[0] + " = vec4(0.0);\n";
+ return code;
+ }
}
- if (id.is_empty()) {
- code += " " + p_output_vars[0] + " = vec4(0.0);\n";
- return code;
+ String default_uv;
+ if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
+ default_uv = "vec3(UV, 0.0)";
+ } else {
+ default_uv = "vec3(0.0)";
}
- if (p_input_vars[0].is_empty()) { // Use UV by default.
-
- if (p_input_vars[1].is_empty()) {
- code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
- } else {
- code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
- }
-
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
+ String uv = p_input_vars[0].is_empty() ? default_uv : p_input_vars[0];
+ if (p_input_vars[1].is_empty()) {
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
} else {
- code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
+
return code;
}
@@ -1594,7 +1593,6 @@ void VisualShaderNodeCubemap::set_source(Source p_source) {
}
source = p_source;
emit_changed();
- emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeCubemap::Source VisualShaderNodeCubemap::get_source() const {
@@ -1702,11 +1700,15 @@ bool VisualShaderNodeLinearSceneDepth::has_output_port_preview(int p_port) const
return false;
}
+String VisualShaderNodeLinearSceneDepth::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ return "uniform sampler2D " + make_unique_id(p_type, p_id, "depth_tex") + " : hint_depth_texture;\n";
+}
+
String VisualShaderNodeLinearSceneDepth::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String code;
code += " {\n";
- code += " float __log_depth = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).x;\n";
+ code += " float __log_depth = textureLod(" + make_unique_id(p_type, p_id, "depth_tex") + ", SCREEN_UV, 0.0).x;\n";
code += " vec3 __depth_ndc = vec3(SCREEN_UV * 2.0 - 1.0, __log_depth);\n";
code += " vec4 __depth_view = INV_PROJECTION_MATRIX * vec4(__depth_ndc, 1.0);\n";
code += " __depth_view.xyz /= __depth_view.w;\n";
@@ -6101,7 +6103,7 @@ VisualShaderNodeTransformParameter::VisualShaderNodeTransformParameter() {
//////////////
-String get_sampler_hint(VisualShaderNodeTextureParameter::TextureType p_texture_type, VisualShaderNodeTextureParameter::ColorDefault p_color_default, VisualShaderNodeTextureParameter::TextureFilter p_texture_filter, VisualShaderNodeTextureParameter::TextureRepeat p_texture_repeat) {
+String get_sampler_hint(VisualShaderNodeTextureParameter::TextureType p_texture_type, VisualShaderNodeTextureParameter::ColorDefault p_color_default, VisualShaderNodeTextureParameter::TextureFilter p_texture_filter, VisualShaderNodeTextureParameter::TextureRepeat p_texture_repeat, VisualShaderNodeTextureParameter::TextureSource p_texture_source) {
String code;
bool has_colon = false;
@@ -6204,6 +6206,33 @@ String get_sampler_hint(VisualShaderNodeTextureParameter::TextureType p_texture_
}
}
+ {
+ String source_code;
+
+ switch (p_texture_source) {
+ case VisualShaderNodeTextureParameter::SOURCE_SCREEN:
+ source_code = "hint_screen_texture";
+ break;
+ case VisualShaderNodeTextureParameter::SOURCE_DEPTH:
+ source_code = "hint_depth_texture";
+ break;
+ case VisualShaderNodeTextureParameter::SOURCE_NORMAL_ROUGHNESS:
+ source_code = "hint_normal_roughness_texture";
+ break;
+ default:
+ break;
+ }
+
+ if (!source_code.is_empty()) {
+ if (!has_colon) {
+ code += " : ";
+ } else {
+ code += ", ";
+ }
+ code += source_code;
+ }
+ }
+
return code;
}
@@ -6290,6 +6319,19 @@ VisualShaderNodeTextureParameter::TextureRepeat VisualShaderNodeTextureParameter
return texture_repeat;
}
+void VisualShaderNodeTextureParameter::set_texture_source(TextureSource p_source) {
+ ERR_FAIL_INDEX(int(p_source), int(SOURCE_MAX));
+ if (texture_source == p_source) {
+ return;
+ }
+ texture_source = p_source;
+ emit_changed();
+}
+
+VisualShaderNodeTextureParameter::TextureSource VisualShaderNodeTextureParameter::get_texture_source() const {
+ return texture_source;
+}
+
Vector<StringName> VisualShaderNodeTextureParameter::get_editable_properties() const {
Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("texture_type");
@@ -6298,6 +6340,7 @@ Vector<StringName> VisualShaderNodeTextureParameter::get_editable_properties() c
}
props.push_back("texture_filter");
props.push_back("texture_repeat");
+ props.push_back("texture_source");
return props;
}
@@ -6311,6 +6354,7 @@ HashMap<StringName, String> VisualShaderNodeTextureParameter::get_editable_prope
names.insert("color_default", RTR("Default Color"));
names.insert("texture_filter", RTR("Filter"));
names.insert("texture_repeat", RTR("Repeat"));
+ names.insert("texture_source", RTR("Source"));
return names;
}
@@ -6318,19 +6362,23 @@ void VisualShaderNodeTextureParameter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_texture_type", "type"), &VisualShaderNodeTextureParameter::set_texture_type);
ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeTextureParameter::get_texture_type);
- ClassDB::bind_method(D_METHOD("set_color_default", "type"), &VisualShaderNodeTextureParameter::set_color_default);
+ ClassDB::bind_method(D_METHOD("set_color_default", "color"), &VisualShaderNodeTextureParameter::set_color_default);
ClassDB::bind_method(D_METHOD("get_color_default"), &VisualShaderNodeTextureParameter::get_color_default);
ClassDB::bind_method(D_METHOD("set_texture_filter", "filter"), &VisualShaderNodeTextureParameter::set_texture_filter);
ClassDB::bind_method(D_METHOD("get_texture_filter"), &VisualShaderNodeTextureParameter::get_texture_filter);
- ClassDB::bind_method(D_METHOD("set_texture_repeat", "type"), &VisualShaderNodeTextureParameter::set_texture_repeat);
+ ClassDB::bind_method(D_METHOD("set_texture_repeat", "repeat"), &VisualShaderNodeTextureParameter::set_texture_repeat);
ClassDB::bind_method(D_METHOD("get_texture_repeat"), &VisualShaderNodeTextureParameter::get_texture_repeat);
+ ClassDB::bind_method(D_METHOD("set_texture_source", "source"), &VisualShaderNodeTextureParameter::set_texture_source);
+ ClassDB::bind_method(D_METHOD("get_texture_source"), &VisualShaderNodeTextureParameter::get_texture_source);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map,Anisotropic"), "set_texture_type", "get_texture_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White,Black,Transparent"), "set_color_default", "get_color_default");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Default,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Default,Enabled,Disabled"), "set_texture_repeat", "get_texture_repeat");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_source", PROPERTY_HINT_ENUM, "None,Screen,Depth,NormalRoughness"), "set_texture_source", "get_texture_source");
BIND_ENUM_CONSTANT(TYPE_DATA);
BIND_ENUM_CONSTANT(TYPE_COLOR);
@@ -6356,6 +6404,12 @@ void VisualShaderNodeTextureParameter::_bind_methods() {
BIND_ENUM_CONSTANT(REPEAT_ENABLED);
BIND_ENUM_CONSTANT(REPEAT_DISABLED);
BIND_ENUM_CONSTANT(REPEAT_MAX);
+
+ BIND_ENUM_CONSTANT(SOURCE_NONE);
+ BIND_ENUM_CONSTANT(SOURCE_SCREEN);
+ BIND_ENUM_CONSTANT(SOURCE_DEPTH);
+ BIND_ENUM_CONSTANT(SOURCE_NORMAL_ROUGHNESS);
+ BIND_ENUM_CONSTANT(SOURCE_MAX);
}
bool VisualShaderNodeTextureParameter::is_qualifier_supported(Qualifier p_qual) const {
@@ -6396,7 +6450,7 @@ String VisualShaderNodeTexture2DParameter::get_output_port_name(int p_port) cons
String VisualShaderNodeTexture2DParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform sampler2D " + get_parameter_name();
- code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
+ code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source);
code += ";\n";
return code;
}
@@ -6407,7 +6461,7 @@ VisualShaderNodeTexture2DParameter::VisualShaderNodeTexture2DParameter() {
////////////// Texture Parameter (Triplanar)
String VisualShaderNodeTextureParameterTriplanar::get_caption() const {
- return "TextureUniformTriplanar";
+ return "TextureParameterTriplanar";
}
int VisualShaderNodeTextureParameterTriplanar::get_input_port_count() const {
@@ -6496,7 +6550,7 @@ String VisualShaderNodeTextureParameterTriplanar::generate_global_per_func(Shade
String VisualShaderNodeTextureParameterTriplanar::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform sampler2D " + get_parameter_name();
- code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
+ code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source);
code += ";\n";
return code;
}
@@ -6542,7 +6596,7 @@ String VisualShaderNodeTexture2DArrayParameter::get_output_port_name(int p_port)
String VisualShaderNodeTexture2DArrayParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform sampler2DArray " + get_parameter_name();
- code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
+ code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source);
code += ";\n";
return code;
}
@@ -6562,7 +6616,7 @@ String VisualShaderNodeTexture3DParameter::get_output_port_name(int p_port) cons
String VisualShaderNodeTexture3DParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform sampler3D " + get_parameter_name();
- code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
+ code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source);
code += ";\n";
return code;
}
@@ -6582,7 +6636,7 @@ String VisualShaderNodeCubemapParameter::get_output_port_name(int p_port) const
String VisualShaderNodeCubemapParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform samplerCube " + get_parameter_name();
- code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
+ code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source);
code += ";\n";
return code;
}
@@ -7640,12 +7694,15 @@ bool VisualShaderNodeProximityFade::has_output_port_preview(int p_port) const {
return false;
}
+String VisualShaderNodeProximityFade::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ return "uniform sampler2D " + make_unique_id(p_type, p_id, "depth_tex") + " : hint_depth_texture;\n";
+}
+
String VisualShaderNodeProximityFade::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String code;
code += " {\n";
- String proximity_fade_distance = vformat("%s", p_input_vars[0]);
- code += " float __depth_tex = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).r;\n";
+ code += " float __depth_tex = texture(" + make_unique_id(p_type, p_id, "depth_tex") + ", SCREEN_UV).r;\n";
if (!RenderingServer::get_singleton()->is_low_end()) {
code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, __depth_tex, 1.0);\n";
} else {
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 07843c0264..e3b101cf84 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -385,6 +385,8 @@ public:
SOURCE_2D_NORMAL,
SOURCE_DEPTH,
SOURCE_PORT,
+ SOURCE_3D_NORMAL,
+ SOURCE_ROUGHNESS,
SOURCE_MAX,
};
@@ -668,6 +670,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual bool has_output_port_preview(int p_port) const override;
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeLinearSceneDepth();
@@ -2362,11 +2365,20 @@ public:
REPEAT_MAX,
};
+ enum TextureSource {
+ SOURCE_NONE,
+ SOURCE_SCREEN,
+ SOURCE_DEPTH,
+ SOURCE_NORMAL_ROUGHNESS,
+ SOURCE_MAX,
+ };
+
protected:
TextureType texture_type = TYPE_DATA;
ColorDefault color_default = COLOR_DEFAULT_WHITE;
TextureFilter texture_filter = FILTER_DEFAULT;
TextureRepeat texture_repeat = REPEAT_DEFAULT;
+ TextureSource texture_source = SOURCE_NONE;
protected:
static void _bind_methods();
@@ -2398,6 +2410,9 @@ public:
void set_texture_repeat(TextureRepeat p_repeat);
TextureRepeat get_texture_repeat() const;
+ void set_texture_source(TextureSource p_source);
+ TextureSource get_texture_source() const;
+
bool is_qualifier_supported(Qualifier p_qual) const override;
bool is_convertible_to_constant() const override;
@@ -2408,6 +2423,7 @@ VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureType)
VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::ColorDefault)
VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureFilter)
VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureRepeat)
+VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureSource)
///////////////////////////////////////
@@ -2833,6 +2849,7 @@ public:
virtual String get_output_port_name(int p_port) const override;
virtual bool has_output_port_preview(int p_port) const override;
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
VisualShaderNodeProximityFade();