diff --git a/doc/classes/SoftBody3D.xml b/doc/classes/SoftBody3D.xml
index 195196b78ca..4d8791d8c1f 100644
--- a/doc/classes/SoftBody3D.xml
+++ b/doc/classes/SoftBody3D.xml
@@ -87,6 +87,7 @@
+
Sets the pinned state of a surface vertex. When set to [code]true[/code], the optional [param attachment_path] can define a [Node3D] the pinned vertex will be attached to.
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index d0d4f6098c8..55649a31dc8 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -1951,9 +1951,8 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) {
surface->queue_redraw();
} else {
if (_edit.gizmo.is_valid()) {
- if (_edit.original_mouse_pos != _edit.mouse_pos) {
- _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, false);
- }
+ _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, false);
+ spatial_editor->get_single_selected_node()->update_gizmos();
_edit.gizmo = Ref();
break;
}
diff --git a/misc/extension_api_validation/4.3-stable.expected b/misc/extension_api_validation/4.3-stable.expected
index ad77e30e11c..06933b58412 100644
--- a/misc/extension_api_validation/4.3-stable.expected
+++ b/misc/extension_api_validation/4.3-stable.expected
@@ -80,3 +80,10 @@ GH-94434
Validate extension JSON: Error: Field 'classes/OS/methods/execute_with_pipe/arguments': size changed value in new API, from 2 to 3.
Optional argument added. Compatibility method registered.
+
+
+GH-94684
+--------
+Validate extension JSON: Error: Field 'classes/SoftBody3D/methods/set_point_pinned/arguments': size changed value in new API, from 3 to 4.
+
+Optional argument added to allow for adding pin point at specific index. Compatibility method registered.
diff --git a/scene/3d/soft_body_3d.compat.inc b/scene/3d/soft_body_3d.compat.inc
new file mode 100644
index 00000000000..0b01bfeb1f3
--- /dev/null
+++ b/scene/3d/soft_body_3d.compat.inc
@@ -0,0 +1,41 @@
+/**************************************************************************/
+/* soft_body_3d.compat.inc */
+/**************************************************************************/
+/* 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 DISABLE_DEPRECATED
+
+void SoftBody3D::_pin_point_bind_compat_94684(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) {
+ pin_point(p_point_index, pin, p_spatial_attachment_path, -1);
+}
+
+void SoftBody3D::_bind_compatibility_methods() {
+ ClassDB::bind_compatibility_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path"), &SoftBody3D::_pin_point_bind_compat_94684, DEFVAL(NodePath()));
+}
+
+#endif // DISABLE_DEPRECATED
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 7f67bde0cf8..b0fc94d75f8 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -29,6 +29,7 @@
/**************************************************************************/
#include "soft_body_3d.h"
+#include "soft_body_3d.compat.inc"
#include "scene/3d/physics/physics_body_3d.h"
@@ -200,12 +201,18 @@ bool SoftBody3D::_set_property_pinned_points_indices(const Array &p_indices) {
int point_index;
for (int i = 0; i < p_indices_size; ++i) {
point_index = p_indices.get(i);
- if (w[i].point_index != point_index) {
- if (-1 != w[i].point_index) {
+ if (w[i].point_index != point_index || pinned_points.size() < p_indices_size) {
+ bool insert = false;
+ if (w[i].point_index != -1 && p_indices.find(w[i].point_index) == -1) {
pin_point(w[i].point_index, false);
+ insert = true;
}
w[i].point_index = point_index;
- pin_point(w[i].point_index, true);
+ if (insert) {
+ pin_point(w[i].point_index, true, NodePath(), i);
+ } else {
+ pin_point(w[i].point_index, true);
+ }
}
}
return true;
@@ -356,7 +363,7 @@ void SoftBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_transform", "point_index"), &SoftBody3D::get_point_transform);
- ClassDB::bind_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path"), &SoftBody3D::pin_point, DEFVAL(NodePath()));
+ ClassDB::bind_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path", "insert_at"), &SoftBody3D::pin_point, DEFVAL(NodePath()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("is_point_pinned", "point_index"), &SoftBody3D::is_point_pinned);
ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftBody3D::set_ray_pickable);
@@ -668,10 +675,11 @@ void SoftBody3D::pin_point_toggle(int p_point_index) {
pin_point(p_point_index, !(-1 != _has_pinned_point(p_point_index)));
}
-void SoftBody3D::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) {
+void SoftBody3D::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path, int p_insert_at) {
+ ERR_FAIL_COND_MSG(p_insert_at < -1 || p_insert_at >= pinned_points.size(), "Invalid index for pin point insertion position.");
_pin_point_on_physics_server(p_point_index, pin);
if (pin) {
- _add_pinned_point(p_point_index, p_spatial_attachment_path);
+ _add_pinned_point(p_point_index, p_spatial_attachment_path, p_insert_at);
} else {
_remove_pinned_point(p_point_index);
}
@@ -730,7 +738,7 @@ void SoftBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) {
PhysicsServer3D::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin);
}
-void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) {
+void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path, int p_insert_at) {
SoftBody3D::PinnedPoint *pinned_point;
if (-1 == _get_pinned_point(p_point_index, pinned_point)) {
// Create new
@@ -743,7 +751,11 @@ void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_
pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index));
}
- pinned_points.push_back(pp);
+ if (p_insert_at != -1) {
+ pinned_points.insert(p_insert_at, pp);
+ } else {
+ pinned_points.push_back(pp);
+ }
} else {
pinned_point->point_index = p_point_index;
diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h
index ab30f7e654f..b01d462d9f1 100644
--- a/scene/3d/soft_body_3d.h
+++ b/scene/3d/soft_body_3d.h
@@ -126,6 +126,11 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+#ifndef DISABLE_DEPRECATED
+ void _pin_point_bind_compat_94684(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path = NodePath());
+ static void _bind_compatibility_methods();
+#endif
+
PackedStringArray get_configuration_warnings() const override;
public:
@@ -177,7 +182,7 @@ public:
Vector3 get_point_transform(int p_point_index);
void pin_point_toggle(int p_point_index);
- void pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path = NodePath());
+ void pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path = NodePath(), int p_insert_at = -1);
bool is_point_pinned(int p_point_index) const;
void _pin_point_deferred(int p_point_index, bool pin, const NodePath p_spatial_attachment_path);
@@ -193,7 +198,7 @@ private:
void _update_cache_pin_points_datas();
void _pin_point_on_physics_server(int p_point_index, bool pin);
- void _add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path);
+ void _add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path, int p_insert_at = -1);
void _reset_points_offsets();
void _remove_pinned_point(int p_point_index);