소스 검색

Merge pull request #59226 from Rindbee/better-setters-in-gui-controls

Improve the setters in gui, return directly if the value does not change.
Yuri Sizov 2 년 전
부모
커밋
5d14d08702

+ 12 - 0
scene/gui/aspect_ratio_container.cpp

@@ -51,21 +51,33 @@ Size2 AspectRatioContainer::get_minimum_size() const {
 }
 
 void AspectRatioContainer::set_ratio(float p_ratio) {
+	if (ratio == p_ratio) {
+		return;
+	}
 	ratio = p_ratio;
 	queue_sort();
 }
 
 void AspectRatioContainer::set_stretch_mode(StretchMode p_mode) {
+	if (stretch_mode == p_mode) {
+		return;
+	}
 	stretch_mode = p_mode;
 	queue_sort();
 }
 
 void AspectRatioContainer::set_alignment_horizontal(AlignmentMode p_alignment_horizontal) {
+	if (alignment_horizontal == p_alignment_horizontal) {
+		return;
+	}
 	alignment_horizontal = p_alignment_horizontal;
 	queue_sort();
 }
 
 void AspectRatioContainer::set_alignment_vertical(AlignmentMode p_alignment_vertical) {
+	if (alignment_vertical == p_alignment_vertical) {
+		return;
+	}
 	alignment_vertical = p_alignment_vertical;
 	queue_sort();
 }

+ 3 - 0
scene/gui/box_container.cpp

@@ -308,6 +308,9 @@ void BoxContainer::_notification(int p_what) {
 }
 
 void BoxContainer::set_alignment(AlignmentMode p_alignment) {
+	if (alignment == p_alignment) {
+		return;
+	}
 	alignment = p_alignment;
 	_resort();
 }

+ 18 - 0
scene/gui/color_picker.cpp

