diff options
Diffstat (limited to 'scene')
78 files changed, 1078 insertions, 165 deletions
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index a761d0d1ec..f8e30c2462 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -33,6 +33,7 @@ #include "scene/2d/area_2d.h" #include "scene/2d/audio_listener_2d.h" #include "scene/main/window.h" +#include "scene/resources/world_2d.h" void AudioStreamPlayer2D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index e8dfaf9c2e..548cd5de9a 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -30,6 +30,7 @@ #include "camera_2d.h" +#include "core/config/project_settings.h" #include "scene/main/window.h" void Camera2D::_update_scroll() { diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 70c7e48fd4..fbfe1d7eff 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -30,6 +30,7 @@ #include "collision_object_2d.h" +#include "scene/resources/world_2d.h" #include "scene/scene_string_names.h" void CollisionObject2D::_notification(int p_what) { diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 9331f2dccb..1bbf7236c5 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -31,6 +31,7 @@ #include "navigation_agent_2d.h" #include "core/math/geometry_2d.h" +#include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" void NavigationAgent2D::_bind_methods() { diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index fad54070a5..90d993f20b 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -31,6 +31,7 @@ #include "navigation_obstacle_2d.h" #include "scene/2d/collision_shape_2d.h" +#include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" void NavigationObstacle2D::_bind_methods() { diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index e685ad8f67..99d8b0f604 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -33,6 +33,7 @@ #include "core/core_string_names.h" #include "core/math/geometry_2d.h" #include "core/os/mutex.h" +#include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" #include "thirdparty/misc/polypartition.h" diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 51b3e676f9..8b69d52c32 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -31,6 +31,7 @@ #include "ray_cast_2d.h" #include "collision_object_2d.h" +#include "scene/resources/world_2d.h" void RayCast2D::set_target_position(const Vector2 &p_point) { target_position = p_point; diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/shape_cast_2d.h index ea36b25068..15436d6e3d 100644 --- a/scene/2d/shape_cast_2d.h +++ b/scene/2d/shape_cast_2d.h @@ -33,6 +33,7 @@ #include "scene/2d/node_2d.h" #include "scene/resources/shape_2d.h" +#include "scene/resources/world_2d.h" class CollisionObject2D; diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 2270926ea7..a12147b7fd 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -31,6 +31,7 @@ #include "skeleton_2d.h" #ifdef TOOLS_ENABLED +#include "editor/editor_data.h" #include "editor/editor_settings.h" #include "editor/plugins/canvas_item_editor_plugin.h" #endif //TOOLS_ENABLED diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 02ca1ba2aa..cd39e08682 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -31,7 +31,7 @@ #include "tile_map.h" #include "core/io/marshalls.h" - +#include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" Map<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlapping_coords_and_peering_bits() const { diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h index b5665814c7..9f2f8ceed1 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -33,6 +33,8 @@ #include "scene/3d/node_3d.h" #include "scene/3d/velocity_tracker_3d.h" +#include "scene/resources/camera_effects.h" +#include "scene/resources/environment.h" class Camera3D : public Node3D { GDCLASS(Camera3D, Node3D); diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index 4abda66187..65d0e071cf 100644 --- a/scene/3d/node_3d.h +++ b/scene/3d/node_3d.h @@ -32,6 +32,7 @@ #define NODE_3D_H #include "scene/main/node.h" +#include "scene/resources/world_3d.h" class Node3DGizmo : public RefCounted { GDCLASS(Node3DGizmo, RefCounted); diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp index 0277171922..231817526c 100644 --- a/scene/3d/occluder_instance_3d.cpp +++ b/scene/3d/occluder_instance_3d.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "occluder_instance_3d.h" + +#include "core/config/project_settings.h" #include "core/core_string_names.h" #include "core/math/geometry_2d.h" #include "core/math/triangulate.h" diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index 66d1b97056..211c39c949 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -30,6 +30,7 @@ #include "xr_nodes.h" +#include "core/config/project_settings.h" #include "scene/main/viewport.h" #include "servers/xr/xr_interface.h" diff --git a/scene/gui/aspect_ratio_container.cpp b/scene/gui/aspect_ratio_container.cpp index 181d1bf33b..b59eda465e 100644 --- a/scene/gui/aspect_ratio_container.cpp +++ b/scene/gui/aspect_ratio_container.cpp @@ -70,6 +70,24 @@ void AspectRatioContainer::set_alignment_vertical(AlignmentMode p_alignment_vert queue_sort(); } +Vector<int> AspectRatioContainer::get_allowed_size_flags_horizontal() const { + Vector<int> flags; + flags.append(SIZE_FILL); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + +Vector<int> AspectRatioContainer::get_allowed_size_flags_vertical() const { + Vector<int> flags; + flags.append(SIZE_FILL); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + void AspectRatioContainer::_notification(int p_what) { switch (p_what) { case NOTIFICATION_SORT_CHILDREN: { diff --git a/scene/gui/aspect_ratio_container.h b/scene/gui/aspect_ratio_container.h index 4a168bad14..6740e2f329 100644 --- a/scene/gui/aspect_ratio_container.h +++ b/scene/gui/aspect_ratio_container.h @@ -72,6 +72,9 @@ public: void set_alignment_vertical(AlignmentMode p_alignment_vertical); AlignmentMode get_alignment_vertical() const { return alignment_vertical; } + + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; }; VARIANT_ENUM_CAST(AspectRatioContainer::StretchMode); diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 0bcad4fc0e..6bfffe7575 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -31,6 +31,7 @@ #ifndef BASE_BUTTON_H #define BASE_BUTTON_H +#include "core/input/shortcut.h" #include "scene/gui/control.h" class ButtonGroup; diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 9827bd0cef..ed54410636 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -331,6 +331,30 @@ Control *BoxContainer::add_spacer(bool p_begin) { return c; } +Vector<int> BoxContainer::get_allowed_size_flags_horizontal() const { + Vector<int> flags; + flags.append(SIZE_FILL); + if (!vertical) { + flags.append(SIZE_EXPAND); + } + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + +Vector<int> BoxContainer::get_allowed_size_flags_vertical() const { + Vector<int> flags; + flags.append(SIZE_FILL); + if (vertical) { + flags.append(SIZE_EXPAND); + } + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + BoxContainer::BoxContainer(bool p_vertical) { vertical = p_vertical; } diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index 68d55e1aaf..3043c3ea45 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -62,6 +62,9 @@ public: virtual Size2 get_minimum_size() const override; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + BoxContainer(bool p_vertical = false); }; diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp index f3306783f3..f6cd74583b 100644 --- a/scene/gui/center_container.cpp +++ b/scene/gui/center_container.cpp @@ -69,6 +69,14 @@ bool CenterContainer::is_using_top_left() const { return use_top_left; } +Vector<int> CenterContainer::get_allowed_size_flags_horizontal() const { + return Vector<int>(); +} + +Vector<int> CenterContainer::get_allowed_size_flags_vertical() const { + return Vector<int>(); +} + void CenterContainer::_notification(int p_what) { if (p_what == NOTIFICATION_SORT_CHILDREN) { Size2 size = get_size(); diff --git a/scene/gui/center_container.h b/scene/gui/center_container.h index 16a10c8070..c35e0c4e29 100644 --- a/scene/gui/center_container.h +++ b/scene/gui/center_container.h @@ -48,6 +48,9 @@ public: virtual Size2 get_minimum_size() const override; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + CenterContainer(); }; diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 8cb8a78e8d..c4e67c2951 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -84,7 +84,7 @@ void CodeEdit::_notification(int p_what) { if (line_length_guideline_columns.size() > 0) { const int xmargin_beg = style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width(); const int xmargin_end = size.width - style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0); - const int char_size = Math::round(font->get_char_size('0', 0, font_size).width); + const float char_size = font->get_char_size('0', 0, font_size).width; for (int i = 0; i < line_length_guideline_columns.size(); i++) { const int xoffset = xmargin_beg + char_size * (int)line_length_guideline_columns[i] - get_h_scroll(); diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 7b213ec314..b8a5a06147 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -143,6 +143,34 @@ void Container::queue_sort() { pending_sort = true; } +Vector<int> Container::get_allowed_size_flags_horizontal() const { + Vector<int> flags; + if (GDVIRTUAL_CALL(_get_allowed_size_flags_horizontal, flags)) { + return flags; + } + + flags.append(SIZE_FILL); + flags.append(SIZE_EXPAND); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + +Vector<int> Container::get_allowed_size_flags_vertical() const { + Vector<int> flags; + if (GDVIRTUAL_CALL(_get_allowed_size_flags_vertical, flags)) { + return flags; + } + + flags.append(SIZE_FILL); + flags.append(SIZE_EXPAND); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + void Container::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -177,6 +205,9 @@ void Container::_bind_methods() { ClassDB::bind_method(D_METHOD("queue_sort"), &Container::queue_sort); ClassDB::bind_method(D_METHOD("fit_child_in_rect", "child", "rect"), &Container::fit_child_in_rect); + GDVIRTUAL_BIND(_get_allowed_size_flags_horizontal); + GDVIRTUAL_BIND(_get_allowed_size_flags_vertical); + BIND_CONSTANT(NOTIFICATION_PRE_SORT_CHILDREN); BIND_CONSTANT(NOTIFICATION_SORT_CHILDREN); diff --git a/scene/gui/container.h b/scene/gui/container.h index 0e986f46ef..9ec4ad3200 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -46,6 +46,9 @@ protected: virtual void move_child_notify(Node *p_child) override; virtual void remove_child_notify(Node *p_child) override; + GDVIRTUAL0RC(Vector<int>, _get_allowed_size_flags_horizontal) + GDVIRTUAL0RC(Vector<int>, _get_allowed_size_flags_vertical) + void _notification(int p_what); static void _bind_methods(); @@ -57,6 +60,9 @@ public: void fit_child_in_rect(Control *p_child, const Rect2 &p_rect); + virtual Vector<int> get_allowed_size_flags_horizontal() const; + virtual Vector<int> get_allowed_size_flags_vertical() const; + TypedArray<String> get_configuration_warnings() const override; Container(); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index fdae8e2f1f..943ba8dfb1 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -47,7 +47,7 @@ #include "servers/text_server.h" #ifdef TOOLS_ENABLED -#include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/plugins/control_editor_plugin.h" #endif #ifdef TOOLS_ENABLED @@ -56,51 +56,71 @@ Dictionary Control::_edit_get_state() const { s["rotation"] = get_rotation(); s["scale"] = get_scale(); s["pivot"] = get_pivot_offset(); + Array anchors; anchors.push_back(get_anchor(SIDE_LEFT)); anchors.push_back(get_anchor(SIDE_TOP)); anchors.push_back(get_anchor(SIDE_RIGHT)); anchors.push_back(get_anchor(SIDE_BOTTOM)); s["anchors"] = anchors; + Array offsets; offsets.push_back(get_offset(SIDE_LEFT)); offsets.push_back(get_offset(SIDE_TOP)); offsets.push_back(get_offset(SIDE_RIGHT)); offsets.push_back(get_offset(SIDE_BOTTOM)); s["offsets"] = offsets; + + s["layout_mode"] = _get_layout_mode(); + s["anchors_layout_preset"] = _get_anchors_layout_preset(); + return s; } void Control::_edit_set_state(const Dictionary &p_state) { ERR_FAIL_COND((p_state.size() <= 0) || !p_state.has("rotation") || !p_state.has("scale") || - !p_state.has("pivot") || !p_state.has("anchors") || !p_state.has("offsets")); + !p_state.has("pivot") || !p_state.has("anchors") || !p_state.has("offsets") || + !p_state.has("layout_mode") || !p_state.has("anchors_layout_preset")); Dictionary state = p_state; set_rotation(state["rotation"]); set_scale(state["scale"]); set_pivot_offset(state["pivot"]); + Array anchors = state["anchors"]; + + // If anchors are not in their default position, force the anchor layout mode in place of position. + LayoutMode _layout = (LayoutMode)(int)state["layout_mode"]; + if (_layout == LayoutMode::LAYOUT_MODE_POSITION) { + bool anchors_mode = ((real_t)anchors[0] != 0.0 || (real_t)anchors[1] != 0.0 || (real_t)anchors[2] != 0.0 || (real_t)anchors[3] != 0.0); + if (anchors_mode) { + _layout = LayoutMode::LAYOUT_MODE_ANCHORS; + } + } + + _set_layout_mode(_layout); + if (_layout == LayoutMode::LAYOUT_MODE_ANCHORS) { + _set_anchors_layout_preset((int)state["anchors_layout_preset"]); + } + data.anchor[SIDE_LEFT] = anchors[0]; data.anchor[SIDE_TOP] = anchors[1]; data.anchor[SIDE_RIGHT] = anchors[2]; data.anchor[SIDE_BOTTOM] = anchors[3]; + Array offsets = state["offsets"]; data.offset[SIDE_LEFT] = offsets[0]; data.offset[SIDE_TOP] = offsets[1]; data.offset[SIDE_RIGHT] = offsets[2]; data.offset[SIDE_BOTTOM] = offsets[3]; + _size_changed(); } void Control::_edit_set_position(const Point2 &p_position) { -#ifdef TOOLS_ENABLED ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins."); - set_position(p_position, CanvasItemEditor::get_singleton()->is_anchors_mode_enabled() && Object::cast_to<Control>(data.parent)); -#else - // Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED - set_position(p_position); -#endif + set_position(p_position, ControlEditorToolbar::get_singleton()->is_anchors_mode_enabled() && Object::cast_to<Control>(data.parent)); }; Point2 Control::_edit_get_position() const { @@ -116,15 +136,9 @@ Size2 Control::_edit_get_scale() const { } void Control::_edit_set_rect(const Rect2 &p_edit_rect) { -#ifdef TOOLS_ENABLED ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins."); - set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled()); - set_size(p_edit_rect.size.snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled()); -#else - // Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED - set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1))); - set_size(p_edit_rect.size.snapped(Vector2(1, 1))); -#endif + set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1)), ControlEditorToolbar::get_singleton()->is_anchors_mode_enabled()); + set_size(p_edit_rect.size.snapped(Vector2(1, 1)), ControlEditorToolbar::get_singleton()->is_anchors_mode_enabled()); } Rect2 Control::_edit_get_rect() const { @@ -177,6 +191,7 @@ String Control::properties_managed_by_container[] = { "anchor_right", "anchor_bottom", "rect_position", + "rect_rotation", "rect_scale", "rect_size" }; @@ -430,6 +445,7 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const { } void Control::_validate_property(PropertyInfo &property) const { + // Update theme type variation options. if (property.name == "theme_type_variation") { List<StringName> names; @@ -455,10 +471,99 @@ void Control::_validate_property(PropertyInfo &property) const { property.hint_string = hint_string; } - if (!Object::cast_to<Container>(get_parent())) { - return; + + // Validate which positioning properties should be displayed depending on the parent and the layout mode. + Node *parent_node = get_parent_control(); + if (!parent_node) { + // If there is no parent, display both anchor and container options. + + // Set the layout mode to be disabled with the proper value. + if (property.name == "layout_mode") { + property.hint_string = "Position,Anchors,Container,Uncontrolled"; + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + + // Use the layout mode to display or hide advanced anchoring properties. + bool use_custom_anchors = _get_anchors_layout_preset() == -1; // Custom "preset". + if (!use_custom_anchors && (property.name.begins_with("anchor_") || property.name.begins_with("offset_") || property.name.begins_with("grow_"))) { + property.usage ^= PROPERTY_USAGE_EDITOR; + } + } else if (Object::cast_to<Container>(parent_node)) { + // If the parent is a container, display only container-related properties. + if (property.name.begins_with("anchor_") || property.name.begins_with("offset_") || property.name.begins_with("grow_") || property.name == "anchors_preset" || + (property.name.begins_with("rect_") && property.name != "rect_min_size" && property.name != "rect_clip_content" && property.name != "rect_global_position")) { + property.usage ^= PROPERTY_USAGE_EDITOR; + + } else if (property.name == "layout_mode") { + // Set the layout mode to be disabled with the proper value. + property.hint_string = "Position,Anchors,Container,Uncontrolled"; + property.usage |= PROPERTY_USAGE_READ_ONLY; + } else if (property.name == "size_flags_horizontal" || property.name == "size_flags_vertical") { + // Filter allowed size flags based on the parent container configuration. + Container *parent_container = Object::cast_to<Container>(parent_node); + Vector<int> size_flags; + if (property.name == "size_flags_horizontal") { + size_flags = parent_container->get_allowed_size_flags_horizontal(); + } else if (property.name == "size_flags_vertical") { + size_flags = parent_container->get_allowed_size_flags_vertical(); + } + + // Enforce the order of the options, regardless of what the container provided. + String hint_string; + if (size_flags.has(SIZE_FILL)) { + hint_string += "Fill:1"; + } + if (size_flags.has(SIZE_EXPAND)) { + if (!hint_string.is_empty()) { + hint_string += ","; + } + hint_string += "Expand:2"; + } + if (size_flags.has(SIZE_SHRINK_CENTER)) { + if (!hint_string.is_empty()) { + hint_string += ","; + } + hint_string += "Shrink Center:4"; + } + if (size_flags.has(SIZE_SHRINK_END)) { + if (!hint_string.is_empty()) { + hint_string += ","; + } + hint_string += "Shrink End:8"; + } + + if (hint_string.is_empty()) { + property.hint_string = ""; + property.usage |= PROPERTY_USAGE_READ_ONLY; + } else { + property.hint_string = hint_string; + } + } + } else { + // If the parent is NOT a container or not a control at all, display only anchoring-related properties. + if (property.name.begins_with("size_flags_")) { + property.usage ^= PROPERTY_USAGE_EDITOR; + + } else if (property.name == "layout_mode") { + // Set the layout mode to be enabled with proper options. + property.hint_string = "Position,Anchors"; + } + + // Use the layout mode to display or hide advanced anchoring properties. + bool use_anchors = _get_layout_mode() == LayoutMode::LAYOUT_MODE_ANCHORS; + if (!use_anchors && property.name == "anchors_preset") { + property.usage ^= PROPERTY_USAGE_EDITOR; + } + bool use_custom_anchors = use_anchors && _get_anchors_layout_preset() == -1; // Custom "preset". + if (!use_custom_anchors && (property.name.begins_with("anchor_") || property.name.begins_with("offset_") || property.name.begins_with("grow_"))) { + property.usage ^= PROPERTY_USAGE_EDITOR; + } } + // Disable the property if it's managed by the parent container. + if (!Object::cast_to<Container>(parent_node)) { + return; + } bool property_is_managed_by_container = false; for (unsigned i = 0; i < properties_managed_by_container_count; i++) { property_is_managed_by_container = properties_managed_by_container[i] == property.name; @@ -1390,6 +1495,54 @@ void Control::_size_changed() { } } +void Control::_set_layout_mode(LayoutMode p_mode) { + bool list_changed = false; + + if (p_mode == LayoutMode::LAYOUT_MODE_POSITION || p_mode == LayoutMode::LAYOUT_MODE_ANCHORS) { + if (has_meta("_edit_layout_mode") && (int)get_meta("_edit_layout_mode") != (int)p_mode) { + list_changed = true; + } + + set_meta("_edit_layout_mode", (int)p_mode); + + if (p_mode == LayoutMode::LAYOUT_MODE_POSITION) { + set_meta("_edit_use_custom_anchors", false); + set_anchors_and_offsets_preset(LayoutPreset::PRESET_TOP_LEFT, LayoutPresetMode::PRESET_MODE_KEEP_SIZE); + set_grow_direction_preset(LayoutPreset::PRESET_TOP_LEFT); + } + } else { + if (has_meta("_edit_layout_mode")) { + remove_meta("_edit_layout_mode"); + list_changed = true; + } + } + + if (list_changed) { + notify_property_list_changed(); + } +} + +Control::LayoutMode Control::_get_layout_mode() const { + Node *parent_node = get_parent_control(); + // In these modes the property is read-only. + if (!parent_node) { + return LayoutMode::LAYOUT_MODE_UNCONTROLLED; + } else if (Object::cast_to<Container>(parent_node)) { + return LayoutMode::LAYOUT_MODE_CONTAINER; + } + + // If anchors are not in the top-left position, this is definitely in anchors mode. + if (_get_anchors_layout_preset() != (int)LayoutPreset::PRESET_TOP_LEFT) { + return LayoutMode::LAYOUT_MODE_ANCHORS; + } + // Otherwise check what was saved. + if (has_meta("_edit_layout_mode")) { + return (LayoutMode)(int)get_meta("_edit_layout_mode"); + } + // Or fallback on default. + return LayoutMode::LAYOUT_MODE_POSITION; +} + void Control::set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) { ERR_FAIL_INDEX((int)p_side, 4); @@ -1431,6 +1584,133 @@ void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos, set_offset(p_side, p_pos); } +void Control::_set_anchors_layout_preset(int p_preset) { + bool list_changed = false; + + if (has_meta("_edit_layout_mode") && (int)get_meta("_edit_layout_mode") != (int)LayoutMode::LAYOUT_MODE_ANCHORS) { + list_changed = true; + set_meta("_edit_layout_mode", (int)LayoutMode::LAYOUT_MODE_ANCHORS); + } + + if (p_preset == -1) { + if (!has_meta("_edit_use_custom_anchors") || !(bool)get_meta("_edit_use_custom_anchors")) { + set_meta("_edit_use_custom_anchors", true); + notify_property_list_changed(); + } + return; // Keep settings as is. + } + + if (!has_meta("_edit_use_custom_anchors") || (bool)get_meta("_edit_use_custom_anchors")) { + list_changed = true; + set_meta("_edit_use_custom_anchors", false); + } + + LayoutPreset preset = (LayoutPreset)p_preset; + // Set correct anchors. + set_anchors_preset(preset); + + // Select correct preset mode. + switch (preset) { + case PRESET_TOP_LEFT: + case PRESET_TOP_RIGHT: + case PRESET_BOTTOM_LEFT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_LEFT: + case PRESET_CENTER_TOP: + case PRESET_CENTER_RIGHT: + case PRESET_CENTER_BOTTOM: + case PRESET_CENTER: + set_offsets_preset(preset, LayoutPresetMode::PRESET_MODE_KEEP_SIZE); + break; + case PRESET_LEFT_WIDE: + case PRESET_TOP_WIDE: + case PRESET_RIGHT_WIDE: + case PRESET_BOTTOM_WIDE: + case PRESET_VCENTER_WIDE: + case PRESET_HCENTER_WIDE: + case PRESET_WIDE: + set_offsets_preset(preset, LayoutPresetMode::PRESET_MODE_MINSIZE); + break; + } + + // Select correct grow directions. + set_grow_direction_preset(preset); + + if (list_changed) { + notify_property_list_changed(); + } +} + +int Control::_get_anchors_layout_preset() const { + // If the custom preset was selected by user, use it. + if (has_meta("_edit_use_custom_anchors") && (bool)get_meta("_edit_use_custom_anchors")) { + return -1; + } + + // Check anchors to determine if the current state matches a preset, or not. + + float left = get_anchor(SIDE_LEFT); + float right = get_anchor(SIDE_RIGHT); + float top = get_anchor(SIDE_TOP); + float bottom = get_anchor(SIDE_BOTTOM); + + if (left == ANCHOR_BEGIN && right == ANCHOR_BEGIN && top == ANCHOR_BEGIN && bottom == ANCHOR_BEGIN) { + return (int)LayoutPreset::PRESET_TOP_LEFT; + } + if (left == ANCHOR_END && right == ANCHOR_END && top == ANCHOR_BEGIN && bottom == ANCHOR_BEGIN) { + return (int)LayoutPreset::PRESET_TOP_RIGHT; + } + if (left == ANCHOR_BEGIN && right == ANCHOR_BEGIN && top == ANCHOR_END && bottom == ANCHOR_END) { + return (int)LayoutPreset::PRESET_BOTTOM_LEFT; + } + if (left == ANCHOR_END && right == ANCHOR_END && top == ANCHOR_END && bottom == ANCHOR_END) { + return (int)LayoutPreset::PRESET_BOTTOM_RIGHT; + } + + if (left == ANCHOR_BEGIN && right == ANCHOR_BEGIN && top == 0.5 && bottom == 0.5) { + return (int)LayoutPreset::PRESET_CENTER_LEFT; + } + if (left == ANCHOR_END && right == ANCHOR_END && top == 0.5 && bottom == 0.5) { + return (int)LayoutPreset::PRESET_CENTER_RIGHT; + } + if (left == 0.5 && right == 0.5 && top == ANCHOR_BEGIN && bottom == ANCHOR_BEGIN) { + return (int)LayoutPreset::PRESET_CENTER_TOP; + } + if (left == 0.5 && right == 0.5 && top == ANCHOR_END && bottom == ANCHOR_END) { + return (int)LayoutPreset::PRESET_CENTER_BOTTOM; + } + if (left == 0.5 && right == 0.5 && top == 0.5 && bottom == 0.5) { + return (int)LayoutPreset::PRESET_CENTER; + } + + if (left == ANCHOR_BEGIN && right == ANCHOR_BEGIN && top == ANCHOR_BEGIN && bottom == ANCHOR_END) { + return (int)LayoutPreset::PRESET_LEFT_WIDE; + } + if (left == ANCHOR_END && right == ANCHOR_END && top == ANCHOR_BEGIN && bottom == ANCHOR_END) { + return (int)LayoutPreset::PRESET_RIGHT_WIDE; + } + if (left == ANCHOR_BEGIN && right == ANCHOR_END && top == ANCHOR_BEGIN && bottom == ANCHOR_BEGIN) { + return (int)LayoutPreset::PRESET_TOP_WIDE; + } + if (left == ANCHOR_BEGIN && right == ANCHOR_END && top == ANCHOR_END && bottom == ANCHOR_END) { + return (int)LayoutPreset::PRESET_BOTTOM_WIDE; + } + + if (left == 0.5 && right == 0.5 && top == ANCHOR_BEGIN && bottom == ANCHOR_END) { + return (int)LayoutPreset::PRESET_VCENTER_WIDE; + } + if (left == ANCHOR_BEGIN && right == ANCHOR_END && top == 0.5 && bottom == 0.5) { + return (int)LayoutPreset::PRESET_HCENTER_WIDE; + } + + if (left == ANCHOR_BEGIN && right == ANCHOR_END && top == ANCHOR_BEGIN && bottom == ANCHOR_END) { + return (int)LayoutPreset::PRESET_WIDE; + } + + // Does not match any preset, return "Custom". + return -1; +} + void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets) { ERR_FAIL_INDEX((int)p_preset, 16); @@ -1687,6 +1967,62 @@ void Control::set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPreset set_offsets_preset(p_preset, p_resize_mode, p_margin); } +void Control::set_grow_direction_preset(LayoutPreset p_preset) { + // Select correct horizontal grow direction. + switch (p_preset) { + case PRESET_TOP_LEFT: + case PRESET_BOTTOM_LEFT: + case PRESET_CENTER_LEFT: + case PRESET_LEFT_WIDE: + set_h_grow_direction(GrowDirection::GROW_DIRECTION_END); + break; + case PRESET_TOP_RIGHT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_RIGHT: + case PRESET_RIGHT_WIDE: + set_h_grow_direction(GrowDirection::GROW_DIRECTION_BEGIN); + break; + case PRESET_CENTER_TOP: + case PRESET_CENTER_BOTTOM: + case PRESET_CENTER: + case PRESET_TOP_WIDE: + case PRESET_BOTTOM_WIDE: + case PRESET_VCENTER_WIDE: + case PRESET_HCENTER_WIDE: + case PRESET_WIDE: + set_h_grow_direction(GrowDirection::GROW_DIRECTION_BOTH); + break; + } + + // Select correct vertical grow direction. + switch (p_preset) { + case PRESET_TOP_LEFT: + case PRESET_TOP_RIGHT: + case PRESET_CENTER_TOP: + case PRESET_TOP_WIDE: + set_v_grow_direction(GrowDirection::GROW_DIRECTION_END); + break; + + case PRESET_BOTTOM_LEFT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_BOTTOM: + case PRESET_BOTTOM_WIDE: + set_v_grow_direction(GrowDirection::GROW_DIRECTION_BEGIN); + break; + + case PRESET_CENTER_LEFT: + case PRESET_CENTER_RIGHT: + case PRESET_CENTER: + case PRESET_LEFT_WIDE: + case PRESET_RIGHT_WIDE: + case PRESET_VCENTER_WIDE: + case PRESET_HCENTER_WIDE: + case PRESET_WIDE: + set_v_grow_direction(GrowDirection::GROW_DIRECTION_BOTH); + break; + } +} + real_t Control::get_anchor(Side p_side) const { ERR_FAIL_INDEX_V(int(p_side), 4, 0.0); @@ -2847,14 +3183,22 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("accept_event"), &Control::accept_event); ClassDB::bind_method(D_METHOD("get_minimum_size"), &Control::get_minimum_size); ClassDB::bind_method(D_METHOD("get_combined_minimum_size"), &Control::get_combined_minimum_size); + + ClassDB::bind_method(D_METHOD("_set_layout_mode", "mode"), &Control::_set_layout_mode); + ClassDB::bind_method(D_METHOD("_get_layout_mode"), &Control::_get_layout_mode); + ClassDB::bind_method(D_METHOD("_set_anchors_layout_preset", "preset"), &Control::_set_anchors_layout_preset); + ClassDB::bind_method(D_METHOD("_get_anchors_layout_preset"), &Control::_get_anchors_layout_preset); ClassDB::bind_method(D_METHOD("set_anchors_preset", "preset", "keep_offsets"), &Control::set_anchors_preset, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_offsets_preset", "preset", "resize_mode", "margin"), &Control::set_offsets_preset, DEFVAL(PRESET_MODE_MINSIZE), DEFVAL(0)); ClassDB::bind_method(D_METHOD("set_anchors_and_offsets_preset", "preset", "resize_mode", "margin"), &Control::set_anchors_and_offsets_preset, DEFVAL(PRESET_MODE_MINSIZE), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("_set_anchor", "side", "anchor"), &Control::_set_anchor); ClassDB::bind_method(D_METHOD("set_anchor", "side", "anchor", "keep_offset", "push_opposite_anchor"), &Control::set_anchor, DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_anchor", "side"), &Control::get_anchor); ClassDB::bind_method(D_METHOD("set_offset", "side", "offset"), &Control::set_offset); + ClassDB::bind_method(D_METHOD("get_offset", "offset"), &Control::get_offset); ClassDB::bind_method(D_METHOD("set_anchor_and_offset", "side", "anchor", "offset", "push_opposite_anchor"), &Control::set_anchor_and_offset, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("set_begin", "position"), &Control::set_begin); ClassDB::bind_method(D_METHOD("set_end", "position"), &Control::set_end); ClassDB::bind_method(D_METHOD("set_position", "position", "keep_offsets"), &Control::set_position, DEFVAL(false)); @@ -2868,7 +3212,6 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale); ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset); - ClassDB::bind_method(D_METHOD("get_offset", "offset"), &Control::get_offset); ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin); ClassDB::bind_method(D_METHOD("get_end"), &Control::get_end); ClassDB::bind_method(D_METHOD("get_position"), &Control::get_position); @@ -2996,37 +3339,54 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_auto_translate", "enable"), &Control::set_auto_translate); ClassDB::bind_method(D_METHOD("is_auto_translating"), &Control::is_auto_translating); - ADD_GROUP("Anchor", "anchor_"); + ADD_GROUP("Layout", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode"); + ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION); + + const String anchors_presets_options = "Custom:-1,PresetWide:15," + "PresetTopLeft:0,PresetTopRight:1,PresetBottomRight:3,PresetBottomLeft:2," + "PresetCenterLeft:4,PresetCenterTop:5,PresetCenterRight:6,PresetCenterBottom:7,PresetCenter:8," + "PresetLeftWide:9,PresetTopWide:10,PresetRightWide:11,PresetBottomWide:12,PresetVCenterWide:13,PresetHCenterWide:14"; + + ADD_PROPERTY(PropertyInfo(Variant::INT, "anchors_preset", PROPERTY_HINT_ENUM, anchors_presets_options, PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_anchors_layout_preset", "_get_anchors_layout_preset"); + ADD_PROPERTY_DEFAULT("anchors_preset", -1); + + ADD_SUBGROUP_INDENT("Anchor Points", "anchor_", 1); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anchor_left", PROPERTY_HINT_RANGE, "0,1,0.001,or_lesser,or_greater"), "_set_anchor", "get_anchor", SIDE_LEFT); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anchor_top", PROPERTY_HINT_RANGE, "0,1,0.001,or_lesser,or_greater"), "_set_anchor", "get_anchor", SIDE_TOP); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anchor_right", PROPERTY_HINT_RANGE, "0,1,0.001,or_lesser,or_greater"), "_set_anchor", "get_anchor", SIDE_RIGHT); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anchor_bottom", PROPERTY_HINT_RANGE, "0,1,0.001,or_lesser,or_greater"), "_set_anchor", "get_anchor", SIDE_BOTTOM); - ADD_GROUP("Offset", "offset_"); + ADD_SUBGROUP_INDENT("Anchor Offsets", "offset_", 1); ADD_PROPERTYI(PropertyInfo(Variant::INT, "offset_left", PROPERTY_HINT_RANGE, "-4096,4096"), "set_offset", "get_offset", SIDE_LEFT); ADD_PROPERTYI(PropertyInfo(Variant::INT, "offset_top", PROPERTY_HINT_RANGE, "-4096,4096"), "set_offset", "get_offset", SIDE_TOP); ADD_PROPERTYI(PropertyInfo(Variant::INT, "offset_right", PROPERTY_HINT_RANGE, "-4096,4096"), "set_offset", "get_offset", SIDE_RIGHT); ADD_PROPERTYI(PropertyInfo(Variant::INT, "offset_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), "set_offset", "get_offset", SIDE_BOTTOM); - ADD_GROUP("Grow Direction", "grow_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_h_grow_direction", "get_h_grow_direction"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_v_grow_direction", "get_v_grow_direction"); - - ADD_GROUP("Layout Direction", "layout_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction"); - - ADD_GROUP("Auto Translate", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating"); + ADD_SUBGROUP_INDENT("Grow Direction", "grow_", 1); + ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Left,Right,Both"), "set_h_grow_direction", "get_h_grow_direction"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Top,Bottom,Both"), "set_v_grow_direction", "get_v_grow_direction"); - ADD_GROUP("Rect", "rect_"); + ADD_SUBGROUP("Rectangle", "rect_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_size", "get_size"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); + + ADD_SUBGROUP("Transform", "rect_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rect_rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); + + ADD_SUBGROUP("Container Sizing", "size_flags_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_h_size_flags", "get_h_size_flags"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_v_size_flags", "get_v_size_flags"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio"); + + ADD_GROUP("Auto Translate", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating"); ADD_GROUP("Hint", "hint_"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "_get_tooltip"); @@ -3044,11 +3404,6 @@ void Control::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,I-Beam,Pointing Hand,Cross,Wait,Busy,Drag,Can Drop,Forbidden,Vertical Resize,Horizontal Resize,Secondary Diagonal Resize,Main Diagonal Resize,Move,Vertical Split,Horizontal Split,Help"), "set_default_cursor_shape", "get_default_cursor_shape"); - ADD_GROUP("Size Flags", "size_flags_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_v_size_flags", "get_v_size_flags"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio"); - ADD_GROUP("Theme", "theme_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_type_variation", PROPERTY_HINT_ENUM_SUGGESTION), "set_theme_type_variation", "get_theme_type_variation"); @@ -3107,6 +3462,7 @@ void Control::_bind_methods() { BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_HEIGHT); BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_SIZE); + BIND_ENUM_CONSTANT(SIZE_SHRINK_BEGIN); BIND_ENUM_CONSTANT(SIZE_FILL); BIND_ENUM_CONSTANT(SIZE_EXPAND); BIND_ENUM_CONSTANT(SIZE_EXPAND_FILL); diff --git a/scene/gui/control.h b/scene/gui/control.h index 962135280f..becb50a118 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -31,12 +31,10 @@ #ifndef CONTROL_H #define CONTROL_H -#include "core/input/shortcut.h" #include "core/math/transform_2d.h" #include "core/object/gdvirtual.gen.inc" #include "core/templates/rid.h" #include "scene/main/canvas_item.h" -#include "scene/main/node.h" #include "scene/main/timer.h" #include "scene/resources/theme.h" @@ -67,12 +65,13 @@ public: }; enum SizeFlags { + SIZE_SHRINK_BEGIN = 0, SIZE_FILL = 1, SIZE_EXPAND = 2, - SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL, - SIZE_SHRINK_CENTER = 4, //ignored by expand or fill - SIZE_SHRINK_END = 8, //ignored by expand or fill + SIZE_SHRINK_CENTER = 4, + SIZE_SHRINK_END = 8, + SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL, }; enum MouseFilter { @@ -128,6 +127,13 @@ public: PRESET_MODE_KEEP_SIZE }; + enum LayoutMode { + LAYOUT_MODE_POSITION, + LAYOUT_MODE_ANCHORS, + LAYOUT_MODE_CONTAINER, + LAYOUT_MODE_UNCONTROLLED, + }; + enum LayoutDirection { LAYOUT_DIRECTION_INHERITED, LAYOUT_DIRECTION_LOCALE, @@ -230,7 +236,7 @@ private: } data; - static constexpr unsigned properties_managed_by_container_count = 11; + static constexpr unsigned properties_managed_by_container_count = 12; static String properties_managed_by_container[properties_managed_by_container_count]; void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest); @@ -241,6 +247,12 @@ private: void _set_global_position(const Point2 &p_point); void _set_size(const Size2 &p_size); + void _set_layout_mode(LayoutMode p_mode); + LayoutMode _get_layout_mode() const; + + void _set_anchors_layout_preset(int p_preset); + int _get_anchors_layout_preset() const; + void _theme_changed(); void _notify_theme_changed(); @@ -285,9 +297,10 @@ protected: bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; + virtual void _validate_property(PropertyInfo &property) const override; + void _notification(int p_notification); static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const override; //bind helpers @@ -378,6 +391,7 @@ public: void set_anchors_preset(LayoutPreset p_preset, bool p_keep_offsets = true); void set_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0); void set_anchors_and_offsets_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0); + void set_grow_direction_preset(LayoutPreset p_preset); void set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset = true, bool p_push_opposite_anchor = true); real_t get_anchor(Side p_side) const; @@ -563,6 +577,7 @@ VARIANT_ENUM_CAST(Control::LayoutPresetMode); VARIANT_ENUM_CAST(Control::MouseFilter); VARIANT_ENUM_CAST(Control::GrowDirection); VARIANT_ENUM_CAST(Control::Anchor); +VARIANT_ENUM_CAST(Control::LayoutMode); VARIANT_ENUM_CAST(Control::LayoutDirection); VARIANT_ENUM_CAST(Control::TextDirection); VARIANT_ENUM_CAST(Control::StructuredTextParser); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 1cbe3adb3c..9297aeea08 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -33,12 +33,7 @@ #include "core/os/keyboard.h" #include "core/string/print_string.h" #include "core/string/translation.h" -#include "line_edit.h" - -#ifdef TOOLS_ENABLED -#include "editor/editor_node.h" -#include "scene/main/window.h" // Only used to check for more modals when dimming the editor. -#endif +#include "scene/gui/line_edit.h" // AcceptDialog diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp index d1ac60b325..e806a4a8a6 100644 --- a/scene/gui/flow_container.cpp +++ b/scene/gui/flow_container.cpp @@ -28,8 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene/gui/container.h" - #include "flow_container.h" struct _LineData { @@ -223,6 +221,30 @@ Size2 FlowContainer::get_minimum_size() const { return minimum; } +Vector<int> FlowContainer::get_allowed_size_flags_horizontal() const { + Vector<int> flags; + flags.append(SIZE_FILL); + if (!vertical) { + flags.append(SIZE_EXPAND); + } + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + +Vector<int> FlowContainer::get_allowed_size_flags_vertical() const { + Vector<int> flags; + flags.append(SIZE_FILL); + if (vertical) { + flags.append(SIZE_EXPAND); + } + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + void FlowContainer::_notification(int p_what) { switch (p_what) { case NOTIFICATION_SORT_CHILDREN: { diff --git a/scene/gui/flow_container.h b/scene/gui/flow_container.h index e3ed423ae1..a2da43e071 100644 --- a/scene/gui/flow_container.h +++ b/scene/gui/flow_container.h @@ -31,7 +31,7 @@ #ifndef FLOW_CONTAINER_H #define FLOW_CONTAINER_H -class Container; +#include "scene/gui/container.h" class FlowContainer : public Container { GDCLASS(FlowContainer, Container); @@ -54,6 +54,9 @@ public: virtual Size2 get_minimum_size() const override; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + FlowContainer(bool p_vertical = false); }; diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index da973b46f0..b0d1944d6e 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -36,9 +36,7 @@ #include "scene/gui/graph_node.h" #include "scene/gui/label.h" #include "scene/gui/scroll_bar.h" -#include "scene/gui/slider.h" #include "scene/gui/spin_box.h" -#include "scene/gui/texture_rect.h" class GraphEdit; class ViewPanner; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 30f6cf4a14..e0c59dd1bf 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -959,6 +959,25 @@ bool GraphNode::is_resizable() const { return resizable; } +Vector<int> GraphNode::get_allowed_size_flags_horizontal() const { + Vector<int> flags; + flags.append(SIZE_FILL); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + +Vector<int> GraphNode::get_allowed_size_flags_vertical() const { + Vector<int> flags; + flags.append(SIZE_FILL); + flags.append(SIZE_EXPAND); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + void GraphNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_title", "title"), &GraphNode::set_title); ClassDB::bind_method(D_METHOD("get_title"), &GraphNode::get_title); diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index b41fc7f5d4..7eb5f27cff 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -182,6 +182,9 @@ public: virtual Size2 get_minimum_size() const override; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + bool is_resizing() const { return resizing; } GraphNode(); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 852aaaab24..7a24c76ff8 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -924,20 +924,24 @@ void Label::_bind_methods() { BIND_ENUM_CONSTANT(VC_GLYPHS_RTL); ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); - ADD_GROUP("Locale", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_vertical_alignment", "get_vertical_alignment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE, "-1,999,1"), "set_max_lines_visible", "get_max_lines_visible"); + + // Note: "visible_characters" and "percent_visible" should be set after "text" to be correctly applied. ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE, "-1,999,1"), "set_max_lines_visible", "get_max_lines_visible"); + + ADD_GROUP("Locale", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); + ADD_GROUP("Structured Text", "structured_text_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options"); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 3aae3377bc..0e2cbfea48 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -1606,7 +1606,7 @@ Size2 LineEdit::get_minimum_size() const { Size2 min_size; // Minimum size of text. - int em_space_size = font->get_char_size('M', 0, font_size).x; + float em_space_size = font->get_char_size('M', 0, font_size).x; min_size.width = get_theme_constant(SNAME("minimum_character_width")) * em_space_size; if (expand_to_text_length) { diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h index 7d302e967d..a455e866b1 100644 --- a/scene/gui/link_button.h +++ b/scene/gui/link_button.h @@ -32,7 +32,6 @@ #define LINKBUTTON_H #include "scene/gui/base_button.h" -#include "scene/resources/bit_map.h" #include "scene/resources/text_line.h" class LinkButton : public BaseButton { diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index 7b696ddb84..89008a19c5 100644 --- a/scene/gui/margin_container.cpp +++ b/scene/gui/margin_container.cpp @@ -65,6 +65,24 @@ Size2 MarginContainer::get_minimum_size() const { return max; } +Vector<int> MarginContainer::get_allowed_size_flags_horizontal() const { + Vector<int> flags; + flags.append(SIZE_FILL); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + +Vector<int> MarginContainer::get_allowed_size_flags_vertical() const { + Vector<int> flags; + flags.append(SIZE_FILL); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + void MarginContainer::_notification(int p_what) { switch (p_what) { case NOTIFICATION_SORT_CHILDREN: { diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h index 3a2f0fa8b3..f8a3c5bb11 100644 --- a/scene/gui/margin_container.h +++ b/scene/gui/margin_container.h @@ -42,6 +42,9 @@ protected: public: virtual Size2 get_minimum_size() const override; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + MarginContainer(); }; diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp index 463ad3c513..91a343084b 100644 --- a/scene/gui/panel_container.cpp +++ b/scene/gui/panel_container.cpp @@ -60,6 +60,24 @@ Size2 PanelContainer::get_minimum_size() const { return ms; } +Vector<int> PanelContainer::get_allowed_size_flags_horizontal() const { + Vector<int> flags; + flags.append(SIZE_FILL); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + +Vector<int> PanelContainer::get_allowed_size_flags_vertical() const { + Vector<int> flags; + flags.append(SIZE_FILL); + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + void PanelContainer::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { RID ci = get_canvas_item(); diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h index a5ff74cebb..8f07ce38eb 100644 --- a/scene/gui/panel_container.h +++ b/scene/gui/panel_container.h @@ -42,6 +42,9 @@ protected: public: virtual Size2 get_minimum_size() const override; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + PanelContainer(); }; diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 61a5fb999c..5c86e1850e 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -30,6 +30,7 @@ #include "popup_menu.h" +#include "core/config/project_settings.h" #include "core/input/input.h" #include "core/os/keyboard.h" #include "core/os/os.h" diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 86e5afcb7c..e442801e0a 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -33,6 +33,7 @@ #include "core/math/math_defs.h" #include "core/os/keyboard.h" #include "core/os/os.h" +#include "label.h" #include "scene/scene_string_names.h" #include "servers/display_server.h" @@ -513,7 +514,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> } break; case ITEM_IMAGE: { ItemImage *img = (ItemImage *)it; - l.text_buf->add_object((uint64_t)it, img->image->get_size(), img->inline_align, 1); + l.text_buf->add_object((uint64_t)it, img->size, img->inline_align, 1); text += String::chr(0xfffc); l.char_count++; remaining_characters--; @@ -1590,6 +1591,9 @@ void RichTextLabel::_notification(int p_what) { update(); } } break; + case NOTIFICATION_DRAG_END: { + selection.drag_attempt = false; + } break; } } @@ -1650,6 +1654,8 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) { int c_index = 0; bool outside; + selection.drag_attempt = false; + _find_click(main, b->get_position(), &c_frame, &c_line, &c_item, &c_index, &outside); if (c_item != nullptr) { if (selection.enabled) { @@ -1660,17 +1666,22 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) { // Erase previous selection. if (selection.active) { - selection.from_frame = nullptr; - selection.from_line = 0; - selection.from_item = nullptr; - selection.from_char = 0; - selection.to_frame = nullptr; - selection.to_line = 0; - selection.to_item = nullptr; - selection.to_char = 0; - selection.active = false; - - update(); + if (_is_click_inside_selection()) { + selection.drag_attempt = true; + selection.click_item = nullptr; + } else { + selection.from_frame = nullptr; + selection.from_line = 0; + selection.from_item = nullptr; + selection.from_char = 0; + selection.to_frame = nullptr; + selection.to_line = 0; + selection.to_item = nullptr; + selection.to_char = 0; + selection.active = false; + + update(); + } } } } @@ -1683,6 +1694,8 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) { int c_index = 0; bool outside; + selection.drag_attempt = false; + _find_click(main, b->get_position(), &c_frame, &c_line, &c_item, &c_index, &outside); if (c_frame) { @@ -1714,6 +1727,22 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) { DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text()); } selection.click_item = nullptr; + if (selection.drag_attempt) { + selection.drag_attempt = false; + if (_is_click_inside_selection()) { + selection.from_frame = nullptr; + selection.from_line = 0; + selection.from_item = nullptr; + selection.from_char = 0; + selection.to_frame = nullptr; + selection.to_line = 0; + selection.to_item = nullptr; + selection.to_char = 0; + selection.active = false; + + update(); + } + } if (!b->is_double_click() && !scroll_updated) { Item *c_item = nullptr; @@ -3734,6 +3763,29 @@ void RichTextLabel::set_deselect_on_focus_loss_enabled(const bool p_enabled) { } } +Variant RichTextLabel::get_drag_data(const Point2 &p_point) { + if (selection.drag_attempt && selection.enabled) { + String t = get_selected_text(); + Label *l = memnew(Label); + l->set_text(t); + set_drag_preview(l); + return t; + } + + return Variant(); +} + +bool RichTextLabel::_is_click_inside_selection() const { + if (selection.active && selection.enabled && selection.click_frame && selection.from_frame && selection.to_frame) { + const Line &l_click = selection.click_frame->lines[selection.click_line]; + const Line &l_from = selection.from_frame->lines[selection.from_line]; + const Line &l_to = selection.to_frame->lines[selection.to_line]; + return (l_click.char_offset + selection.click_char >= l_from.char_offset + selection.from_char) && (l_click.char_offset + selection.click_char <= l_to.char_offset + selection.to_char); + } else { + return false; + } +} + bool RichTextLabel::_search_table(ItemTable *p_table, List<Item *>::Element *p_from, const String &p_string, bool p_reverse_search) { List<Item *>::Element *E = p_from; while (E != nullptr) { @@ -3992,7 +4044,7 @@ int RichTextLabel::get_selection_to() const { void RichTextLabel::set_text(const String &p_bbcode) { text = p_bbcode; - if (is_inside_tree() && use_bbcode) { + if (use_bbcode) { parse_bbcode(p_bbcode); } else { // raw text clear(); @@ -4275,6 +4327,8 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_percent_visible", "percent_visible"), &RichTextLabel::set_percent_visible); ClassDB::bind_method(D_METHOD("get_percent_visible"), &RichTextLabel::get_percent_visible); + ClassDB::bind_method(D_METHOD("get_character_line", "character"), &RichTextLabel::get_character_line); + ClassDB::bind_method(D_METHOD("get_character_paragraph", "character"), &RichTextLabel::get_character_paragraph); ClassDB::bind_method(D_METHOD("get_total_character_count"), &RichTextLabel::get_total_character_count); ClassDB::bind_method(D_METHOD("set_use_bbcode", "enable"), &RichTextLabel::set_use_bbcode); @@ -4295,33 +4349,30 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_effects"), &RichTextLabel::get_effects); ClassDB::bind_method(D_METHOD("install_effect", "effect"), &RichTextLabel::install_effect); - ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior"); + // Note: set "bbcode_enabled" first, to avoid unnecessery "text" resets. + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_underlined"), "set_meta_underline", "is_meta_underlined"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_size", PROPERTY_HINT_RANGE, "0,24,1"), "set_tab_size", "get_tab_size"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fit_content_height"), "set_fit_content_height", "is_fit_content_height_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_active"), "set_scroll_active", "is_scroll_active"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_following"), "set_scroll_follow", "is_scroll_following"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selection_enabled"), "set_selection_enabled", "is_selection_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "RichTextEffect"), (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE)), "set_effects", "get_effects"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_underlined"), "set_meta_underline", "is_meta_underlined"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); + + // Note: "visible_characters" and "percent_visible" should be set after "text" to be correctly applied. + ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); + ADD_GROUP("Locale", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); - ADD_GROUP("Structured Text", "structured_text_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options"); @@ -4410,6 +4461,36 @@ int RichTextLabel::get_visible_characters() const { return visible_characters; } +int RichTextLabel::get_character_line(int p_char) { + int line_count = 0; + for (int i = 0; i < main->lines.size(); i++) { + if (main->lines[i].char_offset < p_char && p_char <= main->lines[i].char_offset + main->lines[i].char_count) { + for (int j = 0; j < main->lines[i].text_buf->get_line_count(); j++) { + Vector2i range = main->lines[i].text_buf->get_line_range(j); + if (main->lines[i].char_offset + range.x < p_char && p_char <= main->lines[i].char_offset + range.y) { + return line_count; + } + line_count++; + } + } else { + line_count += main->lines[i].text_buf->get_line_count(); + } + } + return -1; +} + +int RichTextLabel::get_character_paragraph(int p_char) { + int para_count = 0; + for (int i = 0; i < main->lines.size(); i++) { + if (main->lines[i].char_offset < p_char && p_char <= main->lines[i].char_offset + main->lines[i].char_count) { + return para_count; + } else { + para_count++; + } + } + return -1; +} + int RichTextLabel::get_total_character_count() const { // Note: Do not use line buffer "char_count", it includes only visible characters. int tc = 0; diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index ea3a08d7bd..ddc8cc75b8 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -407,6 +407,7 @@ private: bool active = false; // anything selected? i.e. from, to, etc. valid? bool enabled = false; // allow selections? + bool drag_attempt = false; }; Selection selection; @@ -416,6 +417,7 @@ private: float percent_visible = 1.0; VisibleCharactersBehavior visible_chars_behavior = VC_CHARS_BEFORE_SHAPING; + bool _is_click_inside_selection() const; void _find_click(ItemFrame *p_frame, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr, bool *r_outside = nullptr); String _get_line_text(ItemFrame *p_frame, int p_line, Selection p_sel) const; @@ -559,6 +561,7 @@ public: VScrollBar *get_v_scroll_bar() { return vscroll; } virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override; + virtual Variant get_drag_data(const Point2 &p_point) override; void set_selection_enabled(bool p_enabled); bool is_selection_enabled() const; @@ -595,6 +598,8 @@ public: void set_visible_characters(int p_visible); int get_visible_characters() const; + int get_character_line(int p_char); + int get_character_paragraph(int p_char); int get_total_character_count() const; int get_total_glyph_count() const; diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 5e128d594c..7e69fa09e7 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "scroll_container.h" + +#include "core/config/project_settings.h" #include "core/os/os.h" #include "scene/main/window.h" diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 874e5868b6..b56326088d 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -336,6 +336,30 @@ bool SplitContainer::is_collapsed() const { return collapsed; } +Vector<int> SplitContainer::get_allowed_size_flags_horizontal() const { + Vector<int> flags; + flags.append(SIZE_FILL); + if (!vertical) { + flags.append(SIZE_EXPAND); + } + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + +Vector<int> SplitContainer::get_allowed_size_flags_vertical() const { + Vector<int> flags; + flags.append(SIZE_FILL); + if (vertical) { + flags.append(SIZE_EXPAND); + } + flags.append(SIZE_SHRINK_BEGIN); + flags.append(SIZE_SHRINK_CENTER); + flags.append(SIZE_SHRINK_END); + return flags; +} + void SplitContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_split_offset", "offset"), &SplitContainer::set_split_offset); ClassDB::bind_method(D_METHOD("get_split_offset"), &SplitContainer::get_split_offset); diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index ba6fff6f55..a69ffe4de9 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -79,6 +79,9 @@ public: virtual Size2 get_minimum_size() const override; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + SplitContainer(bool p_vertical = false); }; diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp index 760144591e..b8baefc307 100644 --- a/scene/gui/subviewport_container.cpp +++ b/scene/gui/subviewport_container.cpp @@ -91,6 +91,14 @@ int SubViewportContainer::get_stretch_shrink() const { return shrink; } +Vector<int> SubViewportContainer::get_allowed_size_flags_horizontal() const { + return Vector<int>(); +} + +Vector<int> SubViewportContainer::get_allowed_size_flags_vertical() const { + return Vector<int>(); +} + void SubViewportContainer::_notification(int p_what) { if (p_what == NOTIFICATION_RESIZED) { if (!stretch) { diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h index e7520763fb..3138a6144c 100644 --- a/scene/gui/subviewport_container.h +++ b/scene/gui/subviewport_container.h @@ -54,6 +54,9 @@ public: virtual Size2 get_minimum_size() const override; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + SubViewportContainer(); }; diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index b1baacd887..607031bee6 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -524,13 +524,14 @@ void TabBar::set_tab_count(int p_count) { offset = MIN(offset, p_count - 1); max_drawn_tab = MIN(max_drawn_tab, p_count - 1); current = MIN(current, p_count - 1); - } - _update_cache(); - _ensure_no_over_offset(); - if (scroll_to_selected) { - ensure_tab_visible(current); + _update_cache(); + _ensure_no_over_offset(); + if (scroll_to_selected) { + ensure_tab_visible(current); + } } + update(); update_minimum_size(); notify_property_list_changed(); @@ -961,7 +962,6 @@ void TabBar::clear_tabs() { current = 0; previous = 0; - _update_cache(); update(); update_minimum_size(); notify_property_list_changed(); @@ -975,18 +975,21 @@ void TabBar::remove_tab(int p_idx) { } if (current < 0) { + offset = 0; + max_drawn_tab = 0; current = 0; previous = 0; - } - if (current >= tabs.size()) { - current = tabs.size() - 1; - } + } else { + offset = MIN(offset, tabs.size() - 1); + max_drawn_tab = MIN(max_drawn_tab, tabs.size() - 1); - _update_cache(); - _ensure_no_over_offset(); - if (scroll_to_selected && !tabs.is_empty()) { - ensure_tab_visible(current); + _update_cache(); + _ensure_no_over_offset(); + if (scroll_to_selected && !tabs.is_empty()) { + ensure_tab_visible(current); + } } + update(); update_minimum_size(); notify_property_list_changed(); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 818431a6a0..4bd3686e7c 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -1177,6 +1177,14 @@ bool TabContainer::get_use_hidden_tabs_for_min_size() const { return use_hidden_tabs_for_min_size; } +Vector<int> TabContainer::get_allowed_size_flags_horizontal() const { + return Vector<int>(); +} + +Vector<int> TabContainer::get_allowed_size_flags_vertical() const { + return Vector<int>(); +} + void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tab_count"), &TabContainer::get_tab_count); ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &TabContainer::set_current_tab); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 01e71e9fa8..ee1b3fea51 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -133,6 +133,9 @@ public: void set_use_hidden_tabs_for_min_size(bool p_use_hidden_tabs); bool get_use_hidden_tabs_for_min_size() const; + virtual Vector<int> get_allowed_size_flags_horizontal() const override; + virtual Vector<int> get_allowed_size_flags_vertical() const override; + TabContainer(); }; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 5295acce8f..d40f715ae7 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -961,7 +961,7 @@ void TextEdit::_notification(int p_what) { // Give visual indication of empty selected line. if (selection.active && line >= selection.from_line && line <= selection.to_line && char_margin >= xmargin_beg) { - int char_w = font->get_char_size(' ', 0, font_size).width; + float char_w = font->get_char_size(' ', 0, font_size).width; if (rtl) { RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_beg - ofs_x - char_w, ofs_y, char_w, row_height), selection_color); } else { diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index a368a10ad0..2a9e7bac3d 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -32,10 +32,8 @@ #define CANVAS_ITEM_H #include "scene/main/node.h" -#include "scene/main/scene_tree.h" #include "scene/resources/canvas_item_material.h" #include "scene/resources/font.h" -#include "servers/text_server.h" class CanvasLayer; class MultiMesh; diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 3f3e72357b..2f7b18a80e 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -29,8 +29,10 @@ /*************************************************************************/ #include "canvas_layer.h" -#include "canvas_item.h" -#include "viewport.h" + +#include "scene/main/canvas_item.h" +#include "scene/main/viewport.h" +#include "scene/resources/world_2d.h" void CanvasLayer::set_layer(int p_xform) { layer = p_xform; @@ -65,6 +67,14 @@ void CanvasLayer::set_visible(bool p_visible) { } } +void CanvasLayer::show() { + set_visible(true); +} + +void CanvasLayer::hide() { + set_visible(false); +} + bool CanvasLayer::is_visible() const { return visible; } @@ -293,6 +303,8 @@ void CanvasLayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_visible", "visible"), &CanvasLayer::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &CanvasLayer::is_visible); + ClassDB::bind_method(D_METHOD("show"), &CanvasLayer::show); + ClassDB::bind_method(D_METHOD("hide"), &CanvasLayer::hide); ClassDB::bind_method(D_METHOD("set_transform", "transform"), &CanvasLayer::set_transform); ClassDB::bind_method(D_METHOD("get_transform"), &CanvasLayer::get_transform); diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h index b7bd793440..2493675b31 100644 --- a/scene/main/canvas_layer.h +++ b/scene/main/canvas_layer.h @@ -72,6 +72,8 @@ public: void set_visible(bool p_visible); bool is_visible() const; + void show(); + void hide(); void set_transform(const Transform2D &p_xform); Transform2D get_transform() const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index d5bc7d111a..05086541a5 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -30,6 +30,7 @@ #include "node.h" +#include "core/config/project_settings.h" #include "core/core_string_names.h" #include "core/io/resource_loader.h" #include "core/multiplayer/multiplayer_api.h" diff --git a/scene/main/node.h b/scene/main/node.h index 0ac10f4381..f2dcdf4b43 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -31,9 +31,6 @@ #ifndef NODE_H #define NODE_H -#include "core/config/project_settings.h" -#include "core/object/class_db.h" -#include "core/object/script_language.h" #include "core/string/node_path.h" #include "core/templates/map.h" #include "core/variant/typed_array.h" diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 69d781cbfc..f02032a6c9 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -44,10 +44,13 @@ #include "node.h" #include "scene/animation/tween.h" #include "scene/debugger/scene_debugger.h" +#include "scene/main/viewport.h" #include "scene/resources/font.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/packed_scene.h" +#include "scene/resources/world_2d.h" +#include "scene/resources/world_3d.h" #include "scene/scene_string_names.h" #include "servers/display_server.h" #include "servers/navigation_server_3d.h" diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index a5cd52b4ca..5f7c1729e8 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -35,8 +35,6 @@ #include "core/os/thread_safe.h" #include "core/templates/self_list.h" #include "scene/resources/mesh.h" -#include "scene/resources/world_2d.h" -#include "scene/resources/world_3d.h" #undef Window @@ -48,6 +46,7 @@ class Mesh; class MultiplayerAPI; class SceneDebugger; class Tween; +class Viewport; class SceneTreeTimer : public RefCounted { GDCLASS(SceneTreeTimer, RefCounted); diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp index 240e662efb..09dfc50066 100644 --- a/scene/main/shader_globals_override.cpp +++ b/scene/main/shader_globals_override.cpp @@ -221,6 +221,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const } void ShaderGlobalsOverride::_activate() { + ERR_FAIL_NULL(get_tree()); List<Node *> nodes; get_tree()->get_nodes_in_group(SceneStringNames::get_singleton()->shader_overrides_group_active, &nodes); if (nodes.size() == 0) { diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 522997cdf5..0a46614fd3 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -30,6 +30,7 @@ #include "viewport.h" +#include "core/config/project_settings.h" #include "core/core_string_names.h" #include "core/debugger/engine_debugger.h" #include "core/object/message_queue.h" @@ -1713,7 +1714,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.tooltip_popup) { if (gui.tooltip_control) { String tooltip = _gui_get_tooltip(over, gui.tooltip_control->get_global_transform().xform_inv(mpos)); - + tooltip = tooltip.strip_edges(); if (tooltip.length() == 0) { _gui_cancel_tooltip(); } else if (gui.tooltip_label) { diff --git a/scene/main/window.cpp b/scene/main/window.cpp index f2ebe50fa3..77c0fa2a48 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -30,6 +30,7 @@ #include "window.h" +#include "core/config/project_settings.h" #include "core/debugger/engine_debugger.h" #include "core/string/translation.h" #include "scene/gui/control.h" @@ -254,6 +255,7 @@ void Window::_make_window() { #endif DisplayServer::get_singleton()->window_set_title(tr_title, window_id); DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id); + DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive); _update_window_size(); @@ -522,6 +524,10 @@ void Window::set_exclusive(bool p_exclusive) { exclusive = p_exclusive; + if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive); + } + if (transient_parent) { if (p_exclusive && is_inside_tree() && is_visible()) { ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child."); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 87e9bd023b..152a1616f8 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -1075,11 +1075,22 @@ void initialize_theme() { // Allow creating the default theme at a different scale to suit higher/lower base resolutions. float default_theme_scale = GLOBAL_DEF("gui/theme/default_theme_scale", 1.0); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_theme_scale", PropertyInfo(Variant::FLOAT, "gui/theme/default_theme_scale", PROPERTY_HINT_RANGE, "0.5,8,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + String theme_path = GLOBAL_DEF_RST("gui/theme/custom", ""); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", ""); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + bool font_antialiased = (bool)GLOBAL_DEF_RST("gui/theme/default_font_antialiased", true); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiased", PropertyInfo(Variant::BOOL, "gui/theme/default_font_antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + + TextServer::Hinting font_hinting = (TextServer::Hinting)(int)GLOBAL_DEF_RST("gui/theme/default_font_hinting", TextServer::HINTING_LIGHT); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_hinting", PropertyInfo(Variant::INT, "gui/theme/default_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + + TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)GLOBAL_DEF_RST("gui/theme/default_font_subpixel_positioning", TextServer::SUBPIXEL_POSITIONING_AUTO); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_subpixel_positioning", PropertyInfo(Variant::INT, "gui/theme/default_font_subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + Ref<Font> font; if (!font_path.is_empty()) { font = ResourceLoader::load(font_path); @@ -1090,7 +1101,7 @@ void initialize_theme() { // Always make the default theme to avoid invalid default font/icon/style in the given theme. if (RenderingServer::get_singleton()) { - make_default_theme(default_theme_scale, font); + make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased); } if (!theme_path.is_empty()) { diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index b6151bccf4..bc533ff022 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2320,22 +2320,12 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) { //mix of real and int + real_t a = p_a; + real_t b = p_b; + real_t pa = p_pre_a; + real_t pb = p_post_b; - real_t p0 = p_pre_a; - real_t p1 = p_a; - real_t p2 = p_b; - real_t p3 = p_post_b; - - real_t t = p_c; - real_t t2 = t * t; - real_t t3 = t2 * t; - - return 0.5f * - ((p1 * 2.0f) + - (-p0 + p2) * t + - (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 + - (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3); - + return Math::cubic_interpolate(a, b, pa, pb, p_c); } else if ((vformat & (vformat - 1))) { return p_a; //can't interpolate, mix of types } diff --git a/scene/resources/default_theme/color_picker_sample.svg b/scene/resources/default_theme/color_picker_sample.svg deleted file mode 100644 index 140ac20a99..0000000000 --- a/scene/resources/default_theme/color_picker_sample.svg +++ /dev/null @@ -1 +0,0 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 256 20" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m0 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m5 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m80 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m85 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m159.978 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m164.978 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m39.991 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m44.991 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m119.99 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m124.99 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m199.968 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m204.968 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m9.98 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m14.98 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m89.98 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m94.98 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m169.957 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m174.957 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m49.97 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m54.97 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m129.97 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m134.97 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m209.948 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m214.948 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m19.995 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m24.995 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m99.995 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m104.995 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m179.973 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m184.973 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m59.986 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m64.986 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m139.986 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m144.986 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m219.964 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m224.964 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m30.011 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m35.011 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m110.011 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m115.011 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m189.989 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m194.989 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m70.001 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m75.001 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m150.001 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m155.001 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m229.979 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m234.979 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m240.017 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m245.017 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m249.996 0v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m254.996 0v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m249.996 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m254.996 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m240.017 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m245.017 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m0 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m5 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m80 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m85 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m159.978 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m164.978 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m39.991 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m44.991 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m119.99 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m124.99 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m199.968 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m204.968 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m9.98 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m14.98 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m89.98 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m94.98 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m169.957 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m174.957 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m49.97 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m54.97 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m129.97 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m134.97 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m209.948 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m214.948 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m19.995 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m24.995 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m99.995 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m104.995 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m179.973 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m184.973 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m59.986 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m64.986 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m139.986 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m144.986 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m219.964 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m224.964 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m30.011 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m35.011 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m110.011 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m115.011 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m189.989 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m194.989 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m70.001 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m75.001 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m150.001 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m155.001 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/><path d="m229.979 10v5h5v-5zm5 5v5h5v-5z" fill="#e0e0e0"/><path d="m234.979 10v5h5v-5zm0 5h-5v5h5z" fill="#fff"/></g></svg> diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index c92a46a98c..61114333fb 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -466,7 +466,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te theme->set_color("completion_background_color", "CodeEdit", Color(0.17, 0.16, 0.2)); theme->set_color("completion_selected_color", "CodeEdit", Color(0.26, 0.26, 0.27)); theme->set_color("completion_existing_color", "CodeEdit", Color(0.87, 0.87, 0.87, 0.13)); - theme->set_color("completion_scroll_color", "CodeEdit", control_font_pressed_color); + theme->set_color("completion_scroll_color", "CodeEdit", control_font_pressed_color * Color(1, 1, 1, 0.29)); theme->set_color("completion_font_color", "CodeEdit", Color(0.67, 0.67, 0.67)); theme->set_color("font_color", "CodeEdit", control_font_color); theme->set_color("font_selected_color", "CodeEdit", Color(0, 0, 0)); @@ -490,7 +490,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te theme->set_constant("completion_lines", "CodeEdit", 7); theme->set_constant("completion_max_width", "CodeEdit", 50); - theme->set_constant("completion_scroll_width", "CodeEdit", 3); + theme->set_constant("completion_scroll_width", "CodeEdit", 6); theme->set_constant("line_spacing", "CodeEdit", 4 * scale); theme->set_constant("outline_size", "CodeEdit", 0); @@ -864,7 +864,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te theme->set_icon("screen_picker", "ColorPicker", icons["color_picker_pipette"]); theme->set_icon("add_preset", "ColorPicker", icons["add"]); theme->set_icon("color_hue", "ColorPicker", icons["color_picker_hue"]); - theme->set_icon("color_sample", "ColorPicker", icons["color_picker_sample"]); theme->set_icon("sample_bg", "ColorPicker", icons["mini_checkerboard"]); theme->set_icon("overbright_indicator", "ColorPicker", icons["color_picker_overbright"]); theme->set_icon("bar_arrow", "ColorPicker", icons["color_picker_bar_arrow"]); @@ -1019,7 +1018,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2); } -void make_default_theme(float p_scale, Ref<Font> p_font) { +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa) { Ref<Theme> t; t.instantiate(); @@ -1041,6 +1040,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font) { Ref<FontData> dynamic_font_data; dynamic_font_data.instantiate(); dynamic_font_data->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size); + dynamic_font_data->set_subpixel_positioning(p_subpixel); + dynamic_font_data->set_hinting(p_hinting); + dynamic_font_data->set_antialiased(p_aa); dynamic_font->add_data(dynamic_font_data); default_font = dynamic_font; diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index 3016517824..28afd5f5e1 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -36,7 +36,7 @@ const int default_font_size = 16; void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); -void make_default_theme(float p_scale, Ref<Font> p_font); +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa); void clear_default_theme(); #endif diff --git a/scene/resources/default_theme/mini_checkerboard.svg b/scene/resources/default_theme/mini_checkerboard.svg index 0ae6a855bd..03438f75a6 100644 --- a/scene/resources/default_theme/mini_checkerboard.svg +++ b/scene/resources/default_theme/mini_checkerboard.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="1.9994"><path d="m0 0v8h8v-8zm8 8v8h8v-8z" fill="#e0e0e0"/><path d="m8 0v8h8v-8zm0 8h-8v8h8z" fill="#fff"/></g></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width="2"><path d="m0 0v8h8v-8zm8 8v8h8v-8z" fill="#808080"/><path d="m8 0v8h8v-8zm0 8h-8v8h8z" fill="#fff"/></g></svg> diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index bf17a6ea97..82d8ad4444 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -155,7 +155,9 @@ float Environment::get_ambient_light_energy() const { } void Environment::set_ambient_light_sky_contribution(float p_ratio) { - ambient_sky_contribution = p_ratio; + // Sky contribution values outside the [0.0; 1.0] range don't make sense and + // can result in negative colors. + ambient_sky_contribution = CLAMP(p_ratio, 0.0, 1.0); _update_ambient_light(); } diff --git a/scene/resources/environment.h b/scene/resources/environment.h index dd1e664ca6..b71fe8904a 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -34,7 +34,6 @@ #include "core/io/resource.h" #include "scene/resources/sky.h" #include "scene/resources/texture.h" -#include "servers/rendering_server.h" class Environment : public Resource { GDCLASS(Environment, Resource); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index b512acdd8a..5b57e93950 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -60,6 +60,7 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const { TS->font_set_fixed_size(cache[p_cache_index], fixed_size); TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter); TS->font_set_hinting(cache[p_cache_index], hinting); + TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning); TS->font_set_oversampling(cache[p_cache_index], oversampling); } } @@ -101,6 +102,9 @@ void FontData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &FontData::set_hinting); ClassDB::bind_method(D_METHOD("get_hinting"), &FontData::get_hinting); + ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning); + ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning); + ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling); ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling); @@ -204,6 +208,7 @@ void FontData::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field"); ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range"); ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size"); @@ -430,6 +435,7 @@ void FontData::reset_state() { msdf = false; force_autohinter = false; hinting = TextServer::HINTING_LIGHT; + subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED; msdf_pixel_range = 14; msdf_size = 128; fixed_size = 0; @@ -1364,6 +1370,21 @@ TextServer::Hinting FontData::get_hinting() const { return hinting; } +void FontData::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) { + if (subpixel_positioning != p_subpixel) { + subpixel_positioning = p_subpixel; + for (int i = 0; i < cache.size(); i++) { + _ensure_rid(i); + TS->font_set_subpixel_positioning(cache[i], subpixel_positioning); + } + emit_changed(); + } +} + +TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const { + return subpixel_positioning; +} + void FontData::set_oversampling(real_t p_oversampling) { if (oversampling != p_oversampling) { oversampling = p_oversampling; diff --git a/scene/resources/font.h b/scene/resources/font.h index 93351a3493..aaf0a7fe7b 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -55,6 +55,7 @@ class FontData : public Resource { int fixed_size = 0; bool force_autohinter = false; TextServer::Hinting hinting = TextServer::HINTING_LIGHT; + TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; real_t oversampling = 0.f; // Cache. @@ -118,6 +119,9 @@ public: virtual void set_hinting(TextServer::Hinting p_hinting); virtual TextServer::Hinting get_hinting() const; + virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel); + virtual TextServer::SubpixelPositioning get_subpixel_positioning() const; + virtual void set_oversampling(real_t p_oversampling); virtual real_t get_oversampling() const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index f3e5ece1f9..b74f44c52f 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -2215,7 +2215,9 @@ BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const { RID BaseMaterial3D::get_shader_rid() const { MutexLock lock(material_mutex); - ((BaseMaterial3D *)this)->_update_shader(); + if (element.in_list()) { // _is_shader_dirty() would create anoder mutex lock + ((BaseMaterial3D *)this)->_update_shader(); + } ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); return shader_map[current_key].shader; } diff --git a/scene/resources/skeleton_modification_2d_jiggle.cpp b/scene/resources/skeleton_modification_2d_jiggle.cpp index eee6067dae..0921417656 100644 --- a/scene/resources/skeleton_modification_2d_jiggle.cpp +++ b/scene/resources/skeleton_modification_2d_jiggle.cpp @@ -29,7 +29,9 @@ /*************************************************************************/ #include "skeleton_modification_2d_jiggle.h" + #include "scene/2d/skeleton_2d.h" +#include "scene/resources/world_2d.h" bool SkeletonModification2DJiggle::_set(const StringName &p_path, const Variant &p_value) { String path = p_path; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index c5d5ba2912..8e633a4075 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -208,16 +208,16 @@ void ProceduralSkyMaterial::_update_shader() { shader_type sky; -uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0); -uniform vec4 sky_horizon_color : hint_color = vec4(0.55, 0.69, 0.81, 1.0); -uniform float sky_curve : hint_range(0, 1) = 0.09; +uniform vec4 sky_top_color : hint_color = vec4(0.385, 0.454, 0.55, 1.0); +uniform vec4 sky_horizon_color : hint_color = vec4(0.646, 0.656, 0.67, 1.0); +uniform float sky_curve : hint_range(0, 1) = 0.15; uniform float sky_energy = 1.0; -uniform vec4 ground_bottom_color : hint_color = vec4(0.12, 0.12, 0.13, 1.0); -uniform vec4 ground_horizon_color : hint_color = vec4(0.37, 0.33, 0.31, 1.0); +uniform vec4 ground_bottom_color : hint_color = vec4(0.2, 0.169, 0.133, 1.0); +uniform vec4 ground_horizon_color : hint_color = vec4(0.646, 0.656, 0.67, 1.0); uniform float ground_curve : hint_range(0, 1) = 0.02; uniform float ground_energy = 1.0; -uniform float sun_angle_max = 1.74; -uniform float sun_curve : hint_range(0, 1) = 0.05; +uniform float sun_angle_max = 30.0; +uniform float sun_curve : hint_range(0, 1) = 0.15; void sky() { float v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0)); @@ -277,18 +277,18 @@ void sky() { } ProceduralSkyMaterial::ProceduralSkyMaterial() { - set_sky_top_color(Color(0.35, 0.46, 0.71)); - set_sky_horizon_color(Color(0.55, 0.69, 0.81)); - set_sky_curve(0.09); + set_sky_top_color(Color(0.385, 0.454, 0.55)); + set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708)); + set_sky_curve(0.15); set_sky_energy(1.0); - set_ground_bottom_color(Color(0.12, 0.12, 0.13)); - set_ground_horizon_color(Color(0.37, 0.33, 0.31)); + set_ground_bottom_color(Color(0.2, 0.169, 0.133)); + set_ground_horizon_color(Color(0.6463, 0.6558, 0.6708)); set_ground_curve(0.02); set_ground_energy(1.0); - set_sun_angle_max(100.0); - set_sun_curve(0.05); + set_sun_angle_max(30.0); + set_sun_curve(0.15); } ProceduralSkyMaterial::~ProceduralSkyMaterial() { @@ -583,14 +583,14 @@ void PhysicalSkyMaterial::_update_shader() { shader_type sky; uniform float rayleigh : hint_range(0, 64) = 2.0; -uniform vec4 rayleigh_color : hint_color = vec4(0.26, 0.41, 0.58, 1.0); +uniform vec4 rayleigh_color : hint_color = vec4(0.3, 0.405, 0.6, 1.0); uniform float mie : hint_range(0, 1) = 0.005; uniform float mie_eccentricity : hint_range(-1, 1) = 0.8; -uniform vec4 mie_color : hint_color = vec4(0.63, 0.77, 0.92, 1.0); +uniform vec4 mie_color : hint_color = vec4(0.69, 0.729, 0.812, 1.0); uniform float turbidity : hint_range(0, 1000) = 10.0; uniform float sun_disk_scale : hint_range(0, 360) = 1.0; -uniform vec4 ground_color : hint_color = vec4(1.0); +uniform vec4 ground_color : hint_color = vec4(0.1, 0.07, 0.034, 1.0); uniform float exposure : hint_range(0, 128) = 0.1; uniform float dither_strength : hint_range(0, 10) = 1.0; @@ -680,13 +680,13 @@ void sky() { PhysicalSkyMaterial::PhysicalSkyMaterial() { set_rayleigh_coefficient(2.0); - set_rayleigh_color(Color(0.26, 0.41, 0.58)); + set_rayleigh_color(Color(0.3, 0.405, 0.6)); set_mie_coefficient(0.005); set_mie_eccentricity(0.8); - set_mie_color(Color(0.63, 0.77, 0.92)); + set_mie_color(Color(0.69, 0.729, 0.812)); set_turbidity(10.0); set_sun_disk_scale(1.0); - set_ground_color(Color(1.0, 1.0, 1.0)); + set_ground_color(Color(0.1, 0.07, 0.034)); set_exposure(0.1); set_dither_strength(1.0); } diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index f962e55666..373fbb94ea 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "theme.h" + #include "core/string/print_string.h" // Universal Theme resources used when no other theme has the item. @@ -401,6 +402,26 @@ void Theme::add_icon_type(const StringName &p_theme_type) { icon_map[p_theme_type] = HashMap<StringName, Ref<Texture2D>>(); } +void Theme::remove_icon_type(const StringName &p_theme_type) { + if (!icon_map.has(p_theme_type)) { + return; + } + + _freeze_change_propagation(); + + const StringName *L = nullptr; + while ((L = icon_map[p_theme_type].next(L))) { + Ref<Texture2D> icon = icon_map[p_theme_type][*L]; + if (icon.is_valid()) { + icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + } + } + + icon_map.erase(p_theme_type); + + _unfreeze_and_propagate_changes(); +} + void Theme::get_icon_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -488,6 +509,26 @@ void Theme::add_stylebox_type(const StringName &p_theme_type) { style_map[p_theme_type] = HashMap<StringName, Ref<StyleBox>>(); } +void Theme::remove_stylebox_type(const StringName &p_theme_type) { + if (!style_map.has(p_theme_type)) { + return; + } + + _freeze_change_propagation(); + + const StringName *L = nullptr; + while ((L = style_map[p_theme_type].next(L))) { + Ref<StyleBox> style = style_map[p_theme_type][*L]; + if (style.is_valid()) { + style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + } + } + + style_map.erase(p_theme_type); + + _unfreeze_and_propagate_changes(); +} + void Theme::get_stylebox_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -577,6 +618,26 @@ void Theme::add_font_type(const StringName &p_theme_type) { font_map[p_theme_type] = HashMap<StringName, Ref<Font>>(); } +void Theme::remove_font_type(const StringName &p_theme_type) { + if (!font_map.has(p_theme_type)) { + return; + } + + _freeze_change_propagation(); + + const StringName *L = nullptr; + while ((L = font_map[p_theme_type].next(L))) { + Ref<Font> font = font_map[p_theme_type][*L]; + if (font.is_valid()) { + font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); + } + } + + font_map.erase(p_theme_type); + + _unfreeze_and_propagate_changes(); +} + void Theme::get_font_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -653,6 +714,14 @@ void Theme::add_font_size_type(const StringName &p_theme_type) { font_size_map[p_theme_type] = HashMap<StringName, int>(); } +void Theme::remove_font_size_type(const StringName &p_theme_type) { + if (!font_size_map.has(p_theme_type)) { + return; + } + + font_size_map.erase(p_theme_type); +} + void Theme::get_font_size_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -727,6 +796,14 @@ void Theme::add_color_type(const StringName &p_theme_type) { color_map[p_theme_type] = HashMap<StringName, Color>(); } +void Theme::remove_color_type(const StringName &p_theme_type) { + if (!color_map.has(p_theme_type)) { + return; + } + + color_map.erase(p_theme_type); +} + void Theme::get_color_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -801,6 +878,14 @@ void Theme::add_constant_type(const StringName &p_theme_type) { constant_map[p_theme_type] = HashMap<StringName, int>(); } +void Theme::remove_constant_type(const StringName &p_theme_type) { + if (!constant_map.has(p_theme_type)) { + return; + } + + constant_map.erase(p_theme_type); +} + void Theme::get_constant_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -1017,6 +1102,31 @@ void Theme::add_theme_item_type(DataType p_data_type, const StringName &p_theme_ } } +void Theme::remove_theme_item_type(DataType p_data_type, const StringName &p_theme_type) { + switch (p_data_type) { + case DATA_TYPE_COLOR: + remove_color_type(p_theme_type); + break; + case DATA_TYPE_CONSTANT: + remove_constant_type(p_theme_type); + break; + case DATA_TYPE_FONT: + remove_font_type(p_theme_type); + break; + case DATA_TYPE_FONT_SIZE: + remove_font_size_type(p_theme_type); + break; + case DATA_TYPE_ICON: + remove_icon_type(p_theme_type); + break; + case DATA_TYPE_STYLEBOX: + remove_stylebox_type(p_theme_type); + break; + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + void Theme::get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const { switch (p_data_type) { case DATA_TYPE_COLOR: @@ -1101,6 +1211,38 @@ void Theme::get_type_variation_list(const StringName &p_base_type, List<StringNa } // Theme types. +void Theme::add_type(const StringName &p_theme_type) { + // Add a record to every data type map. + for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) { + Theme::DataType dt = (Theme::DataType)i; + add_theme_item_type(dt, p_theme_type); + } + + _emit_theme_changed(true); +} + +void Theme::remove_type(const StringName &p_theme_type) { + // Gracefully remove the record from every data type map. + for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) { + Theme::DataType dt = (Theme::DataType)i; + remove_theme_item_type(dt, p_theme_type); + } + + // If type is a variation, remove that connection. + if (get_type_variation_base(p_theme_type) != StringName()) { + clear_type_variation(p_theme_type); + } + + // If type is a variation base, remove all those connections. + List<StringName> names; + get_type_variation_list(p_theme_type, &names); + for (const StringName &E : names) { + clear_type_variation(E); + } + + _emit_theme_changed(true); +} + void Theme::get_type_list(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); @@ -1668,6 +1810,8 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("get_type_variation_base", "theme_type"), &Theme::get_type_variation_base); ClassDB::bind_method(D_METHOD("get_type_variation_list", "base_type"), &Theme::_get_type_variation_list); + ClassDB::bind_method(D_METHOD("add_type", "theme_type"), &Theme::add_type); + ClassDB::bind_method(D_METHOD("remove_type", "theme_type"), &Theme::remove_type); ClassDB::bind_method(D_METHOD("get_type_list"), &Theme::_get_type_list); ClassDB::bind_method(D_METHOD("merge_with", "other"), &Theme::merge_with); diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 822743a1fe..9afe05007d 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -32,7 +32,6 @@ #define THEME_H #include "core/io/resource.h" -#include "core/io/resource_loader.h" #include "scene/resources/font.h" #include "scene/resources/style_box.h" #include "scene/resources/texture.h" @@ -158,6 +157,7 @@ public: void clear_icon(const StringName &p_name, const StringName &p_theme_type); void get_icon_list(StringName p_theme_type, List<StringName> *p_list) const; void add_icon_type(const StringName &p_theme_type); + void remove_icon_type(const StringName &p_theme_type); void get_icon_type_list(List<StringName> *p_list) const; void set_stylebox(const StringName &p_name, const StringName &p_theme_type, const Ref<StyleBox> &p_style); @@ -168,6 +168,7 @@ public: void clear_stylebox(const StringName &p_name, const StringName &p_theme_type); void get_stylebox_list(StringName p_theme_type, List<StringName> *p_list) const; void add_stylebox_type(const StringName &p_theme_type); + void remove_stylebox_type(const StringName &p_theme_type); void get_stylebox_type_list(List<StringName> *p_list) const; void set_font(const StringName &p_name, const StringName &p_theme_type, const Ref<Font> &p_font); @@ -178,6 +179,7 @@ public: void clear_font(const StringName &p_name, const StringName &p_theme_type); void get_font_list(StringName p_theme_type, List<StringName> *p_list) const; void add_font_type(const StringName &p_theme_type); + void remove_font_type(const StringName &p_theme_type); void get_font_type_list(List<StringName> *p_list) const; void set_font_size(const StringName &p_name, const StringName &p_theme_type, int p_font_size); @@ -188,6 +190,7 @@ public: void clear_font_size(const StringName &p_name, const StringName &p_theme_type); void get_font_size_list(StringName p_theme_type, List<StringName> *p_list) const; void add_font_size_type(const StringName &p_theme_type); + void remove_font_size_type(const StringName &p_theme_type); void get_font_size_type_list(List<StringName> *p_list) const; void set_color(const StringName &p_name, const StringName &p_theme_type, const Color &p_color); @@ -198,6 +201,7 @@ public: void clear_color(const StringName &p_name, const StringName &p_theme_type); void get_color_list(StringName p_theme_type, List<StringName> *p_list) const; void add_color_type(const StringName &p_theme_type); + void remove_color_type(const StringName &p_theme_type); void get_color_type_list(List<StringName> *p_list) const; void set_constant(const StringName &p_name, const StringName &p_theme_type, int p_constant); @@ -208,6 +212,7 @@ public: void clear_constant(const StringName &p_name, const StringName &p_theme_type); void get_constant_list(StringName p_theme_type, List<StringName> *p_list) const; void add_constant_type(const StringName &p_theme_type); + void remove_constant_type(const StringName &p_theme_type); void get_constant_type_list(List<StringName> *p_list) const; void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type, const Variant &p_value); @@ -218,6 +223,7 @@ public: void clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type); void get_theme_item_list(DataType p_data_type, StringName p_theme_type, List<StringName> *p_list) const; void add_theme_item_type(DataType p_data_type, const StringName &p_theme_type); + void remove_theme_item_type(DataType p_data_type, const StringName &p_theme_type); void get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const; void set_type_variation(const StringName &p_theme_type, const StringName &p_base_type); @@ -226,6 +232,8 @@ public: StringName get_type_variation_base(const StringName &p_theme_type) const; void get_type_variation_list(const StringName &p_base_type, List<StringName> *p_list) const; + void add_type(const StringName &p_theme_type); + void remove_type(const StringName &p_theme_type); void get_type_list(List<StringName> *p_list) const; void get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variant, List<StringName> *p_list); diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index 91f9a026d3..4a277c3d84 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -31,8 +31,8 @@ #ifndef WORLD_2D_H #define WORLD_2D_H -#include "core/config/project_settings.h" #include "core/io/resource.h" +#include "scene/resources/world_2d.h" #include "servers/physics_server_2d.h" class VisibleOnScreenNotifier2D; diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp index c012ab6177..0088236112 100644 --- a/scene/resources/world_3d.cpp +++ b/scene/resources/world_3d.cpp @@ -30,7 +30,7 @@ #include "world_3d.h" -#include "core/math/camera_matrix.h" +#include "core/config/project_settings.h" #include "core/math/octree.h" #include "scene/3d/camera_3d.h" #include "scene/3d/visible_on_screen_notifier_3d.h" |