summaryrefslogtreecommitdiffstats
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/camera_2d.cpp2
-rw-r--r--scene/2d/skeleton_2d.cpp65
-rw-r--r--scene/3d/physics/character_body_3d.cpp2
-rw-r--r--scene/3d/xr_body_modifier_3d.cpp14
-rw-r--r--scene/3d/xr_body_modifier_3d.h2
-rw-r--r--scene/gui/graph_node.cpp23
-rw-r--r--scene/gui/popup_menu.cpp7
-rw-r--r--scene/gui/tab_container.cpp18
-rw-r--r--scene/gui/tab_container.h3
-rw-r--r--scene/gui/text_edit.cpp9
-rw-r--r--scene/gui/tree.cpp83
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d.cpp5
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d.h2
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d_ccdik.cpp13
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d_fabrik.cpp15
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d_jiggle.cpp11
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp9
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp2
-rw-r--r--scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp14
-rw-r--r--scene/resources/animation.h2
-rw-r--r--scene/resources/particle_process_material.cpp45
21 files changed, 216 insertions, 130 deletions
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 4b866fc6de..822f1b58fd 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -877,7 +877,7 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_margin_drawing_enabled"), &Camera2D::is_margin_drawing_enabled);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed Top Left,Drag Center"), "set_anchor_mode", "get_anchor_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_rotation"), "set_ignore_rotation", "is_ignoring_rotation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom", PROPERTY_HINT_LINK), "set_zoom", "get_zoom");
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 69e0414855..fe21c7f21b 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -635,36 +635,47 @@ Bone2D *Skeleton2D::get_bone(int p_idx) {
}
void Skeleton2D::_notification(int p_what) {
- if (p_what == NOTIFICATION_READY) {
- if (bone_setup_dirty) {
- _update_bone_setup();
- }
- if (transform_dirty) {
- _update_transform();
- }
- request_ready();
- }
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ if (bone_setup_dirty) {
+ _update_bone_setup();
+ }
+ if (transform_dirty) {
+ _update_transform();
+ }
+ request_ready();
+ } break;
- if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
- RS::get_singleton()->skeleton_set_base_transform_2d(skeleton, get_global_transform());
- } else if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
- if (modification_stack.is_valid()) {
- execute_modifications(get_process_delta_time(), SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_process);
- }
- } else if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
- if (modification_stack.is_valid()) {
- execute_modifications(get_physics_process_delta_time(), SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_physics_process);
- }
- }
-#ifdef TOOLS_ENABLED
- else if (p_what == NOTIFICATION_DRAW) {
- if (Engine::get_singleton()->is_editor_hint()) {
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ RS::get_singleton()->skeleton_set_base_transform_2d(skeleton, get_global_transform());
+ } break;
+
+ case NOTIFICATION_INTERNAL_PROCESS: {
if (modification_stack.is_valid()) {
- modification_stack->draw_editor_gizmos();
+ execute_modifications(get_process_delta_time(), SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_process);
}
- }
- }
+ } break;
+
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ if (modification_stack.is_valid()) {
+ execute_modifications(get_physics_process_delta_time(), SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_physics_process);
+ }
+ } break;
+
+ case NOTIFICATION_POST_ENTER_TREE: {
+ set_modification_stack(modification_stack);
+ } break;
+
+#ifdef TOOLS_ENABLED
+ case NOTIFICATION_DRAW: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (modification_stack.is_valid()) {
+ modification_stack->draw_editor_gizmos();
+ }
+ }
+ } break;
#endif // TOOLS_ENABLED
+ }
}
RID Skeleton2D::get_skeleton() const {
@@ -692,7 +703,7 @@ void Skeleton2D::set_modification_stack(Ref<SkeletonModificationStack2D> p_stack
set_physics_process_internal(false);
}
modification_stack = p_stack;
- if (modification_stack.is_valid()) {
+ if (modification_stack.is_valid() && is_inside_tree()) {
modification_stack->set_skeleton(this);
modification_stack->setup();
diff --git a/scene/3d/physics/character_body_3d.cpp b/scene/3d/physics/character_body_3d.cpp
index b13c279234..dda3ea9cca 100644
--- a/scene/3d/physics/character_body_3d.cpp
+++ b/scene/3d/physics/character_body_3d.cpp
@@ -232,7 +232,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
} else {
// Travel is too high to be safely canceled, we take it into account.
result.travel = result.travel.slide(up_direction);
- motion = motion.normalized() * result.travel.length();
+ motion = result.remainder;
}
set_global_transform(gt);
// Determines if you are on the ground, and limits the possibility of climbing on the walls because of the approximations.
diff --git a/scene/3d/xr_body_modifier_3d.cpp b/scene/3d/xr_body_modifier_3d.cpp
index 8aec3e856e..cf73882a7b 100644
--- a/scene/3d/xr_body_modifier_3d.cpp
+++ b/scene/3d/xr_body_modifier_3d.cpp
@@ -312,7 +312,7 @@ void XRBodyModifier3D::_process_modification() {
}
}
-void XRBodyModifier3D::_tracker_changed(const StringName &p_tracker_name, const Ref<XRBodyTracker> &p_tracker) {
+void XRBodyModifier3D::_tracker_changed(const StringName &p_tracker_name, XRServer::TrackerType p_tracker_type) {
if (tracker_name == p_tracker_name) {
_get_joint_data();
}
@@ -327,18 +327,18 @@ void XRBodyModifier3D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
XRServer *xr_server = XRServer::get_singleton();
if (xr_server) {
- xr_server->connect("body_tracker_added", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
- xr_server->connect("body_tracker_updated", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
- xr_server->connect("body_tracker_removed", callable_mp(this, &XRBodyModifier3D::_tracker_changed).bind(Ref<XRBodyTracker>()));
+ xr_server->connect("tracker_added", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
+ xr_server->connect("tracker_updated", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
+ xr_server->connect("tracker_removed", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
}
_get_joint_data();
} break;
case NOTIFICATION_EXIT_TREE: {
XRServer *xr_server = XRServer::get_singleton();
if (xr_server) {
- xr_server->disconnect("body_tracker_added", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
- xr_server->disconnect("body_tracker_updated", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
- xr_server->disconnect("body_tracker_removed", callable_mp(this, &XRBodyModifier3D::_tracker_changed).bind(Ref<XRBodyTracker>()));
+ xr_server->disconnect("tracker_added", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
+ xr_server->disconnect("tracker_updated", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
+ xr_server->disconnect("tracker_removed", callable_mp(this, &XRBodyModifier3D::_tracker_changed));
}
for (int i = 0; i < XRBodyTracker::JOINT_MAX; i++) {
joints[i].bone = -1;
diff --git a/scene/3d/xr_body_modifier_3d.h b/scene/3d/xr_body_modifier_3d.h
index 9ff0cd7207..78d70146ee 100644
--- a/scene/3d/xr_body_modifier_3d.h
+++ b/scene/3d/xr_body_modifier_3d.h
@@ -86,7 +86,7 @@ private:
JointData joints[XRBodyTracker::JOINT_MAX];
void _get_joint_data();
- void _tracker_changed(const StringName &p_tracker_name, const Ref<XRBodyTracker> &p_tracker);
+ void _tracker_changed(const StringName &p_tracker_name, XRServer::TrackerType p_tracker_type);
};
VARIANT_BITFIELD_CAST(XRBodyModifier3D::BodyUpdate)
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 1b960a9b62..d035515b51 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -336,7 +336,8 @@ void GraphNode::_notification(int p_what) {
int width = get_size().width - sb_panel->get_minimum_size().x;
- if (get_child_count() > 0) {
+ // Take the HboxContainer child into account.
+ if (get_child_count(false) > 0) {
int slot_index = 0;
for (const KeyValue<int, Slot> &E : slot_table) {
if (E.key < 0 || E.key >= slot_y_cache.size()) {
@@ -647,6 +648,7 @@ void GraphNode::_port_pos_update() {
left_port_cache.clear();
right_port_cache.clear();
int vertical_ofs = titlebar_hbox->get_size().height + sb_titlebar->get_minimum_size().height + sb_panel->get_margin(SIDE_TOP);
+ int slot_index = 0;
for (int i = 0; i < get_child_count(false); i++) {
Control *child = Object::cast_to<Control>(get_child(i, false));
@@ -656,27 +658,28 @@ void GraphNode::_port_pos_update() {
Size2i size = child->get_rect().size;
- if (slot_table.has(i)) {
- if (slot_table[i].enable_left) {
+ if (slot_table.has(slot_index)) {
+ if (slot_table[slot_index].enable_left) {
PortCache port_cache;
port_cache.pos = Point2i(edgeofs, vertical_ofs + size.height / 2);
- port_cache.type = slot_table[i].type_left;
- port_cache.color = slot_table[i].color_left;
- port_cache.slot_index = child->get_index(false);
+ port_cache.type = slot_table[slot_index].type_left;
+ port_cache.color = slot_table[slot_index].color_left;
+ port_cache.slot_index = slot_index;
left_port_cache.push_back(port_cache);
}
- if (slot_table[i].enable_right) {
+ if (slot_table[slot_index].enable_right) {
PortCache port_cache;
port_cache.pos = Point2i(get_size().width - edgeofs, vertical_ofs + size.height / 2);
- port_cache.type = slot_table[i].type_right;
- port_cache.color = slot_table[i].color_right;
- port_cache.slot_index = child->get_index(false);
+ port_cache.type = slot_table[slot_index].type_right;
+ port_cache.color = slot_table[slot_index].color_right;
+ port_cache.slot_index = slot_index;
right_port_cache.push_back(port_cache);
}
}
vertical_ofs += separation;
vertical_ofs += size.height;
+ slot_index++;
}
port_pos_dirty = false;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 260956a775..9b991972be 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -276,6 +276,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
}
}
+ minsize.height = Math::ceil(minsize.height); // Ensures enough height at fractional content scales to prevent the v_scroll_bar from showing.
return minsize;
}
@@ -2832,9 +2833,9 @@ void PopupMenu::popup(const Rect2i &p_bounds) {
if (!is_embedded()) {
float win_scale = get_parent_visible_window()->get_content_scale_factor();
set_content_scale_factor(win_scale);
- Size2 minsize = get_contents_minimum_size();
- minsize.height += 0.5 * win_scale; // Ensures enough height at fractional content scales to prevent the v_scroll_bar from showing.
- set_min_size(minsize * win_scale);
+ Size2 minsize = get_contents_minimum_size() * win_scale;
+ minsize.height = Math::ceil(minsize.height); // Ensures enough height at fractional content scales to prevent the v_scroll_bar from showing.
+ set_min_size(minsize); // `height` is truncated here by the cast to Size2i for Window.min_size.
set_size(Vector2(0, 0)); // Shrinkwraps to min size.
}
Popup::popup(p_bounds);
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 05f44891f6..e2feb59a8c 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -794,6 +794,22 @@ Ref<Texture2D> TabContainer::get_tab_icon(int p_tab) const {
return tab_bar->get_tab_icon(p_tab);
}
+void TabContainer::set_tab_icon_max_width(int p_tab, int p_width) {
+ if (tab_bar->get_tab_icon_max_width(p_tab) == p_width) {
+ return;
+ }
+
+ tab_bar->set_tab_icon_max_width(p_tab, p_width);
+
+ _update_margins();
+ _repaint();
+ queue_redraw();
+}
+
+int TabContainer::get_tab_icon_max_width(int p_tab) const {
+ return tab_bar->get_tab_icon_max_width(p_tab);
+}
+
void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) {
if (tab_bar->is_tab_disabled(p_tab) == p_disabled) {
return;
@@ -990,6 +1006,8 @@ void TabContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tab_tooltip", "tab_idx"), &TabContainer::get_tab_tooltip);
ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &TabContainer::set_tab_icon);
ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &TabContainer::get_tab_icon);
+ ClassDB::bind_method(D_METHOD("set_tab_icon_max_width", "tab_idx", "width"), &TabContainer::set_tab_icon_max_width);
+ ClassDB::bind_method(D_METHOD("get_tab_icon_max_width", "tab_idx"), &TabContainer::get_tab_icon_max_width);
ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabContainer::set_tab_disabled);
ClassDB::bind_method(D_METHOD("is_tab_disabled", "tab_idx"), &TabContainer::is_tab_disabled);
ClassDB::bind_method(D_METHOD("set_tab_hidden", "tab_idx", "hidden"), &TabContainer::set_tab_hidden);
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index c11d9824e7..e00bc780d4 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -161,6 +161,9 @@ public:
void set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon);
Ref<Texture2D> get_tab_icon(int p_tab) const;
+ void set_tab_icon_max_width(int p_tab, int p_width);
+ int get_tab_icon_max_width(int p_tab) const;
+
void set_tab_disabled(int p_tab, bool p_disabled);
bool is_tab_disabled(int p_tab) const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 0bb77a92f2..39fba72e09 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -752,16 +752,15 @@ void TextEdit::_notification(int p_what) {
// Draw the minimap.
// Add visual feedback when dragging or hovering the visible area rectangle.
- float viewport_alpha;
+ Color viewport_color = theme_cache.caret_color;
if (dragging_minimap) {
- viewport_alpha = 0.25;
+ viewport_color.a = 0.25;
} else if (hovering_minimap) {
- viewport_alpha = 0.175;
+ viewport_color.a = 0.175;
} else {
- viewport_alpha = 0.1;
+ viewport_color.a = 0.1;
}
- const Color viewport_color = (theme_cache.background_color.get_v() < 0.5) ? Color(1, 1, 1, viewport_alpha) : Color(0, 0, 0, viewport_alpha);
if (rtl) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, viewport_offset_y, minimap_width, viewport_height), viewport_color);
} else {
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 982473deee..b17d345f1f 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -379,8 +379,8 @@ void TreeItem::set_text_overrun_behavior(int p_column, TextServer::OverrunBehavi
cells.write[p_column].text_buf->set_text_overrun_behavior(p_behavior);
cells.write[p_column].dirty = true;
- _changed_notify(p_column);
cells.write[p_column].cached_minimum_size_dirty = true;
+ _changed_notify(p_column);
}
TextServer::OverrunBehavior TreeItem::get_text_overrun_behavior(int p_column) const {
@@ -1512,7 +1512,9 @@ Size2 TreeItem::get_minimum_size(int p_column) {
const TreeItem::Cell &cell = cells[p_column];
if (cell.cached_minimum_size_dirty) {
- Size2 size;
+ Size2 size = Size2(
+ parent_tree->theme_cache.inner_item_margin_left + parent_tree->theme_cache.inner_item_margin_right,
+ parent_tree->theme_cache.inner_item_margin_top + parent_tree->theme_cache.inner_item_margin_bottom);
// Text.
if (!cell.text.is_empty()) {
@@ -1520,7 +1522,9 @@ Size2 TreeItem::get_minimum_size(int p_column) {
parent_tree->update_item_cell(this, p_column);
}
Size2 text_size = cell.text_buf->get_size();
- size.width += text_size.width;
+ if (get_text_overrun_behavior(p_column) == TextServer::OVERRUN_NO_TRIMMING) {
+ size.width += text_size.width;
+ }
size.height = MAX(size.height, text_size.height);
}
@@ -1539,13 +1543,10 @@ Size2 TreeItem::get_minimum_size(int p_column) {
Ref<Texture2D> texture = cell.buttons[i].texture;
if (texture.is_valid()) {
Size2 button_size = texture->get_size() + parent_tree->theme_cache.button_pressed->get_minimum_size();
- size.width += button_size.width;
+ size.width += button_size.width + parent_tree->theme_cache.button_margin;
size.height = MAX(size.height, button_size.height);
}
}
- if (cell.buttons.size() >= 2) {
- size.width += (cell.buttons.size() - 1) * parent_tree->theme_cache.button_margin;
- }
cells.write[p_column].cached_minimum_size = size;
cells.write[p_column].cached_minimum_size_dirty = false;
@@ -4394,17 +4395,23 @@ void Tree::_update_all() {
}
Size2 Tree::get_minimum_size() const {
- if (h_scroll_enabled && v_scroll_enabled) {
- return Size2();
- } else {
- Vector2 min_size = get_internal_min_size();
- Ref<StyleBox> bg = theme_cache.panel_style;
- if (bg.is_valid()) {
- min_size.x += bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
- min_size.y += bg->get_margin(SIDE_TOP) + bg->get_margin(SIDE_BOTTOM);
- }
- return Vector2(h_scroll_enabled ? 0 : min_size.x, v_scroll_enabled ? 0 : min_size.y);
+ Vector2 min_size = Vector2(0, _get_title_button_height());
+
+ if (theme_cache.panel_style.is_valid()) {
+ min_size += theme_cache.panel_style->get_minimum_size();
+ }
+
+ Vector2 content_min_size = get_internal_min_size();
+ if (h_scroll_enabled) {
+ content_min_size.x = 0;
+ min_size.y += h_scroll->get_combined_minimum_size().height;
+ }
+ if (v_scroll_enabled) {
+ min_size.x += v_scroll->get_combined_minimum_size().width;
+ content_min_size.y = 0;
}
+
+ return min_size + content_min_size;
}
TreeItem *Tree::create_item(TreeItem *p_parent, int p_index) {
@@ -4582,6 +4589,7 @@ void Tree::set_hide_root(bool p_enabled) {
hide_root = p_enabled;
queue_redraw();
+ update_minimum_size();
}
bool Tree::is_root_hidden() const {
@@ -4730,31 +4738,33 @@ int Tree::get_column_minimum_width(int p_column) const {
min_width = MAX(theme_cache.font->get_string_size(columns[p_column].xl_title, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + padding, min_width);
}
- if (!columns[p_column].clip_content) {
- int depth = 0;
- TreeItem *next;
- for (TreeItem *item = get_root(); item; item = next) {
- next = item->get_next_visible();
- // Compute the depth in tree.
- if (next && p_column == 0) {
- if (next->get_parent() == item) {
- depth += 1;
- } else {
- TreeItem *common_parent = item->get_parent();
- while (common_parent != next->get_parent() && common_parent) {
- common_parent = common_parent->get_parent();
- depth -= 1;
+ if (root && !columns[p_column].clip_content) {
+ int depth = 1;
+
+ TreeItem *last = nullptr;
+ TreeItem *first = hide_root ? root->get_next_visible() : root;
+ for (TreeItem *item = first; item; last = item, item = item->get_next_visible()) {
+ // Get column indentation.
+ int indent;
+ if (p_column == 0) {
+ if (last) {
+ if (item->parent == last) {
+ depth += 1;
+ } else if (item->parent != last->parent) {
+ depth = hide_root ? 0 : 1;
+ for (TreeItem *iter = item->parent; iter; iter = iter->parent) {
+ depth += 1;
+ }
}
}
+ indent = theme_cache.item_margin * depth;
+ } else {
+ indent = theme_cache.h_separation;
}
// Get the item minimum size.
Size2 item_size = item->get_minimum_size(p_column);
- if (p_column == 0) {
- item_size.width += theme_cache.item_margin * depth;
- } else {
- item_size.width += theme_cache.h_separation;
- }
+ item_size.width += indent;
// Check if the item is wider.
min_width = MAX(min_width, item_size.width);
@@ -4968,6 +4978,7 @@ void Tree::set_column_titles_visible(bool p_show) {
show_column_titles = p_show;
queue_redraw();
+ update_minimum_size();
}
bool Tree::are_column_titles_visible() const {
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d.cpp
index 4e7563fdc3..5450f544c3 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d.cpp
@@ -233,6 +233,11 @@ void SkeletonModification2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "execution_mode", PROPERTY_HINT_ENUM, "process,physics_process"), "set_execution_mode", "get_execution_mode");
}
+void SkeletonModification2D::reset_state() {
+ stack = nullptr;
+ is_setup = false;
+}
+
SkeletonModification2D::SkeletonModification2D() {
stack = nullptr;
is_setup = false;
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d.h b/scene/resources/2d/skeleton/skeleton_modification_2d.h
index 413b860a99..6a6f1bb39b 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d.h
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d.h
@@ -57,6 +57,8 @@ protected:
bool _print_execution_error(bool p_condition, String p_message);
+ virtual void reset_state() override;
+
GDVIRTUAL1(_execute, double)
GDVIRTUAL1(_setup_modification, Ref<SkeletonModificationStack2D>)
GDVIRTUAL0(_draw_editor_gizmo)
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_ccdik.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_ccdik.cpp
index 1ad8d0eccc..051c4eabc0 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d_ccdik.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d_ccdik.cpp
@@ -266,7 +266,9 @@ void SkeletonModification2DCCDIK::_draw_editor_gizmo() {
void SkeletonModification2DCCDIK::update_target_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ }
return;
}
@@ -287,7 +289,9 @@ void SkeletonModification2DCCDIK::update_target_cache() {
void SkeletonModification2DCCDIK::update_tip_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update tip cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update tip cache: modification is not properly setup!");
+ }
return;
}
@@ -309,7 +313,9 @@ void SkeletonModification2DCCDIK::update_tip_cache() {
void SkeletonModification2DCCDIK::ccdik_joint_update_bone2d_cache(int p_joint_idx) {
ERR_FAIL_INDEX_MSG(p_joint_idx, ccdik_data_chain.size(), "Cannot update bone2d cache: joint index out of range!");
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update CCDIK Bone2D cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update CCDIK Bone2D cache: modification is not properly setup!");
+ }
return;
}
@@ -390,7 +396,6 @@ void SkeletonModification2DCCDIK::set_ccdik_joint_bone_index(int p_joint_idx, in
ccdik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
}
} else {
- WARN_PRINT("Cannot verify the CCDIK joint " + itos(p_joint_idx) + " bone index for this modification...");
ccdik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
}
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_fabrik.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_fabrik.cpp
index dd1c4a91d5..16a6166878 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d_fabrik.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d_fabrik.cpp
@@ -289,13 +289,21 @@ void SkeletonModification2DFABRIK::_setup_modification(SkeletonModificationStack
if (stack != nullptr) {
is_setup = true;
+
+ if (stack->skeleton) {
+ for (int i = 0; i < fabrik_data_chain.size(); i++) {
+ fabrik_joint_update_bone2d_cache(i);
+ }
+ }
update_target_cache();
}
}
void SkeletonModification2DFABRIK::update_target_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ }
return;
}
@@ -317,7 +325,9 @@ void SkeletonModification2DFABRIK::update_target_cache() {
void SkeletonModification2DFABRIK::fabrik_joint_update_bone2d_cache(int p_joint_idx) {
ERR_FAIL_INDEX_MSG(p_joint_idx, fabrik_data_chain.size(), "Cannot update bone2d cache: joint index out of range!");
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update FABRIK Bone2D cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update FABRIK Bone2D cache: modification is not properly setup!");
+ }
return;
}
@@ -389,7 +399,6 @@ void SkeletonModification2DFABRIK::set_fabrik_joint_bone_index(int p_joint_idx,
fabrik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
}
} else {
- WARN_PRINT("Cannot verify the FABRIK joint " + itos(p_joint_idx) + " bone index for this modification...");
fabrik_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
}
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_jiggle.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_jiggle.cpp
index 2ace9577e4..b7200b49c4 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d_jiggle.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d_jiggle.cpp
@@ -254,6 +254,8 @@ void SkeletonModification2DJiggle::_setup_modification(SkeletonModificationStack
Bone2D *bone2d_node = stack->skeleton->get_bone(bone_idx);
jiggle_data_chain.write[i].dynamic_position = bone2d_node->get_global_position();
}
+
+ jiggle_joint_update_bone2d_cache(i);
}
}
@@ -263,7 +265,9 @@ void SkeletonModification2DJiggle::_setup_modification(SkeletonModificationStack
void SkeletonModification2DJiggle::update_target_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ }
return;
}
@@ -285,7 +289,9 @@ void SkeletonModification2DJiggle::update_target_cache() {
void SkeletonModification2DJiggle::jiggle_joint_update_bone2d_cache(int p_joint_idx) {
ERR_FAIL_INDEX_MSG(p_joint_idx, jiggle_data_chain.size(), "Cannot update bone2d cache: joint index out of range!");
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update Jiggle " + itos(p_joint_idx) + " Bone2D cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update Jiggle " + itos(p_joint_idx) + " Bone2D cache: modification is not properly setup!");
+ }
return;
}
@@ -425,7 +431,6 @@ void SkeletonModification2DJiggle::set_jiggle_joint_bone_index(int p_joint_idx,
jiggle_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
}
} else {
- WARN_PRINT("Cannot verify the Jiggle joint " + itos(p_joint_idx) + " bone index for this modification...");
jiggle_data_chain.write[p_joint_idx].bone_idx = p_bone_idx;
}
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp
index 8f6f6bc4ae..cd4ca8e090 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp
@@ -200,7 +200,9 @@ void SkeletonModification2DLookAt::_draw_editor_gizmo() {
void SkeletonModification2DLookAt::update_bone2d_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update Bone2D cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update Bone2D cache: modification is not properly setup!");
+ }
return;
}
@@ -256,7 +258,6 @@ void SkeletonModification2DLookAt::set_bone_index(int p_bone_idx) {
bone_idx = p_bone_idx;
}
} else {
- WARN_PRINT("Cannot verify the bone index for this modification...");
bone_idx = p_bone_idx;
}
@@ -265,7 +266,9 @@ void SkeletonModification2DLookAt::set_bone_index(int p_bone_idx) {
void SkeletonModification2DLookAt::update_target_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ }
return;
}
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp
index 61e5aed150..aa8d7d0b3b 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d_physicalbones.cpp
@@ -153,7 +153,7 @@ void SkeletonModification2DPhysicalBones::_setup_modification(SkeletonModificati
void SkeletonModification2DPhysicalBones::_physical_bone_update_cache(int p_joint_idx) {
ERR_FAIL_INDEX_MSG(p_joint_idx, physical_bone_chain.size(), "Cannot update PhysicalBone2D cache: joint index out of range!");
if (!is_setup || !stack) {
- if (!stack) {
+ if (is_setup) {
ERR_PRINT_ONCE("Cannot update PhysicalBone2D cache: modification is not properly setup!");
}
return;
diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp
index c3366d5c36..41e4ea828e 100644
--- a/scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp
+++ b/scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp
@@ -250,7 +250,9 @@ void SkeletonModification2DTwoBoneIK::_draw_editor_gizmo() {
void SkeletonModification2DTwoBoneIK::update_target_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!");
+ }
return;
}
@@ -271,7 +273,9 @@ void SkeletonModification2DTwoBoneIK::update_target_cache() {
void SkeletonModification2DTwoBoneIK::update_joint_one_bone2d_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update joint one Bone2D cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update joint one Bone2D cache: modification is not properly setup!");
+ }
return;
}
@@ -299,7 +303,9 @@ void SkeletonModification2DTwoBoneIK::update_joint_one_bone2d_cache() {
void SkeletonModification2DTwoBoneIK::update_joint_two_bone2d_cache() {
if (!is_setup || !stack) {
- ERR_PRINT_ONCE("Cannot update joint two Bone2D cache: modification is not properly setup!");
+ if (is_setup) {
+ ERR_PRINT_ONCE("Cannot update joint two Bone2D cache: modification is not properly setup!");
+ }
return;
}
@@ -400,7 +406,6 @@ void SkeletonModification2DTwoBoneIK::set_joint_one_bone_idx(int p_bone_idx) {
joint_one_bone_idx = p_bone_idx;
}
} else {
- WARN_PRINT("TwoBoneIK: Cannot verify the joint bone index for joint one...");
joint_one_bone_idx = p_bone_idx;
}
@@ -425,7 +430,6 @@ void SkeletonModification2DTwoBoneIK::set_joint_two_bone_idx(int p_bone_idx) {
joint_two_bone_idx = p_bone_idx;
}
} else {
- WARN_PRINT("TwoBoneIK: Cannot verify the joint bone index for joint two...");
joint_two_bone_idx = p_bone_idx;
}
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index c72327e464..6005172c11 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -266,7 +266,7 @@ private:
_FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const;
double length = 1.0;
- real_t step = 0.1;
+ real_t step = 1.0 / 30;
LoopMode loop_mode = LOOP_NONE;
void _track_update_hash(int p_track);
diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp
index 30b90841e3..685625ab72 100644
--- a/scene/resources/particle_process_material.cpp
+++ b/scene/resources/particle_process_material.cpp
@@ -741,26 +741,33 @@ void ParticleProcessMaterial::_update_shader() {
code += "vec3 get_random_direction_from_spread(inout uint alt_seed, float spread_angle){\n";
code += " float pi = 3.14159;\n";
code += " float degree_to_rad = pi / 180.0;\n";
- code += " vec3 velocity = vec3(0.);\n";
code += " float spread_rad = spread_angle * degree_to_rad;\n";
- code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n";
- code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n";
- code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n";
- code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n";
- code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n";
- code += " vec3 spread_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n";
- code += " vec3 direction_nrm = length(direction) > 0.0 ? normalize(direction) : vec3(0.0, 0.0, 1.0);\n";
- code += " // rotate spread to direction\n";
- code += " vec3 binormal = cross(vec3(0.0, 1.0, 0.0), direction_nrm);\n";
- code += " if (length(binormal) < 0.0001) {\n";
- code += " // direction is parallel to Y. Choose Z as the binormal.\n";
- code += " binormal = vec3(0.0, 0.0, 1.0);\n";
- code += " }\n";
- code += " binormal = normalize(binormal);\n";
- code += " vec3 normal = cross(binormal, direction_nrm);\n";
- code += " spread_direction = binormal * spread_direction.x + normal * spread_direction.y + direction_nrm * spread_direction.z;\n";
- code += " return spread_direction;\n";
-
+ if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
+ // Spread calculation for 2D.
+ code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n";
+ code += " angle1_rad += direction.x != 0.0 ? atan(direction.y, direction.x) : sign(direction.y) * (pi / 2.0);\n";
+ code += " vec3 spread_direction = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n";
+ code += " return spread_direction;\n";
+ } else {
+ // Spread calculation for 3D.
+ code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n";
+ code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n";
+ code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n";
+ code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n";
+ code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n";
+ code += " vec3 spread_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n";
+ code += " vec3 direction_nrm = length(direction) > 0.0 ? normalize(direction) : vec3(0.0, 0.0, 1.0);\n";
+ code += " // rotate spread to direction\n";
+ code += " vec3 binormal = cross(vec3(0.0, 1.0, 0.0), direction_nrm);\n";
+ code += " if (length(binormal) < 0.0001) {\n";
+ code += " // direction is parallel to Y. Choose Z as the binormal.\n";
+ code += " binormal = vec3(0.0, 0.0, 1.0);\n";
+ code += " }\n";
+ code += " binormal = normalize(binormal);\n";
+ code += " vec3 normal = cross(binormal, direction_nrm);\n";
+ code += " spread_direction = binormal * spread_direction.x + normal * spread_direction.y + direction_nrm * spread_direction.z;\n";
+ code += " return normalize(spread_direction);\n";
+ }
code += "}\n";
code += "vec3 process_radial_displacement(DynamicsParameters param, float lifetime, inout uint alt_seed, mat4 transform, mat4 emission_transform, float delta){\n";