@@ -292,6 +292,9 @@ bool ColorPicker::is_displaying_old_color() const {
 }
 
 void ColorPicker::set_edit_alpha(bool p_show) {
+	if (edit_alpha == p_show) {
+		return;
+	}
 	edit_alpha = p_show;
 	_update_controls();
 
@@ -509,6 +512,9 @@ Color ColorPicker::get_pick_color() const {
 
 void ColorPicker::set_picker_shape(PickerShapeType p_shape) {
 	ERR_FAIL_INDEX(p_shape, SHAPE_MAX);
+	if (current_shape == p_shape) {
+		return;
+	}
 	current_shape = p_shape;
 
 	_copy_color_to_hsv();
@@ -1131,6 +1137,9 @@ void ColorPicker::_html_focus_exit() {
 }
 
 void ColorPicker::set_presets_enabled(bool p_enabled) {
+	if (presets_enabled == p_enabled) {
+		return;
+	}
 	presets_enabled = p_enabled;
 	if (!p_enabled) {
 		btn_add_preset->set_disabled(true);
@@ -1146,6 +1155,9 @@ bool ColorPicker::are_presets_enabled() const {
 }
 
 void ColorPicker::set_presets_visible(bool p_visible) {
+	if (presets_visible == p_visible) {
+		return;
+	}
 	presets_visible = p_visible;
 	preset_separator->set_visible(p_visible);
 	preset_container->set_visible(p_visible);
@@ -1419,6 +1431,9 @@ void ColorPickerButton::_notification(int p_what) {
 }
 
 void ColorPickerButton::set_pick_color(const Color &p_color) {
+	if (color == p_color) {
+		return;
+	}
 	color = p_color;
 	if (picker) {
 		picker->set_pick_color(p_color);
@@ -1432,6 +1447,9 @@ Color ColorPickerButton::get_pick_color() const {
 }
 
 void ColorPickerButton::set_edit_alpha(bool p_show) {
+	if (edit_alpha == p_show) {
+		return;
+	}
 	edit_alpha = p_show;
 	if (picker) {
 		picker->set_edit_alpha(p_show);

+ 3 - 0
scene/gui/color_rect.cpp

@@ -31,6 +31,9 @@
 #include "color_rect.h"
 
 void ColorRect::set_color(const Color &p_color) {
+	if (color == p_color) {
+		return;
+	}
 	color = p_color;
 	update();
 }

+ 43 - 0
scene/gui/control.cpp

@@ -723,6 +723,9 @@ real_t Control::get_anchor(Side p_side) const {
 
 void Control::set_offset(Side p_side, real_t p_value) {
 	ERR_FAIL_INDEX((int)p_side, 4);
+	if (data.offset[p_side] == p_value) {
+		return;
+	}
 
 	data.offset[p_side] = p_value;
 	_size_changed();
@@ -740,6 +743,10 @@ void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos,
 }
 
 void Control::set_begin(const Size2 &p_point) {
+	if (data.offset[0] == p_point.x && data.offset[1] == p_point.y) {
+		return;
+	}
+
 	data.offset[0] = p_point.x;
 	data.offset[1] = p_point.y;
 	_size_changed();
@@ -750,6 +757,10 @@ Size2 Control::get_begin() const {
 }
 
 void Control::set_end(const Size2 &p_point) {
+	if (data.offset[2] == p_point.x && data.offset[3] == p_point.y) {
+		return;
+	}
+
 	data.offset[2] = p_point.x;
 	data.offset[3] = p_point.y;
 	_size_changed();
@@ -760,6 +771,10 @@ Size2 Control::get_end() const {
 }
 
 void Control::set_h_grow_direction(GrowDirection p_direction) {
+	if (data.h_grow == p_direction) {
+		return;
+	}
+
 	ERR_FAIL_INDEX((int)p_direction, 3);
 
 	data.h_grow = p_direction;
@@ -771,6 +786,10 @@ Control::GrowDirection Control::get_h_grow_direction() const {
 }
 
 void Control::set_v_grow_direction(GrowDirection p_direction) {
+	if (data.v_grow == p_direction) {
+		return;
+	}
+
 	ERR_FAIL_INDEX((int)p_direction, 3);
 
 	data.v_grow = p_direction;
@@ -1427,6 +1446,10 @@ Rect2 Control::get_anchorable_rect() const {
 }
 
 void Control::set_scale(const Vector2 &p_scale) {
+	if (data.scale == p_scale) {
+		return;
+	}
+
 	data.scale = p_scale;
 	// Avoid having 0 scale values, can lead to errors in physics and rendering.
 	if (data.scale.x == 0) {
@@ -1444,6 +1467,10 @@ Vector2 Control::get_scale() const {
 }
 
 void Control::set_rotation(real_t p_radians) {
+	if (data.rotation == p_radians) {
+		return;
+	}
+
 	data.rotation = p_radians;
 	update();
 	_notify_transform();
@@ -1454,6 +1481,10 @@ real_t Control::get_rotation() const {
 }
 
 void Control::set_pivot_offset(const Vector2 &p_pivot) {
+	if (data.pivot_offset == p_pivot) {
+		return;
+	}
+
 	data.pivot_offset = p_pivot;
 	update();
 	_notify_transform();
@@ -2204,6 +2235,9 @@ Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const {
 }
 
 void Control::set_disable_visibility_clip(bool p_ignore) {
+	if (data.disable_visibility_clip == p_ignore) {
+		return;
+	}
 	data.disable_visibility_clip = p_ignore;
 	update();
 }
@@ -2213,6 +2247,9 @@ bool Control::is_visibility_clip_disabled() const {
 }
 
 void Control::set_clip_contents(bool p_clip) {
+	if (data.clip_contents == p_clip) {
+		return;
+	}
 	data.clip_contents = p_clip;
 	update();
 }
@@ -2331,6 +2368,9 @@ Ref<Theme> Control::get_theme() const {
 }
 
 void Control::set_theme_type_variation(const StringName &p_theme_type) {
+	if (data.theme_type_variation == p_theme_type) {
+		return;
+	}
 	data.theme_type_variation = p_theme_type;
 	_propagate_theme_changed(this, data.theme_owner, data.theme_owner_window);
 }
@@ -2960,6 +3000,9 @@ TypedArray<Vector2i> Control::structured_text_parser(TextServer::StructuredTextP
 }
 
 void Control::set_layout_direction(Control::LayoutDirection p_direction) {
+	if (data.layout_dir == p_direction) {
+		return;
+	}
 	ERR_FAIL_INDEX((int)p_direction, 4);
 
 	data.layout_dir = p_direction;

+ 3 - 0
scene/gui/dialogs.cpp

@@ -130,6 +130,9 @@ String AcceptDialog::get_text() const {
 }
 
 void AcceptDialog::set_text(String p_text) {
+	if (label->get_text() == p_text) {
+		return;
+	}
 	label->set_text(p_text);
 	child_controls_changed();
 	if (is_visible()) {

+ 13 - 1
scene/gui/file_dialog.cpp

@@ -685,6 +685,9 @@ void FileDialog::add_filter(const String &p_filter, const String &p_description)
 }
 
 void FileDialog::set_filters(const Vector<String> &p_filters) {
+	if (filters == p_filters) {
+		return;
+	}
 	filters = p_filters;
 	update_filters();
 	invalidate();
@@ -708,10 +711,14 @@ String FileDialog::get_current_path() const {
 
 void FileDialog::set_current_dir(const String &p_dir) {
 	_change_dir(p_dir);
+
 	_push_history();
 }
 
 void FileDialog::set_current_file(const String &p_file) {
+	if (file->get_text() == p_file) {
+		return;
+	}
 	file->set_text(p_file);
 	update_dir();
 	invalidate();
@@ -764,7 +771,9 @@ bool FileDialog::is_mode_overriding_title() const {
 
 void FileDialog::set_file_mode(FileMode p_mode) {
 	ERR_FAIL_INDEX((int)p_mode, 5);
-
+	if (mode == p_mode) {
+		return;
+	}
 	mode = p_mode;
 	switch (mode) {
 		case FILE_MODE_OPEN_FILE:
@@ -977,6 +986,9 @@ void FileDialog::_bind_methods() {
 }
 
 void FileDialog::set_show_hidden_files(bool p_show) {
+	if (show_hidden_files == p_show) {
+		return;
+	}
 	show_hidden_files = p_show;
 	invalidate();
 }

+ 15 - 0
scene/gui/graph_edit.cpp

@@ -1640,6 +1640,9 @@ bool GraphEdit::is_valid_connection_type(int p_type, int p_with_type) const {
 }
 
 void GraphEdit::set_use_snap(bool p_enable) {
+	if (snap_button->is_pressed() == p_enable) {
+		return;
+	}
 	snap_button->set_pressed(p_enable);
 	update();
 }
@@ -1683,6 +1686,9 @@ Vector2 GraphEdit::get_minimap_size() const {
 }
 
 void GraphEdit::set_minimap_opacity(float p_opacity) {
+	if (minimap->get_modulate().a == p_opacity) {
+		return;
+	}
 	minimap->set_modulate(Color(1, 1, 1, p_opacity));
 	minimap->update();
 }
@@ -1693,6 +1699,9 @@ float GraphEdit::get_minimap_opacity() const {
 }
 
 void GraphEdit::set_minimap_enabled(bool p_enable) {
+	if (minimap_button->is_pressed() == p_enable) {
+		return;
+	}
 	minimap_button->set_pressed(p_enable);
 	_minimap_toggled();
 	minimap->update();
@@ -1721,6 +1730,9 @@ float GraphEdit::get_connection_lines_curvature() const {
 }
 
 void GraphEdit::set_connection_lines_thickness(float p_thickness) {
+	if (lines_thickness == p_thickness) {
+		return;
+	}
 	lines_thickness = p_thickness;
 	update();
 }
@@ -1730,6 +1742,9 @@ float GraphEdit::get_connection_lines_thickness() const {
 }
 
 void GraphEdit::set_connection_lines_antialiased(bool p_antialiased) {
+	if (lines_antialiased == p_antialiased) {
+		return;
+	}
 	lines_antialiased = p_antialiased;
 	update();
 }

+ 48 - 0
scene/gui/graph_node.cpp

@@ -505,6 +505,10 @@ bool GraphNode::is_slot_enabled_left(int p_idx) const {
 void GraphNode::set_slot_enabled_left(int p_idx, bool p_enable_left) {
 	ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set enable_left for the slot with p_idx (%d) lesser than zero.", p_idx));
 
+	if (slot_info[p_idx].enable_left == p_enable_left) {
+		return;
+	}
+
 	slot_info[p_idx].enable_left = p_enable_left;
 	update();
 	connpos_dirty = true;
@@ -515,6 +519,10 @@ void GraphNode::set_slot_enabled_left(int p_idx, bool p_enable_left) {
 void GraphNode::set_slot_type_left(int p_idx, int p_type_left) {
 	ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set type_left for the slot '%d' because it hasn't been enabled.", p_idx));
 
+	if (slot_info[p_idx].type_left == p_type_left) {
+		return;
+	}
+
 	slot_info[p_idx].type_left = p_type_left;
 	update();
 	connpos_dirty = true;
@@ -532,6 +540,10 @@ int GraphNode::get_slot_type_left(int p_idx) const {
 void GraphNode::set_slot_color_left(int p_idx, const Color &p_color_left) {
 	ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set color_left for the slot '%d' because it hasn't been enabled.", p_idx));
 
+	if (slot_info[p_idx].color_left == p_color_left) {
+		return;
+	}
+
 	slot_info[p_idx].color_left = p_color_left;
 	update();
 	connpos_dirty = true;
@@ -556,6 +568,10 @@ bool GraphNode::is_slot_enabled_right(int p_idx) const {
 void GraphNode::set_slot_enabled_right(int p_idx, bool p_enable_right) {
 	ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set enable_right for the slot with p_idx (%d) lesser than zero.", p_idx));
 
+	if (slot_info[p_idx].enable_right == p_enable_right) {
+		return;
+	}
+
 	slot_info[p_idx].enable_right = p_enable_right;
 	update();
 	connpos_dirty = true;
@@ -566,6 +582,10 @@ void GraphNode::set_slot_enabled_right(int p_idx, bool p_enable_right) {
 void GraphNode::set_slot_type_right(int p_idx, int p_type_right) {
 	ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set type_right for the slot '%d' because it hasn't been enabled.", p_idx));
 
+	if (slot_info[p_idx].type_right == p_type_right) {
+		return;
+	}
+
 	slot_info[p_idx].type_right = p_type_right;
 	update();
 	connpos_dirty = true;
@@ -583,6 +603,10 @@ int GraphNode::get_slot_type_right(int p_idx) const {
 void GraphNode::set_slot_color_right(int p_idx, const Color &p_color_right) {
 	ERR_FAIL_COND_MSG(!slot_info.has(p_idx), vformat("Cannot set color_right for the slot '%d' because it hasn't been enabled.", p_idx));
 
+	if (slot_info[p_idx].color_right == p_color_right) {
+		return;
+	}
+
 	slot_info[p_idx].color_right = p_color_right;
 	update();
 	connpos_dirty = true;
@@ -700,6 +724,10 @@ String GraphNode::get_language() const {
 }
 
 void GraphNode::set_position_offset(const Vector2 &p_offset) {
+	if (position_offset == p_offset) {
+		return;
+	}
+
 	position_offset = p_offset;
 	emit_signal(SNAME("position_offset_changed"));
 	update();
@@ -710,6 +738,10 @@ Vector2 GraphNode::get_position_offset() const {
 }
 
 void GraphNode::set_selected(bool p_selected) {
+	if (selected == p_selected) {
+		return;
+	}
+
 	selected = p_selected;
 	update();
 }
@@ -731,6 +763,10 @@ Vector2 GraphNode::get_drag_from() {
 }
 
 void GraphNode::set_show_close_button(bool p_enable) {
+	if (show_close == p_enable) {
+		return;
+	}
+
 	show_close = p_enable;
 	update();
 }
@@ -931,6 +967,10 @@ void GraphNode::gui_input(const Ref<InputEvent> &p_ev) {
 }
 
 void GraphNode::set_overlay(Overlay p_overlay) {
+	if (overlay == p_overlay) {
+		return;
+	}
+
 	overlay = p_overlay;
 	update();
 }
@@ -940,6 +980,10 @@ GraphNode::Overlay GraphNode::get_overlay() const {
 }
 
 void GraphNode::set_comment(bool p_enable) {
+	if (comment == p_enable) {
+		return;
+	}
+
 	comment = p_enable;
 	update();
 }
@@ -949,6 +993,10 @@ bool GraphNode::is_comment() const {
 }
 
 void GraphNode::set_resizable(bool p_enable) {
+	if (resizable == p_enable) {
+		return;
+	}
+
 	resizable = p_enable;
 	update();
 }

+ 5 - 0
scene/gui/grid_container.cpp

@@ -246,6 +246,11 @@ void GridContainer::_notification(int p_what) {
 
 void GridContainer::set_columns(int p_columns) {
 	ERR_FAIL_COND(p_columns < 1);
+
+	if (columns == p_columns) {
+		return;
+	}
+
 	columns = p_columns;
 	queue_sort();
 	update_minimum_size();

+ 79 - 0
scene/gui/item_list.cpp

@@ -88,6 +88,10 @@ void ItemList::set_item_text(int p_idx, const String &p_text) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].text == p_text) {
+		return;
+	}
+
 	items.write[p_idx].text = p_text;
 	_shape(p_idx);
 	update();
@@ -153,6 +157,10 @@ void ItemList::set_item_tooltip(int p_idx, const String &p_tooltip) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].tooltip == p_tooltip) {
+		return;
+	}
+
 	items.write[p_idx].tooltip = p_tooltip;
 	update();
 	shape_changed = true;
@@ -169,6 +177,10 @@ void ItemList::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].icon == p_icon) {
+		return;
+	}
+
 	items.write[p_idx].icon = p_icon;
 	update();
 	shape_changed = true;
@@ -186,6 +198,10 @@ void ItemList::set_item_icon_transposed(int p_idx, const bool p_transposed) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].icon_transposed == p_transposed) {
+		return;
+	}
+
 	items.write[p_idx].icon_transposed = p_transposed;
 	update();
 	shape_changed = true;
@@ -203,6 +219,10 @@ void ItemList::set_item_icon_region(int p_idx, const Rect2 &p_region) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].icon_region == p_region) {
+		return;
+	}
+
 	items.write[p_idx].icon_region = p_region;
 	update();
 	shape_changed = true;
@@ -220,6 +240,10 @@ void ItemList::set_item_icon_modulate(int p_idx, const Color &p_modulate) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].icon_modulate == p_modulate) {
+		return;
+	}
+
 	items.write[p_idx].icon_modulate = p_modulate;
 	update();
 }
@@ -236,6 +260,10 @@ void ItemList::set_item_custom_bg_color(int p_idx, const Color &p_custom_bg_colo
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].custom_bg == p_custom_bg_color) {
+		return;
+	}
+
 	items.write[p_idx].custom_bg = p_custom_bg_color;
 	update();
 }
@@ -252,6 +280,10 @@ void ItemList::set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_colo
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].custom_fg == p_custom_fg_color) {
+		return;
+	}
+
 	items.write[p_idx].custom_fg = p_custom_fg_color;
 	update();
 }
@@ -268,6 +300,10 @@ void ItemList::set_item_tag_icon(int p_idx, const Ref<Texture2D> &p_tag_icon) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].tag_icon == p_tag_icon) {
+		return;
+	}
+
 	items.write[p_idx].tag_icon = p_tag_icon;
 	update();
 	shape_changed = true;
@@ -299,6 +335,10 @@ void ItemList::set_item_disabled(int p_idx, bool p_disabled) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].disabled == p_disabled) {
+		return;
+	}
+
 	items.write[p_idx].disabled = p_disabled;
 	update();
 }
@@ -314,6 +354,10 @@ void ItemList::set_item_metadata(int p_idx, const Variant &p_metadata) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].metadata == p_metadata) {
+		return;
+	}
+
 	items.write[p_idx].metadata = p_metadata;
 	update();
 	shape_changed = true;
@@ -379,6 +423,10 @@ bool ItemList::is_selected(int p_idx) const {
 void ItemList::set_current(int p_current) {
 	ERR_FAIL_INDEX(p_current, items.size());
 
+	if (current == p_current) {
+		return;
+	}
+
 	if (select_mode == SELECT_SINGLE) {
 		select(p_current, true);
 	} else {
@@ -410,6 +458,11 @@ void ItemList::move_item(int p_from_idx, int p_to_idx) {
 
 void ItemList::set_item_count(int p_count) {
 	ERR_FAIL_COND(p_count < 0);
+
+	if (items.size() == p_count) {
+		return;
+	}
+
 	items.resize(p_count);
 	update();
 	shape_changed = true;
@@ -445,6 +498,11 @@ void ItemList::clear() {
 
 void ItemList::set_fixed_column_width(int p_size) {
 	ERR_FAIL_COND(p_size < 0);
+
+	if (fixed_column_width == p_size) {
+		return;
+	}
+
 	fixed_column_width = p_size;
 	update();
 	shape_changed = true;
@@ -455,6 +513,10 @@ int ItemList::get_fixed_column_width() const {
 }
 
 void ItemList::set_same_column_width(bool p_enable) {
+	if (same_column_width == p_enable) {
+		return;
+	}
+
 	same_column_width = p_enable;
 	update();
 	shape_changed = true;
@@ -487,6 +549,11 @@ int ItemList::get_max_text_lines() const {
 
 void ItemList::set_max_columns(int p_amount) {
 	ERR_FAIL_COND(p_amount < 0);
+
+	if (max_columns == p_amount) {
+		return;
+	}
+
 	max_columns = p_amount;
 	update();
 	shape_changed = true;
@@ -497,6 +564,10 @@ int ItemList::get_max_columns() const {
 }
 
 void ItemList::set_select_mode(SelectMode p_mode) {
+	if (select_mode == p_mode) {
+		return;
+	}
+
 	select_mode = p_mode;
 	update();
 }
@@ -526,6 +597,10 @@ ItemList::IconMode ItemList::get_icon_mode() const {
 }
 
 void ItemList::set_fixed_icon_size(const Size2 &p_size) {
+	if (fixed_icon_size == p_size) {
+		return;
+	}
+
 	fixed_icon_size = p_size;
 	update();
 }
@@ -1512,6 +1587,10 @@ void ItemList::set_autoscroll_to_bottom(const bool p_enable) {
 }
 
 void ItemList::set_auto_height(bool p_enable) {
+	if (auto_height == p_enable) {
+		return;
+	}
+
 	auto_height = p_enable;
 	shape_changed = true;
 	update();

+ 44 - 11
scene/gui/label.cpp

@@ -38,10 +38,12 @@
 #include "servers/text_server.h"
 
 void Label::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
-	if (autowrap_mode != p_mode) {
-		autowrap_mode = p_mode;
-		lines_dirty = true;
+	if (autowrap_mode == p_mode) {
+		return;
 	}
+
+	autowrap_mode = p_mode;
+	lines_dirty = true;
 	update();
 
 	if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
@@ -54,6 +56,10 @@ TextServer::AutowrapMode Label::get_autowrap_mode() const {
 }
 
 void Label::set_uppercase(bool p_uppercase) {
+	if (uppercase == p_uppercase) {
+		return;
+	}
+
 	uppercase = p_uppercase;
 	dirty = true;
 
@@ -608,12 +614,15 @@ int Label::get_visible_line_count() const {
 
 void Label::set_horizontal_alignment(HorizontalAlignment p_alignment) {
 	ERR_FAIL_INDEX((int)p_alignment, 4);
-	if (horizontal_alignment != p_alignment) {
-		if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL || p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
-			lines_dirty = true; // Reshape lines.
-		}
-		horizontal_alignment = p_alignment;
+	if (horizontal_alignment == p_alignment) {
+		return;
 	}
+
+	if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL || p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+		lines_dirty = true; // Reshape lines.
+	}
+	horizontal_alignment = p_alignment;
+
 	update();
 }
 
@@ -623,6 +632,11 @@ HorizontalAlignment Label::get_horizontal_alignment() const {
 
 void Label::set_vertical_alignment(VerticalAlignment p_alignment) {
 	ERR_FAIL_INDEX((int)p_alignment, 4);
+
+	if (vertical_alignment == p_alignment) {
+		return;
+	}
+
 	vertical_alignment = p_alignment;
 	update();
 }
@@ -689,6 +703,10 @@ TextServer::StructuredTextParser Label::get_structured_text_bidi_override() cons
 }
 
 void Label::set_structured_text_bidi_override_options(Array p_args) {
+	if (st_args == p_args) {
+		return;
+	}
+
 	st_args = p_args;
 	dirty = true;
 	update();
@@ -715,6 +733,10 @@ String Label::get_language() const {
 }
 
 void Label::set_clip_text(bool p_clip) {
+	if (clip == p_clip) {
+		return;
+	}
+
 	clip = p_clip;
 	update();
 	update_minimum_size();
@@ -725,10 +747,12 @@ bool Label::is_clipping_text() const {
 }
 
 void Label::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
-	if (overrun_behavior != p_behavior) {
-		overrun_behavior = p_behavior;
-		lines_dirty = true;
+	if (overrun_behavior == p_behavior) {
+		return;
 	}
+
+	overrun_behavior = p_behavior;
+	lines_dirty = true;
 	update();
 	if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
 		update_minimum_size();
@@ -800,6 +824,11 @@ void Label::set_visible_characters_behavior(TextServer::VisibleCharactersBehavio
 
 void Label::set_lines_skipped(int p_lines) {
 	ERR_FAIL_COND(p_lines < 0);
+
+	if (lines_skipped == p_lines) {
+		return;
+	}
+
 	lines_skipped = p_lines;
 	_update_visible();
 	update();
@@ -810,6 +839,10 @@ int Label::get_lines_skipped() const {
 }
 
 void Label::set_max_lines_visible(int p_lines) {
+	if (max_lines_visible == p_lines) {
+		return;
+	}
+
 	max_lines_visible = p_lines;
 	_update_visible();
 	update();

+ 27 - 9
scene/gui/line_edit.cpp

@@ -607,10 +607,12 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
 
 void LineEdit::set_horizontal_alignment(HorizontalAlignment p_alignment) {
 	ERR_FAIL_INDEX((int)p_alignment, 4);
-	if (alignment != p_alignment) {
-		alignment = p_alignment;
-		_shape();
+	if (alignment == p_alignment) {
+		return;
 	}
+
+	alignment = p_alignment;
+	_shape();
 	update();
 }
 
@@ -1525,6 +1527,10 @@ String LineEdit::get_text() const {
 }
 
 void LineEdit::set_placeholder(String p_text) {
+	if (placeholder == p_text) {
+		return;
+	}
+
 	placeholder = p_text;
 	placeholder_translated = atr(placeholder);
 	_shape();
@@ -1781,10 +1787,12 @@ bool LineEdit::is_editable() const {
 }
 
 void LineEdit::set_secret(bool p_secret) {
-	if (pass != p_secret) {
-		pass = p_secret;
-		_shape();
+	if (pass == p_secret) {
+		return;
 	}
+
+	pass = p_secret;
+	_shape();
 	update();
 }
 
@@ -1797,10 +1805,12 @@ void LineEdit::set_secret_character(const String &p_string) {
 	// It also wouldn't make sense to use multiple characters as the secret character.
 	ERR_FAIL_COND_MSG(p_string.length() != 1, "Secret character must be exactly one character long (" + itos(p_string.length()) + " characters given).");
 
-	if (secret_character != p_string) {
-		secret_character = p_string;
-		_shape();
+	if (secret_character == p_string) {
+		return;
 	}
+
+	secret_character = p_string;
+	_shape();
 	update();
 }
 
@@ -2057,6 +2067,10 @@ bool LineEdit::is_middle_mouse_paste_enabled() const {
 }
 
 void LineEdit::set_selecting_enabled(bool p_enabled) {
+	if (selecting_enabled == p_enabled) {
+		return;
+	}
+
 	selecting_enabled = p_enabled;
 
 	if (!selecting_enabled) {
@@ -2069,6 +2083,10 @@ bool LineEdit::is_selecting_enabled() const {
 }
 
 void LineEdit::set_deselect_on_focus_loss_enabled(const bool p_enabled) {
+	if (deselect_on_focus_loss_enabled == p_enabled) {
+		return;
+	}
+
 	deselect_on_focus_loss_enabled = p_enabled;
 	if (p_enabled && selection.enabled && !has_focus()) {
 		deselect();

+ 4 - 0
scene/gui/link_button.cpp

@@ -109,6 +109,10 @@ String LinkButton::get_language() const {
 }
 
 void LinkButton::set_underline_mode(UnderlineMode p_underline_mode) {
+	if (underline_mode == p_underline_mode) {
+		return;
+	}
+
 	underline_mode = p_underline_mode;
 	update();
 }

+ 5 - 0
scene/gui/menu_button.cpp

@@ -130,6 +130,11 @@ bool MenuButton::is_switch_on_hover() {
 
 void MenuButton::set_item_count(int p_count) {
 	ERR_FAIL_COND(p_count < 0);
+
+	if (popup->get_item_count() == p_count) {
+		return;
+	}
+
 	popup->set_item_count(p_count);
 	notify_property_list_changed();
 }

+ 17 - 0
scene/gui/nine_patch_rect.cpp

@@ -105,6 +105,11 @@ Ref<Texture2D> NinePatchRect::get_texture() const {
 
 void NinePatchRect::set_patch_margin(Side p_side, int p_size) {
 	ERR_FAIL_INDEX((int)p_side, 4);
+
+	if (margin[p_side] == p_size) {
+		return;
+	}
+
 	margin[p_side] = p_size;
 	update();
 	update_minimum_size();
@@ -130,6 +135,10 @@ Rect2 NinePatchRect::get_region_rect() const {
 }
 
 void NinePatchRect::set_draw_center(bool p_enabled) {
+	if (draw_center == p_enabled) {
+		return;
+	}
+
 	draw_center = p_enabled;
 	update();
 }
@@ -139,6 +148,10 @@ bool NinePatchRect::is_draw_center_enabled() const {
 }
 
 void NinePatchRect::set_h_axis_stretch_mode(AxisStretchMode p_mode) {
+	if (axis_h == p_mode) {
+		return;
+	}
+
 	axis_h = p_mode;
 	update();
 }
@@ -148,6 +161,10 @@ NinePatchRect::AxisStretchMode NinePatchRect::get_h_axis_stretch_mode() const {
 }
 
 void NinePatchRect::set_v_axis_stretch_mode(AxisStretchMode p_mode) {
+	if (axis_v == p_mode) {
+		return;
+	}
+
 	axis_v = p_mode;
 	update();
 }

+ 86 - 0
scene/gui/popup_menu.cpp

@@ -1144,6 +1144,11 @@ void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].icon == p_icon) {
+		return;
+	}
+
 	items.write[p_idx].icon = p_icon;
 
 	control->update();
@@ -1157,6 +1162,10 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
 
+	if (items[p_idx].checked == p_checked) {
+		return;
+	}
+
 	items.write[p_idx].checked = p_checked;
 
 	control->update();
@@ -1169,6 +1178,11 @@ void PopupMenu::set_item_id(int p_idx, int p_id) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].id == p_id) {
+		return;
+	}
+
 	items.write[p_idx].id = p_id;
 
 	control->update();
@@ -1181,6 +1195,11 @@ void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].accel == p_accel) {
+		return;
+	}
+
 	items.write[p_idx].accel = p_accel;
 	items.write[p_idx].dirty = true;
 
@@ -1194,6 +1213,11 @@ void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].metadata == p_meta) {
+		return;
+	}
+
 	items.write[p_idx].metadata = p_meta;
 	control->update();
 	child_controls_changed();
@@ -1205,6 +1229,11 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].disabled == p_disabled) {
+		return;
+	}
+
 	items.write[p_idx].disabled = p_disabled;
 	control->update();
 	child_controls_changed();
@@ -1216,6 +1245,11 @@ void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].submenu == p_submenu) {
+		return;
+	}
+
 	items.write[p_idx].submenu = p_submenu;
 	control->update();
 	child_controls_changed();
@@ -1330,6 +1364,11 @@ void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].separator == p_separator) {
+		return;
+	}
+
 	items.write[p_idx].separator = p_separator;
 	control->update();
 }
@@ -1344,6 +1383,12 @@ void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	int type = (int)(p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE);
+	if (type == items[p_idx].checkable_type) {
+		return;
+	}
+
 	items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
 	control->update();
 	_menu_changed();
@@ -1354,6 +1399,12 @@ void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	int type = (int)(p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE);
+	if (type == items[p_idx].checkable_type) {
+		return;
+	}
+
 	items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
 	control->update();
 	_menu_changed();
@@ -1364,6 +1415,11 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].tooltip == p_tooltip) {
+		return;
+	}
+
 	items.write[p_idx].tooltip = p_tooltip;
 	control->update();
 	_menu_changed();
@@ -1374,6 +1430,11 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].shortcut == p_shortcut && items[p_idx].shortcut_is_global == p_global && items[p_idx].shortcut.is_valid() == p_shortcut.is_valid()) {
+		return;
+	}
+
 	if (items[p_idx].shortcut.is_valid()) {
 		_unref_shortcut(items[p_idx].shortcut);
 	}
@@ -1394,7 +1455,12 @@ void PopupMenu::set_item_indent(int p_idx, int p_indent) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items.write[p_idx].indent == p_indent) {
+		return;
+	}
 	items.write[p_idx].indent = p_indent;
+
 	control->update();
 	child_controls_changed();
 	_menu_changed();
@@ -1405,6 +1471,11 @@ void PopupMenu::set_item_multistate(int p_idx, int p_state) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].state == p_state) {
+		return;
+	}
+
 	items.write[p_idx].state = p_state;
 	control->update();
 	_menu_changed();
@@ -1415,6 +1486,11 @@ void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) {
 		p_idx += get_item_count();
 	}
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (items[p_idx].shortcut_is_disabled == p_disabled) {
+		return;
+	}
+
 	items.write[p_idx].shortcut_is_disabled = p_disabled;
 	control->update();
 	_menu_changed();
@@ -1457,6 +1533,11 @@ bool PopupMenu::is_item_shortcut_disabled(int p_idx) const {
 
 void PopupMenu::set_current_index(int p_idx) {
 	ERR_FAIL_INDEX(p_idx, items.size());
+
+	if (mouse_over == p_idx) {
+		return;
+	}
+
 	mouse_over = p_idx;
 	scroll_to_item(mouse_over);
 	control->update();
@@ -1469,6 +1550,11 @@ int PopupMenu::get_current_index() const {
 void PopupMenu::set_item_count(int p_count) {
 	ERR_FAIL_COND(p_count < 0);
 	int prev_size = items.size();
+
+	if (prev_size == p_count) {
+		return;
+	}
+
 	items.resize(p_count);
 
 	if (prev_size < p_count) {

+ 20 - 0
scene/gui/range.cpp

@@ -106,6 +106,10 @@ void Range::set_value(double p_val) {
 }
 
 void Range::set_min(double p_min) {
+	if (shared->min == p_min) {
+		return;
+	}
+
 	shared->min = p_min;
 	set_value(shared->val);
 	_validate_values();
@@ -116,6 +120,10 @@ void Range::set_min(double p_min) {
 }
 
 void Range::set_max(double p_max) {
+	if (shared->max == p_max) {
+		return;
+	}
+
 	shared->max = p_max;
 	set_value(shared->val);
 	_validate_values();
@@ -124,11 +132,19 @@ void Range::set_max(double p_max) {
 }
 
 void Range::set_step(double p_step) {
+	if (shared->step == p_step) {
+		return;
+	}
+
 	shared->step = p_step;
 	shared->emit_changed("step");
 }
 
 void Range::set_page(double p_page) {
+	if (shared->page == p_page) {
+		return;
+	}
+
 	shared->page = p_page;
 	set_value(shared->val);
 	_validate_values();
@@ -300,6 +316,10 @@ bool Range::is_using_rounded_values() const {
 }
 
 void Range::set_exp_ratio(bool p_enable) {
+	if (shared->exp_ratio == p_enable) {
+		return;
+	}
+
 	shared->exp_ratio = p_enable;
 
 	update_configuration_warnings();

+ 14 - 1
scene/gui/reference_rect.cpp

@@ -46,6 +46,10 @@ void ReferenceRect::_notification(int p_what) {
 }
 
 void ReferenceRect::set_border_color(const Color &p_color) {
+	if (border_color == p_color) {
+		return;
+	}
+
 	border_color = p_color;
 	update();
 }
@@ -55,7 +59,12 @@ Color ReferenceRect::get_border_color() const {
 }
 
 void ReferenceRect::set_border_width(float p_width) {
-	border_width = MAX(0.0, p_width);
+	float width_max = MAX(0.0, p_width);
+	if (border_width == width_max) {
+		return;
+	}
+
+	border_width = width_max;
 	update();
 }
 
@@ -64,6 +73,10 @@ float ReferenceRect::get_border_width() const {
 }
 
 void ReferenceRect::set_editor_only(const bool &p_enabled) {
+	if (editor_only == p_enabled) {
+		return;
+	}
+
 	editor_only = p_enabled;
 	update();
 }

+ 24 - 0
scene/gui/rich_text_label.cpp

@@ -3378,6 +3378,10 @@ void RichTextLabel::clear() {
 }
 
 void RichTextLabel::set_tab_size(int p_spaces) {
+	if (tab_size == p_spaces) {
+		return;
+	}
+
 	_stop_thread();
 
 	tab_size = p_spaces;
@@ -3401,6 +3405,10 @@ bool RichTextLabel::is_fit_content_height_enabled() const {
 }
 
 void RichTextLabel::set_meta_underline(bool p_underline) {
+	if (underline_meta == p_underline) {
+		return;
+	}
+
 	underline_meta = p_underline;
 	update();
 }
@@ -4417,6 +4425,10 @@ int RichTextLabel::get_visible_line_count() const {
 }
 
 void RichTextLabel::set_selection_enabled(bool p_enabled) {
+	if (selection.enabled == p_enabled) {
+		return;
+	}
+
 	selection.enabled = p_enabled;
 	if (!p_enabled) {
 		if (selection.active) {
@@ -4429,6 +4441,10 @@ void RichTextLabel::set_selection_enabled(bool p_enabled) {
 }
 
 void RichTextLabel::set_deselect_on_focus_loss_enabled(const bool p_enabled) {
+	if (deselect_on_focus_loss_enabled == p_enabled) {
+		return;
+	}
+
 	deselect_on_focus_loss_enabled = p_enabled;
 	if (p_enabled && selection.active && !has_focus()) {
 		deselect();
@@ -4796,6 +4812,10 @@ int RichTextLabel::get_selection_to() const {
 }
 
 void RichTextLabel::set_text(const String &p_bbcode) {
+	if (text == p_bbcode) {
+		return;
+	}
+
 	text = p_bbcode;
 	if (use_bbcode) {
 		parse_bbcode(p_bbcode);
@@ -5332,6 +5352,10 @@ int RichTextLabel::get_total_glyph_count() const {
 }
 
 void RichTextLabel::set_fixed_size_to_width(int p_width) {
+	if (fixed_width == p_width) {
+		return;
+	}
+
 	fixed_width = p_width;
 	update_minimum_size();
 }

+ 12 - 0
scene/gui/slider.cpp

@@ -227,6 +227,10 @@ double Slider::get_custom_step() const {
 }
 
 void Slider::set_ticks(int p_count) {
+	if (ticks == p_count) {
+		return;
+	}
+
 	ticks = p_count;
 	update();
 }
@@ -240,11 +244,19 @@ bool Slider::get_ticks_on_borders() const {
 }
 
 void Slider::set_ticks_on_borders(bool _tob) {
+	if (ticks_on_borders == _tob) {
+		return;
+	}
+
 	ticks_on_borders = _tob;
 	update();
 }
 
 void Slider::set_editable(bool p_editable) {
+	if (editable == p_editable) {
+		return;
+	}
+
 	editable = p_editable;
 	update();
 }

+ 8 - 0
scene/gui/spin_box.cpp

@@ -250,6 +250,10 @@ HorizontalAlignment SpinBox::get_horizontal_alignment() const {
 }
 
 void SpinBox::set_suffix(const String &p_suffix) {
+	if (suffix == p_suffix) {
+		return;
+	}
+
 	suffix = p_suffix;
 	_value_changed(0);
 }
@@ -259,6 +263,10 @@ String SpinBox::get_suffix() const {
 }
 
 void SpinBox::set_prefix(const String &p_prefix) {
+	if (prefix == p_prefix) {
+		return;
+	}
+
 	prefix = p_prefix;
 	_value_changed(0);
 }

+ 4 - 0
scene/gui/split_container.cpp

@@ -331,6 +331,10 @@ void SplitContainer::set_collapsed(bool p_collapsed) {
 }
 
 void SplitContainer::set_dragger_visibility(DraggerVisibility p_visibility) {
+	if (dragger_visibility == p_visibility) {
+		return;
+	}
+
 	dragger_visibility = p_visibility;
 	queue_sort();
 	update();

+ 4 - 0
scene/gui/subviewport_container.cpp

@@ -53,6 +53,10 @@ Size2 SubViewportContainer::get_minimum_size() const {
 }
 
 void SubViewportContainer::set_stretch(bool p_enable) {
+	if (stretch == p_enable) {
+		return;
+	}
+
 	stretch = p_enable;
 	update_minimum_size();
 	queue_sort();

+ 40 - 0
scene/gui/tab_bar.cpp

@@ -634,6 +634,11 @@ bool TabBar::get_offset_buttons_visible() const {
 
 void TabBar::set_tab_title(int p_tab, const String &p_title) {
 	ERR_FAIL_INDEX(p_tab, tabs.size());
+
+	if (tabs[p_tab].text == p_title) {
+		return;
+	}
+
 	tabs.write[p_tab].text = p_title;
 
 	_shape(p_tab);
@@ -690,6 +695,11 @@ String TabBar::get_tab_language(int p_tab) const {
 
 void TabBar::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
 	ERR_FAIL_INDEX(p_tab, tabs.size());
+
+	if (tabs[p_tab].icon == p_icon) {
+		return;
+	}
+
 	tabs.write[p_tab].icon = p_icon;
 
 	_update_cache();
@@ -708,6 +718,11 @@ Ref<Texture2D> TabBar::get_tab_icon(int p_tab) const {
 
 void TabBar::set_tab_disabled(int p_tab, bool p_disabled) {
 	ERR_FAIL_INDEX(p_tab, tabs.size());
+
+	if (tabs[p_tab].disabled == p_disabled) {
+		return;
+	}
+
 	tabs.write[p_tab].disabled = p_disabled;
 
 	_update_cache();
@@ -726,6 +741,11 @@ bool TabBar::is_tab_disabled(int p_tab) const {
 
 void TabBar::set_tab_hidden(int p_tab, bool p_hidden) {
 	ERR_FAIL_INDEX(p_tab, tabs.size());
+
+	if (tabs[p_tab].hidden == p_hidden) {
+		return;
+	}
+
 	tabs.write[p_tab].hidden = p_hidden;
 
 	_update_cache();
@@ -744,6 +764,11 @@ bool TabBar::is_tab_hidden(int p_tab) const {
 
 void TabBar::set_tab_button_icon(int p_tab, const Ref<Texture2D> &p_icon) {
 	ERR_FAIL_INDEX(p_tab, tabs.size());
+
+	if (tabs[p_tab].right_button == p_icon) {
+		return;
+	}
+
 	tabs.write[p_tab].right_button = p_icon;
 
 	_update_cache();
@@ -1155,6 +1180,11 @@ int TabBar::get_tab_idx_at_point(const Point2 &p_point) const {
 
 void TabBar::set_tab_alignment(AlignmentMode p_alignment) {
 	ERR_FAIL_INDEX(p_alignment, ALIGNMENT_MAX);
+
+	if (tab_alignment == p_alignment) {
+		return;
+	}
+
 	tab_alignment = p_alignment;
 
 	_update_cache();
@@ -1374,6 +1404,11 @@ Rect2 TabBar::get_tab_rect(int p_tab) const {
 
 void TabBar::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
 	ERR_FAIL_INDEX(p_policy, CLOSE_BUTTON_MAX);
+
+	if (cb_displaypolicy == p_policy) {
+		return;
+	}
+
 	cb_displaypolicy = p_policy;
 
 	_update_cache();
@@ -1391,6 +1426,11 @@ TabBar::CloseButtonDisplayPolicy TabBar::get_tab_close_display_policy() const {
 
 void TabBar::set_max_tab_width(int p_width) {
 	ERR_FAIL_COND(p_width < 0);
+
+	if (max_width == p_width) {
+		return;
+	}
+
 	max_width = p_width;
 
 	_update_cache();

+ 29 - 1
scene/gui/tab_container.cpp

@@ -618,6 +618,10 @@ int TabContainer::get_tab_idx_from_control(Control *p_child) const {
 }
 
 void TabContainer::set_tab_alignment(TabBar::AlignmentMode p_alignment) {
+	if (tab_bar->get_tab_alignment() == p_alignment) {
+		return;
+	}
+
 	tab_bar->set_tab_alignment(p_alignment);
 	_update_margins();
 }
@@ -679,6 +683,10 @@ void TabContainer::set_tab_title(int p_tab, const String &p_title) {
 	Control *child = get_tab_control(p_tab);
 	ERR_FAIL_COND(!child);
 
+	if (tab_bar->get_tab_title(p_tab) == p_title) {
+		return;
+	}
+
 	tab_bar->set_tab_title(p_tab, p_title);
 
 	if (p_title == child->get_name()) {
@@ -698,6 +706,10 @@ String TabContainer::get_tab_title(int p_tab) const {
 }
 
 void TabContainer::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
+	if (tab_bar->get_tab_icon(p_tab) == p_icon) {
+		return;
+	}
+
 	tab_bar->set_tab_icon(p_tab, p_icon);
 
 	_update_margins();
@@ -709,6 +721,10 @@ Ref<Texture2D> TabContainer::get_tab_icon(int p_tab) const {
 }
 
 void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) {
+	if (tab_bar->is_tab_disabled(p_tab) == p_disabled) {
+		return;
+	}
+
 	tab_bar->set_tab_disabled(p_tab, p_disabled);
 
 	_update_margins();
@@ -725,6 +741,10 @@ void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) {
 	Control *child = get_tab_control(p_tab);
 	ERR_FAIL_COND(!child);
 
+	if (tab_bar->is_tab_hidden(p_tab) == p_hidden) {
+		return;
+	}
+
 	tab_bar->set_tab_hidden(p_tab, p_hidden);
 	child->hide();
 
@@ -811,7 +831,11 @@ void TabContainer::set_popup(Node *p_popup) {
 	bool had_popup = get_popup();
 
 	Popup *popup = Object::cast_to<Popup>(p_popup);
-	popup_obj_id = popup ? popup->get_instance_id() : ObjectID();
+	ObjectID popup_id = popup ? popup->get_instance_id() : ObjectID();
+	if (popup_obj_id == popup_id) {
+		return;
+	}
+	popup_obj_id = popup_id;
 
 	if (had_popup != bool(popup)) {
 		update();
@@ -855,6 +879,10 @@ int TabContainer::get_tabs_rearrange_group() const {
 }
 
 void TabContainer::set_use_hidden_tabs_for_min_size(bool p_use_hidden_tabs) {
+	if (use_hidden_tabs_for_min_size == p_use_hidden_tabs) {
+		return;
+	}
+
 	use_hidden_tabs_for_min_size = p_use_hidden_tabs;
 	update_minimum_size();
 }

+ 109 - 6
scene/gui/text_edit.cpp

@@ -2889,6 +2889,10 @@ TextServer::StructuredTextParser TextEdit::get_structured_text_bidi_override() c
 }
 
 void TextEdit::set_structured_text_bidi_override_options(Array p_args) {
+	if (st_args == p_args) {
+		return;
+	}
+
 	st_args = p_args;
 	for (int i = 0; i < text.size(); i++) {
 		text.set(i, text[i], structured_text_parser(st_parser, st_args, text[i]));
@@ -2917,6 +2921,10 @@ int TextEdit::get_tab_size() const {
 
 // User controls
 void TextEdit::set_overtype_mode_enabled(const bool p_enabled) {
+	if (overtype_mode == p_enabled) {
+		return;
+	}
+
 	overtype_mode = p_enabled;
 	update();
 }
@@ -3036,6 +3044,10 @@ int TextEdit::get_line_count() const {
 }
 
 void TextEdit::set_placeholder(const String &p_text) {
+	if (placeholder_text == p_text) {
+		return;
+	}
+
 	placeholder_text = p_text;
 	_update_placeholder();
 	update();
@@ -3945,6 +3957,10 @@ bool TextEdit::is_mouse_over_selection(bool p_edges) const {
 
 /* Caret */
 void TextEdit::set_caret_type(CaretType p_type) {
+	if (caret_type == p_type) {
+		return;
+	}
+
 	caret_type = p_type;
 	update();
 }
@@ -3954,6 +3970,10 @@ TextEdit::CaretType TextEdit::get_caret_type() const {
 }
 
 void TextEdit::set_caret_blink_enabled(const bool p_enabled) {
+	if (caret_blink_enabled == p_enabled) {
+		return;
+	}
+
 	caret_blink_enabled = p_enabled;
 
 	if (has_focus()) {
@@ -4114,6 +4134,10 @@ String TextEdit::get_word_under_caret() const {
 
 /* Selection. */
 void TextEdit::set_selecting_enabled(const bool p_enabled) {
+	if (selecting_enabled == p_enabled) {
+		return;
+	}
+
 	selecting_enabled = p_enabled;
 
 	if (!selecting_enabled) {
@@ -4126,6 +4150,10 @@ bool TextEdit::is_selecting_enabled() const {
 }
 
 void TextEdit::set_deselect_on_focus_loss_enabled(const bool p_enabled) {
+	if (deselect_on_focus_loss_enabled == p_enabled) {
+		return;
+	}
+
 	deselect_on_focus_loss_enabled = p_enabled;
 	if (p_enabled && selection.active && !has_focus()) {
 		deselect();
@@ -4431,6 +4459,10 @@ bool TextEdit::is_smooth_scroll_enabled() const {
 }
 
 void TextEdit::set_scroll_past_end_of_file_enabled(const bool p_enabled) {
+	if (scroll_past_end_of_file_enabled == p_enabled) {
+		return;
+	}
+
 	scroll_past_end_of_file_enabled = p_enabled;
 	update();
 }
@@ -4714,10 +4746,12 @@ void TextEdit::center_viewport_to_caret() {
 
 /* Minimap */
 void TextEdit::set_draw_minimap(bool p_enabled) {
-	if (draw_minimap != p_enabled) {
-		draw_minimap = p_enabled;
-		_update_wrap_at_column();
+	if (draw_minimap == p_enabled) {
+		return;
 	}
+
+	draw_minimap = p_enabled;
+	_update_wrap_at_column();
 	update();
 }
 
@@ -4726,10 +4760,12 @@ bool TextEdit::is_drawing_minimap() const {
 }
 
 void TextEdit::set_minimap_width(int p_minimap_width) {
-	if (minimap_width != p_minimap_width) {
-		minimap_width = p_minimap_width;
-		_update_wrap_at_column();
+	if (minimap_width == p_minimap_width) {
+		return;
 	}
+
+	minimap_width = p_minimap_width;
+	_update_wrap_at_column();
 	update();
 }
 
@@ -4780,6 +4816,11 @@ String TextEdit::get_gutter_name(int p_gutter) const {
 
 void TextEdit::set_gutter_type(int p_gutter, GutterType p_type) {
 	ERR_FAIL_INDEX(p_gutter, gutters.size());
+
+	if (gutters[p_gutter].type == p_type) {
+		return;
+	}
+
 	gutters.write[p_gutter].type = p_type;
 	update();
 }
@@ -4823,6 +4864,11 @@ bool TextEdit::is_gutter_drawn(int p_gutter) const {
 
 void TextEdit::set_gutter_clickable(int p_gutter, bool p_clickable) {
 	ERR_FAIL_INDEX(p_gutter, gutters.size());
+
+	if (gutters[p_gutter].clickable == p_clickable) {
+		return;
+	}
+
 	gutters.write[p_gutter].clickable = p_clickable;
 	update();
 }
@@ -4878,6 +4924,10 @@ void TextEdit::merge_gutters(int p_from_line, int p_to_line) {
 void TextEdit::set_gutter_custom_draw(int p_gutter, const Callable &p_draw_callback) {
 	ERR_FAIL_INDEX(p_gutter, gutters.size());
 
+	if (gutters[p_gutter].custom_draw_callback == p_draw_callback) {
+		return;
+	}
+
 	gutters.write[p_gutter].custom_draw_callback = p_draw_callback;
 	update();
 }
@@ -4898,6 +4948,11 @@ Variant TextEdit::get_line_gutter_metadata(int p_line, int p_gutter) const {
 void TextEdit::set_line_gutter_text(int p_line, int p_gutter, const String &p_text) {
 	ERR_FAIL_INDEX(p_line, text.size());
 	ERR_FAIL_INDEX(p_gutter, gutters.size());
+
+	if (text.get_line_gutter_text(p_line, p_gutter) == p_text) {
+		return;
+	}
+
 	text.set_line_gutter_text(p_line, p_gutter, p_text);
 	update();
 }
@@ -4911,6 +4966,11 @@ String TextEdit::get_line_gutter_text(int p_line, int p_gutter) const {
 void TextEdit::set_line_gutter_icon(int p_line, int p_gutter, const Ref<Texture2D> &p_icon) {
 	ERR_FAIL_INDEX(p_line, text.size());
 	ERR_FAIL_INDEX(p_gutter, gutters.size());
+
+	if (text.get_line_gutter_icon(p_line, p_gutter) == p_icon) {
+		return;
+	}
+
 	text.set_line_gutter_icon(p_line, p_gutter, p_icon);
 	update();
 }
@@ -4924,6 +4984,11 @@ Ref<Texture2D> TextEdit::get_line_gutter_icon(int p_line, int p_gutter) const {
 void TextEdit::set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color) {
 	ERR_FAIL_INDEX(p_line, text.size());
 	ERR_FAIL_INDEX(p_gutter, gutters.size());
+
+	if (text.get_line_gutter_item_color(p_line, p_gutter) == p_color) {
+		return;
+	}
+
 	text.set_line_gutter_item_color(p_line, p_gutter, p_color);
 	update();
 }
@@ -4949,6 +5014,11 @@ bool TextEdit::is_line_gutter_clickable(int p_line, int p_gutter) const {
 // Line style
 void TextEdit::set_line_background_color(int p_line, const Color &p_color) {
 	ERR_FAIL_INDEX(p_line, text.size());
+
+	if (text.get_line_background_color(p_line) == p_color) {
+		return;
+	}
+
 	text.set_line_background_color(p_line, p_color);
 	update();
 }
@@ -4960,6 +5030,10 @@ Color TextEdit::get_line_background_color(int p_line) const {
 
 /* Syntax Highlighting. */
 void TextEdit::set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter) {
+	if (syntax_highlighter == p_syntax_highlighter && syntax_highlighter.is_valid() == p_syntax_highlighter.is_valid()) {
+		return;
+	}
+
 	syntax_highlighter = p_syntax_highlighter;
 	if (syntax_highlighter.is_valid()) {
 		syntax_highlighter->set_text_edit(this);
@@ -4973,6 +5047,10 @@ Ref<SyntaxHighlighter> TextEdit::get_syntax_highlighter() const {
 
 /* Visual. */
 void TextEdit::set_highlight_current_line(bool p_enabled) {
+	if (highlight_current_line == p_enabled) {
+		return;
+	}
+
 	highlight_current_line = p_enabled;
 	update();
 }
@@ -4982,6 +5060,10 @@ bool TextEdit::is_highlight_current_line_enabled() const {
 }
 
 void TextEdit::set_highlight_all_occurrences(const bool p_enabled) {
+	if (highlight_all_occurrences == p_enabled) {
+		return;
+	}
+
 	highlight_all_occurrences = p_enabled;
 	update();
 }
@@ -5008,6 +5090,10 @@ bool TextEdit::get_draw_control_chars() const {
 }
 
 void TextEdit::set_draw_tabs(bool p_enabled) {
+	if (draw_tabs == p_enabled) {
+		return;
+	}
+
 	draw_tabs = p_enabled;
 	update();
 }
@@ -5017,6 +5103,10 @@ bool TextEdit::is_drawing_tabs() const {
 }
 
 void TextEdit::set_draw_spaces(bool p_enabled) {
+	if (draw_spaces == p_enabled) {
+		return;
+	}
+
 	draw_spaces = p_enabled;
 	update();
 }
@@ -5462,6 +5552,10 @@ void TextEdit::_bind_methods() {
 /* Internal API for CodeEdit. */
 // Line hiding.
 void TextEdit::_set_hiding_enabled(bool p_enabled) {
+	if (hiding_enabled == p_enabled) {
+		return;
+	}
+
 	if (!p_enabled) {
 		_unhide_all_lines();
 	}
@@ -5488,6 +5582,11 @@ void TextEdit::_unhide_all_lines() {
 
 void TextEdit::_set_line_as_hidden(int p_line, bool p_hidden) {
 	ERR_FAIL_INDEX(p_line, text.size());
+
+	if (text.is_hidden(p_line) == p_hidden) {
+		return;
+	}
+
 	if (_is_hiding_enabled() || !p_hidden) {
 		text.set_hidden(p_line, p_hidden);
 	}
@@ -5496,6 +5595,10 @@ void TextEdit::_set_line_as_hidden(int p_line, bool p_hidden) {
 
 // Symbol lookup.
 void TextEdit::_set_symbol_lookup_word(const String &p_symbol) {
+	if (lookup_symbol_word == p_symbol) {
+		return;
+	}
+
 	lookup_symbol_word = p_symbol;
 	update();
 }

+ 3 - 0
scene/gui/text_edit.h

@@ -195,6 +195,9 @@ private:
 
 		void set(int p_line, const String &p_text, const Array &p_bidi_override);
 		void set_hidden(int p_line, bool p_hidden) {
+			if (text[p_line].hidden == p_hidden) {
+				return;
+			}
 			text.write[p_line].hidden = p_hidden;
 			if (!p_hidden && text[p_line].width > max_width) {
 				max_width = text[p_line].width;

+ 35 - 0
scene/gui/texture_button.cpp

@@ -294,29 +294,48 @@ void TextureButton::_bind_methods() {
 }
 
 void TextureButton::set_normal_texture(const Ref<Texture2D> &p_normal) {
+	if (normal == p_normal) {
+		return;
+	}
+
 	normal = p_normal;
 	update();
 	update_minimum_size();
 }
 
 void TextureButton::set_pressed_texture(const Ref<Texture2D> &p_pressed) {
+	if (pressed == p_pressed) {
+		return;
+	}
+
 	pressed = p_pressed;
 	update();
 	update_minimum_size();
 }
 
 void TextureButton::set_hover_texture(const Ref<Texture2D> &p_hover) {
+	if (hover == p_hover) {
+		return;
+	}
+
 	hover = p_hover;
 	update();
 	update_minimum_size();
 }
 
 void TextureButton::set_disabled_texture(const Ref<Texture2D> &p_disabled) {
+	if (disabled == p_disabled) {
+		return;
+	}
+
 	disabled = p_disabled;
 	update();
 }
 
 void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
+	if (click_mask == p_click_mask) {
+		return;
+	}
 	click_mask = p_click_mask;
 	update();
 	update_minimum_size();
@@ -355,12 +374,20 @@ bool TextureButton::get_ignore_texture_size() const {
 }
 
 void TextureButton::set_ignore_texture_size(bool p_ignore) {
+	if (ignore_texture_size == p_ignore) {
+		return;
+	}
+
 	ignore_texture_size = p_ignore;
 	update_minimum_size();
 	update();
 }
 
 void TextureButton::set_stretch_mode(StretchMode p_stretch_mode) {
+	if (stretch_mode == p_stretch_mode) {
+		return;
+	}
+
 	stretch_mode = p_stretch_mode;
 	update();
 }
@@ -370,6 +397,10 @@ TextureButton::StretchMode TextureButton::get_stretch_mode() const {
 }
 
 void TextureButton::set_flip_h(bool p_flip) {
+	if (hflip == p_flip) {
+		return;
+	}
+
 	hflip = p_flip;
 	update();
 }
@@ -379,6 +410,10 @@ bool TextureButton::is_flipped_h() const {
 }
 
 void TextureButton::set_flip_v(bool p_flip) {
+	if (vflip == p_flip) {
+		return;
+	}
+
 	vflip = p_flip;
 	update();
 }

+ 58 - 1
scene/gui/texture_progress_bar.cpp

@@ -33,6 +33,10 @@
 #include "core/config/engine.h"
 
 void TextureProgressBar::set_under_texture(const Ref<Texture2D> &p_texture) {
+	if (under == p_texture) {
+		return;
+	}
+
 	under = p_texture;
 	update();
 	update_minimum_size();
@@ -43,6 +47,10 @@ Ref<Texture2D> TextureProgressBar::get_under_texture() const {
 }
 
 void TextureProgressBar::set_over_texture(const Ref<Texture2D> &p_texture) {
+	if (over == p_texture) {
+		return;
+	}
+
 	over = p_texture;
 	update();
 	if (under.is_null()) {
@@ -56,6 +64,11 @@ Ref<Texture2D> TextureProgressBar::get_over_texture() const {
 
 void TextureProgressBar::set_stretch_margin(Side p_side, int p_size) {
 	ERR_FAIL_INDEX((int)p_side, 4);
+
+	if (stretch_margin[p_side] == p_size) {
+		return;
+	}
+
 	stretch_margin[p_side] = p_size;
 	update();
 	update_minimum_size();
@@ -67,6 +80,10 @@ int TextureProgressBar::get_stretch_margin(Side p_side) const {
 }
 
 void TextureProgressBar::set_nine_patch_stretch(bool p_stretch) {
+	if (nine_patch_stretch == p_stretch) {
+		return;
+	}
+
 	nine_patch_stretch = p_stretch;
 	update();
 	update_minimum_size();
@@ -91,6 +108,10 @@ Size2 TextureProgressBar::get_minimum_size() const {
 }
 
 void TextureProgressBar::set_progress_texture(const Ref<Texture2D> &p_texture) {
+	if (progress == p_texture) {
+		return;
+	}
+
 	progress = p_texture;
 	update();
 	update_minimum_size();
@@ -101,6 +122,10 @@ Ref<Texture2D> TextureProgressBar::get_progress_texture() const {
 }
 
 void TextureProgressBar::set_progress_offset(Point2 p_offset) {
+	if (progress_offset == p_offset) {
+		return;
+	}
+
 	progress_offset = p_offset;
 	update();
 }
@@ -110,6 +135,10 @@ Point2 TextureProgressBar::get_progress_offset() const {
 }
 
 void TextureProgressBar::set_tint_under(const Color &p_tint) {
+	if (tint_under == p_tint) {
+		return;
+	}
+
 	tint_under = p_tint;
 	update();
 }
@@ -119,6 +148,10 @@ Color TextureProgressBar::get_tint_under() const {
 }
 
 void TextureProgressBar::set_tint_progress(const Color &p_tint) {
+	if (tint_progress == p_tint) {
+		return;
+	}
+
 	tint_progress = p_tint;
 	update();
 }
@@ -128,6 +161,10 @@ Color TextureProgressBar::get_tint_progress() const {
 }
 
 void TextureProgressBar::set_tint_over(const Color &p_tint) {
+	if (tint_over == p_tint) {
+		return;
+	}
+
 	tint_over = p_tint;
 	update();
 }
@@ -548,6 +585,11 @@ void TextureProgressBar::_notification(int p_what) {
 
 void TextureProgressBar::set_fill_mode(int p_fill) {
 	ERR_FAIL_INDEX(p_fill, FILL_MODE_MAX);
+
+	if (mode == (FillMode)p_fill) {
+		return;
+	}
+
 	mode = (FillMode)p_fill;
 	update();
 }
@@ -563,6 +605,11 @@ void TextureProgressBar::set_radial_initial_angle(float p_angle) {
 	while (p_angle < 0) {
 		p_angle += 360;
 	}
+
+	if (rad_init_angle == p_angle) {
+		return;
+	}
+
 	rad_init_angle = p_angle;
 	update();
 }
@@ -572,7 +619,13 @@ float TextureProgressBar::get_radial_initial_angle() {
 }
 
 void TextureProgressBar::set_fill_degrees(float p_angle) {
-	rad_max_degrees = CLAMP(p_angle, 0, 360);
+	float angle_clamped = CLAMP(p_angle, 0, 360);
+
+	if (rad_max_degrees == angle_clamped) {
+		return;
+	}
+
+	rad_max_degrees = angle_clamped;
 	update();
 }
 
@@ -581,6 +634,10 @@ float TextureProgressBar::get_fill_degrees() {
 }
 
 void TextureProgressBar::set_radial_center_offset(const Point2 &p_off) {
+	if (rad_center_off == p_off) {
+		return;
+	}
+
 	rad_center_off = p_off;
 	update();
 }

+ 16 - 0
scene/gui/texture_rect.cpp

@@ -179,6 +179,10 @@ Ref<Texture2D> TextureRect::get_texture() const {
 }
 
 void TextureRect::set_ignore_texture_size(bool p_ignore) {
+	if (ignore_texture_size == p_ignore) {
+		return;
+	}
+
 	ignore_texture_size = p_ignore;
 	update();
 	update_minimum_size();
@@ -189,6 +193,10 @@ bool TextureRect::get_ignore_texture_size() const {
 }
 
 void TextureRect::set_stretch_mode(StretchMode p_mode) {
+	if (stretch_mode == p_mode) {
+		return;
+	}
+
 	stretch_mode = p_mode;
 	update();
 }
@@ -198,6 +206,10 @@ TextureRect::StretchMode TextureRect::get_stretch_mode() const {
 }
 
 void TextureRect::set_flip_h(bool p_flip) {
+	if (hflip == p_flip) {
+		return;
+	}
+
 	hflip = p_flip;
 	update();
 }
@@ -207,6 +219,10 @@ bool TextureRect::is_flipped_h() const {
 }
 
 void TextureRect::set_flip_v(bool p_flip) {
+	if (vflip == p_flip) {
+		return;
+	}
+
 	vflip = p_flip;
 	update();
 }

+ 143 - 4
scene/gui/tree.cpp

@@ -141,6 +141,10 @@ void TreeItem::_change_tree(Tree *p_tree) {
 void TreeItem::set_cell_mode(int p_column, TreeCellMode p_mode) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].mode == p_mode) {
+		return;
+	}
+
 	Cell &c = cells.write[p_column];
 	c.mode = p_mode;
 	c.min = 0;
@@ -166,6 +170,10 @@ TreeItem::TreeCellMode TreeItem::get_cell_mode(int p_column) const {
 void TreeItem::set_checked(int p_column, bool p_checked) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].checked == p_checked) {
+		return;
+	}
+
 	cells.write[p_column].checked = p_checked;
 	cells.write[p_column].indeterminate = false;
 	cells.write[p_column].cached_minimum_size_dirty = true;
@@ -259,6 +267,11 @@ void TreeItem::_propagate_check_through_parents(int p_column, bool p_emit_signal
 
 void TreeItem::set_text(int p_column, String p_text) {
 	ERR_FAIL_INDEX(p_column, cells.size());
+
+	if (cells[p_column].text == p_text) {
+		return;
+	}
+
 	cells.write[p_column].text = p_text;
 	cells.write[p_column].dirty = true;
 
@@ -290,11 +303,14 @@ String TreeItem::get_text(int p_column) const {
 void TreeItem::set_text_direction(int p_column, Control::TextDirection p_text_direction) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 	ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
-	if (cells[p_column].text_direction != p_text_direction) {
-		cells.write[p_column].text_direction = p_text_direction;
-		cells.write[p_column].dirty = true;
-		_changed_notify(p_column);
+
+	if (cells[p_column].text_direction == p_text_direction) {
+		return;
 	}
+
+	cells.write[p_column].text_direction = p_text_direction;
+	cells.write[p_column].dirty = true;
+	_changed_notify(p_column);
 	cells.write[p_column].cached_minimum_size_dirty = true;
 }
 
@@ -323,6 +339,10 @@ TextServer::StructuredTextParser TreeItem::get_structured_text_bidi_override(int
 void TreeItem::set_structured_text_bidi_override_options(int p_column, Array p_args) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].st_args == p_args) {
+		return;
+	}
+
 	cells.write[p_column].st_args = p_args;
 	cells.write[p_column].dirty = true;
 	cells.write[p_column].cached_minimum_size_dirty = true;
@@ -355,6 +375,10 @@ String TreeItem::get_language(int p_column) const {
 void TreeItem::set_suffix(int p_column, String p_suffix) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].suffix == p_suffix) {
+		return;
+	}
+
 	cells.write[p_column].suffix = p_suffix;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -369,6 +393,10 @@ String TreeItem::get_suffix(int p_column) const {
 void TreeItem::set_icon(int p_column, const Ref<Texture2D> &p_icon) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].icon == p_icon) {
+		return;
+	}
+
 	cells.write[p_column].icon = p_icon;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -383,6 +411,10 @@ Ref<Texture2D> TreeItem::get_icon(int p_column) const {
 void TreeItem::set_icon_region(int p_column, const Rect2 &p_icon_region) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].icon_region == p_icon_region) {
+		return;
+	}
+
 	cells.write[p_column].icon_region = p_icon_region;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -396,6 +428,11 @@ Rect2 TreeItem::get_icon_region(int p_column) const {
 
 void TreeItem::set_icon_modulate(int p_column, const Color &p_modulate) {
 	ERR_FAIL_INDEX(p_column, cells.size());
+
+	if (cells[p_column].icon_color == p_modulate) {
+		return;
+	}
+
 	cells.write[p_column].icon_color = p_modulate;
 	_changed_notify(p_column);
 }
@@ -408,6 +445,10 @@ Color TreeItem::get_icon_modulate(int p_column) const {
 void TreeItem::set_icon_max_width(int p_column, int p_max) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].icon_max_w == p_max) {
+		return;
+	}
+
 	cells.write[p_column].icon_max_w = p_max;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -432,6 +473,10 @@ void TreeItem::set_range(int p_column, double p_value) {
 		p_value = cells[p_column].max;
 	}
 
+	if (cells[p_column].val == p_value) {
+		return;
+	}
+
 	cells.write[p_column].val = p_value;
 	cells.write[p_column].dirty = true;
 	_changed_notify(p_column);
@@ -449,6 +494,11 @@ bool TreeItem::is_range_exponential(int p_column) const {
 
 void TreeItem::set_range_config(int p_column, double p_min, double p_max, double p_step, bool p_exp) {
 	ERR_FAIL_INDEX(p_column, cells.size());
+
+	if (cells[p_column].min == p_min && cells[p_column].max == p_max && cells[p_column].step == p_step && cells[p_column].expr == p_exp) {
+		return;
+	}
+
 	cells.write[p_column].min = p_min;
 	cells.write[p_column].max = p_max;
 	cells.write[p_column].step = p_step;
@@ -537,6 +587,10 @@ void TreeItem::uncollapse_tree() {
 }
 
 void TreeItem::set_custom_minimum_height(int p_height) {
+	if (custom_min_height == p_height) {
+		return;
+	}
+
 	custom_min_height = p_height;
 
 	for (Cell &c : cells) {
@@ -913,6 +967,9 @@ void TreeItem::set_as_cursor(int p_column) {
 	if (tree->select_mode != Tree::SELECT_MULTI) {
 		return;
 	}
+	if (tree->selected_col == p_column) {
+		return;
+	}
 	tree->selected_item = this;
 	tree->selected_col = p_column;
 	tree->update();
@@ -990,6 +1047,11 @@ void TreeItem::set_button(int p_column, int p_idx, const Ref<Texture2D> &p_butto
 	ERR_FAIL_COND(p_button.is_null());
 	ERR_FAIL_INDEX(p_column, cells.size());
 	ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size());
+
+	if (cells[p_column].buttons[p_idx].texture == p_button) {
+		return;
+	}
+
 	cells.write[p_column].buttons.write[p_idx].texture = p_button;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -999,6 +1061,11 @@ void TreeItem::set_button(int p_column, int p_idx, const Ref<Texture2D> &p_butto
 void TreeItem::set_button_color(int p_column, int p_idx, const Color &p_color) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 	ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size());
+
+	if (cells[p_column].buttons[p_idx].color == p_color) {
+		return;
+	}
+
 	cells.write[p_column].buttons.write[p_idx].color = p_color;
 	_changed_notify(p_column);
 }
@@ -1007,6 +1074,10 @@ void TreeItem::set_button_disabled(int p_column, int p_idx, bool p_disabled) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 	ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size());
 
+	if (cells[p_column].buttons[p_idx].disabled == p_disabled) {
+		return;
+	}
+
 	cells.write[p_column].buttons.write[p_idx].disabled = p_disabled;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -1023,6 +1094,10 @@ bool TreeItem::is_button_disabled(int p_column, int p_idx) const {
 void TreeItem::set_editable(int p_column, bool p_editable) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].editable == p_editable) {
+		return;
+	}
+
 	cells.write[p_column].editable = p_editable;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -1036,6 +1111,11 @@ bool TreeItem::is_editable(int p_column) {
 
 void TreeItem::set_custom_color(int p_column, const Color &p_color) {
 	ERR_FAIL_INDEX(p_column, cells.size());
+
+	if (cells[p_column].custom_color == true) {
+		return;
+	}
+
 	cells.write[p_column].custom_color = true;
 	cells.write[p_column].color = p_color;
 	_changed_notify(p_column);
@@ -1092,6 +1172,11 @@ String TreeItem::get_tooltip(int p_column) const {
 
 void TreeItem::set_custom_bg_color(int p_column, const Color &p_color, bool p_bg_outline) {
 	ERR_FAIL_INDEX(p_column, cells.size());
+
+	if (cells[p_column].custom_bg_color && cells[p_column].custom_bg_outline == p_bg_outline && cells[p_column].bg_color == p_color) {
+		return;
+	}
+
 	cells.write[p_column].custom_bg_color = true;
 	cells.write[p_column].custom_bg_outline = p_bg_outline;
 	cells.write[p_column].bg_color = p_color;
@@ -1128,6 +1213,10 @@ bool TreeItem::is_custom_set_as_button(int p_column) const {
 void TreeItem::set_text_alignment(int p_column, HorizontalAlignment p_alignment) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].text_alignment == p_alignment) {
+		return;
+	}
+
 	cells.write[p_column].text_alignment = p_alignment;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -1142,6 +1231,10 @@ HorizontalAlignment TreeItem::get_text_alignment(int p_column) const {
 void TreeItem::set_expand_right(int p_column, bool p_enable) {
 	ERR_FAIL_INDEX(p_column, cells.size());
 
+	if (cells[p_column].expand_right == p_enable) {
+		return;
+	}
+
 	cells.write[p_column].expand_right = p_enable;
 	cells.write[p_column].cached_minimum_size_dirty = true;
 
@@ -1154,6 +1247,10 @@ bool TreeItem::get_expand_right(int p_column) const {
 }
 
 void TreeItem::set_disable_folding(bool p_disable) {
+	if (disable_folding == p_disable) {
+		return;
+	}
+
 	disable_folding = p_disable;
 
 	for (Cell &c : cells) {
@@ -4098,6 +4195,10 @@ void Tree::clear() {
 };
 
 void Tree::set_hide_root(bool p_enabled) {
+	if (hide_root == p_enabled) {
+		return;
+	}
+
 	hide_root = p_enabled;
 	update();
 }
@@ -4109,6 +4210,10 @@ bool Tree::is_root_hidden() const {
 void Tree::set_column_custom_minimum_width(int p_column, int p_min_width) {
 	ERR_FAIL_INDEX(p_column, columns.size());
 
+	if (columns[p_column].custom_min_width == p_min_width) {
+		return;
+	}
+
 	if (p_min_width < 0) {
 		return;
 	}
@@ -4119,12 +4224,21 @@ void Tree::set_column_custom_minimum_width(int p_column, int p_min_width) {
 void Tree::set_column_expand(int p_column, bool p_expand) {
 	ERR_FAIL_INDEX(p_column, columns.size());
 
+	if (columns[p_column].expand == p_expand) {
+		return;
+	}
+
 	columns.write[p_column].expand = p_expand;
 	update();
 }
 
 void Tree::set_column_expand_ratio(int p_column, int p_ratio) {
 	ERR_FAIL_INDEX(p_column, columns.size());
+
+	if (columns[p_column].expand_ratio == p_ratio) {
+		return;
+	}
+
 	columns.write[p_column].expand_ratio = p_ratio;
 	update();
 }
@@ -4132,6 +4246,10 @@ void Tree::set_column_expand_ratio(int p_column, int p_ratio) {
 void Tree::set_column_clip_content(int p_column, bool p_fit) {
 	ERR_FAIL_INDEX(p_column, columns.size());
 
+	if (columns[p_column].clip_content == p_fit) {
+		return;
+	}
+
 	columns.write[p_column].clip_content = p_fit;
 	update();
 }
@@ -4454,6 +4572,10 @@ Rect2 Tree::get_item_rect(TreeItem *p_item, int p_column, int p_button) const {
 }
 
 void Tree::set_column_titles_visible(bool p_show) {
+	if (show_column_titles == p_show) {
+		return;
+	}
+
 	show_column_titles = p_show;
 	update();
 }
@@ -4464,6 +4586,11 @@ bool Tree::are_column_titles_visible() const {
 
 void Tree::set_column_title(int p_column, const String &p_title) {
 	ERR_FAIL_INDEX(p_column, columns.size());
+
+	if (columns[p_column].title == p_title) {
+		return;
+	}
+
 	if (cache.font.is_null()) { // avoid a strange case that may corrupt stuff
 		update_cache();
 	}
@@ -4545,6 +4672,10 @@ void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) {
 }
 
 void Tree::set_h_scroll_enabled(bool p_enable) {
+	if (h_scroll_enabled == p_enable) {
+		return;
+	}
+
 	h_scroll_enabled = p_enable;
 	update_minimum_size();
 }
@@ -4554,6 +4685,10 @@ bool Tree::is_h_scroll_enabled() const {
 }
 
 void Tree::set_v_scroll_enabled(bool p_enable) {
+	if (v_scroll_enabled == p_enable) {
+		return;
+	}
+
 	v_scroll_enabled = p_enable;
 	update_minimum_size();
 }
@@ -4882,6 +5017,10 @@ void Tree::set_cursor_can_exit_tree(bool p_enable) {
 }
 
 void Tree::set_hide_folding(bool p_hide) {
+	if (hide_folding == p_hide) {
+		return;
+	}
+
 	hide_folding = p_hide;
 	update();
 }

+ 8 - 0
scene/gui/video_stream_player.cpp

@@ -208,6 +208,10 @@ Size2 VideoStreamPlayer::get_minimum_size() const {
 }
 
 void VideoStreamPlayer::set_expand(bool p_expand) {
+	if (expand == p_expand) {
+		return;
+	}
+
 	expand = p_expand;
 	update();
 	update_minimum_size();
@@ -306,6 +310,10 @@ bool VideoStreamPlayer::is_playing() const {
 }
 
 void VideoStreamPlayer::set_paused(bool p_paused) {
+	if (paused == p_paused) {
+		return;
+	}
+
 	paused = p_paused;
 	if (!p_paused && !can_process()) {
 		paused_from_tree = true;