diff options
Diffstat (limited to 'editor/editor_properties.cpp')
-rw-r--r-- | editor/editor_properties.cpp | 1880 |
1 files changed, 747 insertions, 1133 deletions
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index fa44239e32..99619cfc40 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -38,7 +38,7 @@ #include "scene/main/window.h" #include "scene/resources/font.h" -///////////////////// NULL ///////////////////////// +///////////////////// Nil ///////////////////////// void EditorPropertyNil::update_property() { } @@ -51,7 +51,7 @@ EditorPropertyNil::EditorPropertyNil() { ///////////////////// TEXT ///////////////////////// -void EditorPropertyText::_text_entered(const String &p_string) { +void EditorPropertyText::_text_submitted(const String &p_string) { if (updating) { return; } @@ -100,7 +100,7 @@ EditorPropertyText::EditorPropertyText() { add_child(text); add_focusable(text); text->connect("text_changed", callable_mp(this, &EditorPropertyText::_text_changed)); - text->connect("text_entered", callable_mp(this, &EditorPropertyText::_text_entered)); + text->connect("text_submitted", callable_mp(this, &EditorPropertyText::_text_submitted)); string_name = false; updating = false; @@ -121,7 +121,7 @@ void EditorPropertyMultilineText::_open_big_text() { if (!big_text_dialog) { big_text = memnew(TextEdit); big_text->connect("text_changed", callable_mp(this, &EditorPropertyMultilineText::_big_text_changed)); - big_text->set_wrap_enabled(true); + big_text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY); big_text_dialog = memnew(AcceptDialog); big_text_dialog->add_child(big_text); big_text_dialog->set_title(TTR("Edit Text:")); @@ -147,10 +147,10 @@ void EditorPropertyMultilineText::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { - Ref<Texture2D> df = get_theme_icon("DistractionFree", "EditorIcons"); + Ref<Texture2D> df = get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons")); open_big_text->set_icon(df); - Ref<Font> font = get_theme_font("font", "Label"); - int font_size = get_theme_font_size("font_size", "Label"); + Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); + int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6)); } break; @@ -166,7 +166,7 @@ EditorPropertyMultilineText::EditorPropertyMultilineText() { set_bottom_editor(hb); text = memnew(TextEdit); text->connect("text_changed", callable_mp(this, &EditorPropertyMultilineText::_text_changed)); - text->set_wrap_enabled(true); + text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY); add_focusable(text); hb->add_child(text); text->set_h_size_flags(SIZE_EXPAND_FILL); @@ -180,44 +180,150 @@ EditorPropertyMultilineText::EditorPropertyMultilineText() { ///////////////////// TEXT ENUM ///////////////////////// -void EditorPropertyTextEnum::_option_selected(int p_which) { +void EditorPropertyTextEnum::_emit_changed_value(String p_string) { if (string_name) { - emit_changed(get_edited_property(), StringName(options->get_item_text(p_which))); + emit_changed(get_edited_property(), StringName(p_string)); } else { - emit_changed(get_edited_property(), options->get_item_text(p_which)); + emit_changed(get_edited_property(), p_string); } } +void EditorPropertyTextEnum::_option_selected(int p_which) { + _emit_changed_value(option_button->get_item_text(p_which)); +} + +void EditorPropertyTextEnum::_edit_custom_value() { + default_layout->hide(); + edit_custom_layout->show(); + custom_value_edit->grab_focus(); +} + +void EditorPropertyTextEnum::_custom_value_submitted(String p_value) { + edit_custom_layout->hide(); + default_layout->show(); + + _emit_changed_value(p_value.strip_edges()); +} + +void EditorPropertyTextEnum::_custom_value_accepted() { + String new_value = custom_value_edit->get_text().strip_edges(); + _custom_value_submitted(new_value); +} + +void EditorPropertyTextEnum::_custom_value_cancelled() { + custom_value_edit->set_text(get_edited_object()->get(get_edited_property())); + + edit_custom_layout->hide(); + default_layout->show(); +} + void EditorPropertyTextEnum::update_property() { - String which = get_edited_object()->get(get_edited_property()); - for (int i = 0; i < options->get_item_count(); i++) { - String t = options->get_item_text(i); - if (t == which) { - options->select(i); - return; + String current_value = get_edited_object()->get(get_edited_property()); + int default_option = options.find(current_value); + + // The list can change in the loose mode. + if (loose_mode) { + custom_value_edit->set_text(current_value); + option_button->clear(); + + // Manually entered value. + if (default_option < 0 && !current_value.is_empty()) { + option_button->add_item(current_value, options.size() + 1001); + option_button->select(0); + + option_button->add_separator(); } + + // Add an explicit empty value for clearing the property. + option_button->add_item("", options.size() + 1000); + + for (int i = 0; i < options.size(); i++) { + option_button->add_item(options[i], i); + if (options[i] == current_value) { + option_button->select(option_button->get_item_count() - 1); + } + } + } else { + option_button->select(default_option); } } -void EditorPropertyTextEnum::setup(const Vector<String> &p_options, bool p_string_name) { +void EditorPropertyTextEnum::setup(const Vector<String> &p_options, bool p_string_name, bool p_loose_mode) { + string_name = p_string_name; + loose_mode = p_loose_mode; + + options.clear(); + + if (loose_mode) { + // Add an explicit empty value for clearing the property in the loose mode. + option_button->add_item("", options.size() + 1000); + } + for (int i = 0; i < p_options.size(); i++) { - options->add_item(p_options[i], i); + options.append(p_options[i]); + option_button->add_item(p_options[i], i); + } + + if (loose_mode) { + edit_button->show(); } - string_name = p_string_name; } void EditorPropertyTextEnum::_bind_methods() { } -EditorPropertyTextEnum::EditorPropertyTextEnum() { - options = memnew(OptionButton); - options->set_clip_text(true); - options->set_flat(true); - string_name = false; +void EditorPropertyTextEnum::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: + edit_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); + accept_button->set_icon(get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons"))); + cancel_button->set_icon(get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons"))); + break; + } +} - add_child(options); - add_focusable(options); - options->connect("item_selected", callable_mp(this, &EditorPropertyTextEnum::_option_selected)); +EditorPropertyTextEnum::EditorPropertyTextEnum() { + default_layout = memnew(HBoxContainer); + add_child(default_layout); + + edit_custom_layout = memnew(HBoxContainer); + edit_custom_layout->hide(); + add_child(edit_custom_layout); + + option_button = memnew(OptionButton); + option_button->set_h_size_flags(SIZE_EXPAND_FILL); + option_button->set_clip_text(true); + option_button->set_flat(true); + default_layout->add_child(option_button); + option_button->connect("item_selected", callable_mp(this, &EditorPropertyTextEnum::_option_selected)); + + edit_button = memnew(Button); + edit_button->set_flat(true); + edit_button->hide(); + default_layout->add_child(edit_button); + edit_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_edit_custom_value)); + + custom_value_edit = memnew(LineEdit); + custom_value_edit->set_h_size_flags(SIZE_EXPAND_FILL); + edit_custom_layout->add_child(custom_value_edit); + custom_value_edit->connect("text_submitted", callable_mp(this, &EditorPropertyTextEnum::_custom_value_submitted)); + + accept_button = memnew(Button); + accept_button->set_flat(true); + edit_custom_layout->add_child(accept_button); + accept_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_custom_value_accepted)); + + cancel_button = memnew(Button); + cancel_button->set_flat(true); + edit_custom_layout->add_child(cancel_button); + cancel_button->connect("pressed", callable_mp(this, &EditorPropertyTextEnum::_custom_value_cancelled)); + + add_focusable(option_button); + add_focusable(edit_button); + add_focusable(custom_value_edit); + add_focusable(accept_button); + add_focusable(cancel_button); } ///////////////////// PATH ///////////////////////// @@ -280,7 +386,7 @@ void EditorPropertyPath::set_save_mode() { void EditorPropertyPath::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - path_edit->set_icon(get_theme_icon("Folder", "EditorIcons")); + path_edit->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } } @@ -297,7 +403,7 @@ EditorPropertyPath::EditorPropertyPath() { path = memnew(LineEdit); path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE); path_hb->add_child(path); - path->connect("text_entered", callable_mp(this, &EditorPropertyPath::_path_selected)); + path->connect("text_submitted", callable_mp(this, &EditorPropertyPath::_path_selected)); path->connect("focus_exited", callable_mp(this, &EditorPropertyPath::_path_focus_exited)); path->set_h_size_flags(SIZE_EXPAND_FILL); @@ -491,6 +597,7 @@ void EditorPropertyEnum::update_property() { } void EditorPropertyEnum::setup(const Vector<String> &p_options) { + options->clear(); int64_t current_val = 0; for (int i = 0; i < p_options.size(); i++) { Vector<String> text_split = p_options[i].split(":"); @@ -584,17 +691,39 @@ EditorPropertyFlags::EditorPropertyFlags() { class EditorPropertyLayersGrid : public Control { GDCLASS(EditorPropertyLayersGrid, Control); -public: - uint32_t value; +private: Vector<Rect2> flag_rects; + Rect2 expand_rect; + bool expand_hovered = false; + bool expanded = false; + int expansion_rows = 0; + int hovered_index = -1; + + Size2 get_grid_size() const { + Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); + int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); + return Vector2(0, font->get_height(font_size) * 3); + } + +public: + uint32_t value = 0; + int layer_group_size = 0; + int layer_count = 0; Vector<String> names; Vector<String> tooltips; - int hovered_index; virtual Size2 get_minimum_size() const override { - Ref<Font> font = get_theme_font("font", "Label"); - int font_size = get_theme_font_size("font_size", "Label"); - return Vector2(0, font->get_height(font_size) * 2); + Size2 min_size = get_grid_size(); + + // Add extra rows when expanded. + if (expanded) { + const int bsize = (min_size.height * 80 / 100) / 2; + for (int i = 0; i < expansion_rows; ++i) { + min_size.y += 2 * (bsize + 1) + 3; + } + } + + return min_size; } virtual String get_tooltip(const Point2 &p_pos) const override { @@ -605,80 +734,192 @@ public: } return String(); } + void _gui_input(const Ref<InputEvent> &p_ev) { const Ref<InputEventMouseMotion> mm = p_ev; - if (mm.is_valid()) { - for (int i = 0; i < flag_rects.size(); i++) { - if (flag_rects[i].has_point(mm->get_position())) { - // Used to highlight the hovered flag in the layers grid. - hovered_index = i; - update(); - break; + bool expand_was_hovered = expand_hovered; + expand_hovered = expand_rect.has_point(mm->get_position()); + if (expand_hovered != expand_was_hovered) { + update(); + } + + if (!expand_hovered) { + for (int i = 0; i < flag_rects.size(); i++) { + if (flag_rects[i].has_point(mm->get_position())) { + // Used to highlight the hovered flag in the layers grid. + hovered_index = i; + update(); + return; + } } } + + // Remove highlight when no square is hovered. + if (hovered_index != -1) { + hovered_index = -1; + update(); + } + + return; } const Ref<InputEventMouseButton> mb = p_ev; + if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { + if (hovered_index >= 0) { + // Toggle the flag. + // We base our choice on the hovered flag, so that it always matches the hovered flag. + if (value & (1 << hovered_index)) { + value &= ~(1 << hovered_index); + } else { + value |= (1 << hovered_index); + } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed() && hovered_index >= 0) { - // Toggle the flag. - // We base our choice on the hovered flag, so that it always matches the hovered flag. - if (value & (1 << hovered_index)) { - value &= ~(1 << hovered_index); - } else { - value |= (1 << hovered_index); + emit_signal(SNAME("flag_changed"), value); + update(); + } else if (expand_hovered) { + expanded = !expanded; + minimum_size_changed(); + update(); } - - emit_signal("flag_changed", value); - update(); } } void _notification(int p_what) { switch (p_what) { case NOTIFICATION_DRAW: { - Rect2 rect; - rect.size = get_size(); + Size2 grid_size = get_grid_size(); + grid_size.x = get_size().x; + flag_rects.clear(); - const int bsize = (rect.size.height * 80 / 100) / 2; + int prev_expansion_rows = expansion_rows; + expansion_rows = 0; + + const int bsize = (grid_size.height * 80 / 100) / 2; const int h = bsize * 2 + 1; - const int vofs = (rect.size.height - h) / 2; - Color color = get_theme_color("highlight_color", "Editor"); - for (int i = 0; i < 2; i++) { - Point2 ofs(4, vofs); - if (i == 1) { + Color color = get_theme_color(SNAME("highlight_color"), SNAME("Editor")); + + Color text_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); + text_color.a *= 0.5; + + Color text_color_on = get_theme_color(SNAME("font_hover_color"), SNAME("Editor")); + text_color_on.a *= 0.7; + + const int vofs = (grid_size.height - h) / 2; + + int layer_index = 0; + int block_index = 0; + + Point2 arrow_pos; + + Point2 block_ofs(4, vofs); + + while (true) { + Point2 ofs = block_ofs; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < layer_group_size; j++) { + const bool on = value & (1 << layer_index); + Rect2 rect2 = Rect2(ofs, Size2(bsize, bsize)); + + color.a = on ? 0.6 : 0.2; + if (layer_index == hovered_index) { + // Add visual feedback when hovering a flag. + color.a += 0.15; + } + + draw_rect(rect2, color); + flag_rects.push_back(rect2); + + Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); + Vector2 offset; + offset.y = rect2.size.y * 0.75; + + draw_string(font, rect2.position + offset, itos(layer_index + 1), HALIGN_CENTER, rect2.size.x, -1, on ? text_color_on : text_color); + + ofs.x += bsize + 1; + + ++layer_index; + } + + ofs.x = block_ofs.x; ofs.y += bsize + 1; } - ofs += rect.position; - for (int j = 0; j < 10; j++) { - Point2 o = ofs + Point2(j * (bsize + 1), 0); - if (j >= 5) { - o.x += 1; + if (layer_index >= layer_count) { + if (!flag_rects.is_empty() && (expansion_rows == 0)) { + const Rect2 &last_rect = flag_rects[flag_rects.size() - 1]; + arrow_pos = last_rect.position + last_rect.size; } + break; + } - const int idx = i * 10 + j; - const bool on = value & (1 << idx); - Rect2 rect2 = Rect2(o, Size2(bsize, bsize)); + int block_size_x = layer_group_size * (bsize + 1); + block_ofs.x += block_size_x + 3; - color.a = on ? 0.6 : 0.2; - if (idx == hovered_index) { - // Add visual feedback when hovering a flag. - color.a += 0.15; + if (block_ofs.x + block_size_x + 12 > grid_size.width) { + // Keep last valid cell position for the expansion icon. + if (!flag_rects.is_empty() && (expansion_rows == 0)) { + const Rect2 &last_rect = flag_rects[flag_rects.size() - 1]; + arrow_pos = last_rect.position + last_rect.size; + } + ++expansion_rows; + + if (expanded) { + // Expand grid to next line. + block_ofs.x = 4; + block_ofs.y += 2 * (bsize + 1) + 3; + } else { + // Skip remaining blocks. + break; } - - draw_rect(rect2, color); - flag_rects.push_back(rect2); } + + ++block_index; + } + + if ((expansion_rows != prev_expansion_rows) && expanded) { + minimum_size_changed(); + } + + if ((expansion_rows == 0) && (layer_index == layer_count)) { + // Whole grid was drawn, no need for expansion icon. + break; + } + + Ref<Texture2D> arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree")); + ERR_FAIL_COND(arrow.is_null()); + + Color arrow_color = get_theme_color(SNAME("highlight_color"), SNAME("Editor")); + arrow_color.a = expand_hovered ? 1.0 : 0.6; + + arrow_pos.x += 2.0; + arrow_pos.y -= arrow->get_height(); + + Rect2 arrow_draw_rect(arrow_pos, arrow->get_size()); + expand_rect = arrow_draw_rect; + if (expanded) { + arrow_draw_rect.size.y *= -1.0; // Flip arrow vertically when expanded. } + + RID ci = get_canvas_item(); + arrow->draw_rect(ci, arrow_draw_rect, false, arrow_color); + } break; + case NOTIFICATION_MOUSE_EXIT: { - hovered_index = -1; - update(); + if (expand_hovered) { + expand_hovered = false; + update(); + } + if (hovered_index != -1) { + hovered_index = -1; + update(); + } } break; + default: break; } @@ -693,12 +934,8 @@ public: ClassDB::bind_method(D_METHOD("_gui_input"), &EditorPropertyLayersGrid::_gui_input); ADD_SIGNAL(MethodInfo("flag_changed", PropertyInfo(Variant::INT, "flag"))); } - - EditorPropertyLayersGrid() { - value = 0; - hovered_index = -1; // Nothing is hovered. - } }; + void EditorPropertyLayers::_grid_changed(uint32_t p_grid) { emit_changed(get_edited_property(), p_grid); } @@ -711,38 +948,57 @@ void EditorPropertyLayers::update_property() { void EditorPropertyLayers::setup(LayerType p_layer_type) { String basename; + int layer_group_size = 0; + int layer_count = 0; switch (p_layer_type) { - case LAYER_RENDER_2D: + case LAYER_RENDER_2D: { basename = "layer_names/2d_render"; - break; - case LAYER_PHYSICS_2D: + layer_group_size = 5; + layer_count = 20; + } break; + + case LAYER_PHYSICS_2D: { basename = "layer_names/2d_physics"; - break; - case LAYER_NAVIGATION_2D: + layer_group_size = 4; + layer_count = 32; + } break; + + case LAYER_NAVIGATION_2D: { basename = "layer_names/2d_navigation"; - break; - case LAYER_RENDER_3D: + layer_group_size = 4; + layer_count = 32; + } break; + + case LAYER_RENDER_3D: { basename = "layer_names/3d_render"; - break; - case LAYER_PHYSICS_3D: + layer_group_size = 5; + layer_count = 20; + } break; + + case LAYER_PHYSICS_3D: { basename = "layer_names/3d_physics"; - break; - case LAYER_NAVIGATION_3D: + layer_group_size = 4; + layer_count = 32; + } break; + + case LAYER_NAVIGATION_3D: { basename = "layer_names/3d_navigation"; - break; + layer_group_size = 4; + layer_count = 32; + } break; } Vector<String> names; Vector<String> tooltips; - for (int i = 0; i < 20; i++) { + for (int i = 0; i < layer_count; i++) { String name; - if (ProjectSettings::get_singleton()->has_setting(basename + vformat("/layer_%d", i))) { - name = ProjectSettings::get_singleton()->get(basename + vformat("/layer_%d", i)); + if (ProjectSettings::get_singleton()->has_setting(basename + vformat("/layer_%d", i + 1))) { + name = ProjectSettings::get_singleton()->get(basename + vformat("/layer_%d", i + 1)); } if (name == "") { - name = vformat(TTR("Layer %d"), i); + name = vformat(TTR("Layer %d"), i + 1); } names.push_back(name); @@ -751,12 +1007,17 @@ void EditorPropertyLayers::setup(LayerType p_layer_type) { grid->names = names; grid->tooltips = tooltips; + grid->layer_group_size = layer_group_size; + grid->layer_count = layer_count; } void EditorPropertyLayers::_button_pressed() { + int layer_count = grid->layer_count; + int layer_group_size = grid->layer_group_size; + layers->clear(); - for (int i = 0; i < 20; i++) { - if (i == 5 || i == 10 || i == 15) { + for (int i = 0; i < layer_count; i++) { + if ((i != 0) && ((i % layer_group_size) == 0)) { layers->add_separator(); } layers->add_check_item(grid->names[i], i); @@ -787,17 +1048,21 @@ void EditorPropertyLayers::_bind_methods() { EditorPropertyLayers::EditorPropertyLayers() { HBoxContainer *hb = memnew(HBoxContainer); + hb->set_clip_contents(true); add_child(hb); grid = memnew(EditorPropertyLayersGrid); grid->connect("flag_changed", callable_mp(this, &EditorPropertyLayers::_grid_changed)); grid->set_h_size_flags(SIZE_EXPAND_FILL); hb->add_child(grid); + button = memnew(Button); button->set_toggle_mode(true); button->set_text("..."); button->connect("pressed", callable_mp(this, &EditorPropertyLayers::_button_pressed)); hb->add_child(button); + set_bottom_editor(hb); + layers = memnew(PopupMenu); add_child(layers); layers->set_hide_on_checkable_item_selection(false); @@ -850,7 +1115,7 @@ EditorPropertyInteger::EditorPropertyInteger() { ///////////////////// OBJECT ID ///////////////////////// void EditorPropertyObjectID::_edit_pressed() { - emit_signal("object_id_selected", get_edited_property(), get_edited_object()->get(get_edited_property())); + emit_signal(SNAME("object_id_selected"), get_edited_property(), get_edited_object()->get(get_edited_property())); } void EditorPropertyObjectID::update_property() { @@ -892,11 +1157,17 @@ void EditorPropertyFloat::_value_changed(double val) { return; } + if (angle_in_radians) { + val = Math::deg2rad(val); + } emit_changed(get_edited_property(), val); } void EditorPropertyFloat::update_property() { double val = get_edited_object()->get(get_edited_property()); + if (angle_in_radians) { + val = Math::rad2deg(val); + } setting = true; spin->set_value(val); setting = false; @@ -905,7 +1176,8 @@ void EditorPropertyFloat::update_property() { void EditorPropertyFloat::_bind_methods() { } -void EditorPropertyFloat::setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_exp_range, bool p_greater, bool p_lesser) { +void EditorPropertyFloat::setup(double p_min, double p_max, double p_step, bool p_no_slider, bool p_exp_range, bool p_greater, bool p_lesser, const String &p_suffix, bool p_angle_in_radians) { + angle_in_radians = p_angle_in_radians; spin->set_min(p_min); spin->set_max(p_max); spin->set_step(p_step); @@ -913,6 +1185,7 @@ void EditorPropertyFloat::setup(double p_min, double p_max, double p_step, bool spin->set_exp_ratio(p_exp_range); spin->set_allow_greater(p_greater); spin->set_allow_lesser(p_lesser); + spin->set_suffix(p_suffix); } EditorPropertyFloat::EditorPropertyFloat() { @@ -921,7 +1194,6 @@ EditorPropertyFloat::EditorPropertyFloat() { add_child(spin); add_focusable(spin); spin->connect("value_changed", callable_mp(this, &EditorPropertyFloat::_value_changed)); - setting = false; } ///////////////////// EASING ///////////////////////// @@ -929,7 +1201,7 @@ EditorPropertyFloat::EditorPropertyFloat() { void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { const Ref<InputEventMouseButton> mb = p_ev; if (mb.is_valid()) { - if (mb->is_doubleclick() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->is_double_click() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { _setup_spin(); } @@ -951,7 +1223,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { const Ref<InputEventMouseMotion> mm = p_ev; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (dragging && mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { float rel = mm->get_relative().x; if (rel == 0) { return; @@ -994,39 +1266,34 @@ void EditorPropertyEasing::_draw_easing() { Size2 s = easing_draw->get_size(); - const int points = 48; + const int point_count = 48; - float prev = 1.0; const float exp = get_edited_object()->get(get_edited_property()); - const Ref<Font> f = get_theme_font("font", "Label"); - int font_size = get_theme_font_size("font_size", "Label"); - const Color font_color = get_theme_color("font_color", "Label"); + const Ref<Font> f = get_theme_font(SNAME("font"), SNAME("Label")); + int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); + const Color font_color = get_theme_color(SNAME("font_color"), SNAME("Label")); Color line_color; if (dragging) { - line_color = get_theme_color("accent_color", "Editor"); + line_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")); } else { - line_color = get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.9); + line_color = get_theme_color(SNAME("font_color"), SNAME("Label")) * Color(1, 1, 1, 0.9); } - Vector<Point2> lines; - for (int i = 1; i <= points; i++) { - float ifl = i / float(points); - float iflp = (i - 1) / float(points); + Vector<Point2> points; + for (int i = 0; i <= point_count; i++) { + float ifl = i / float(point_count); const float h = 1.0 - Math::ease(ifl, exp); if (flip) { ifl = 1.0 - ifl; - iflp = 1.0 - iflp; } - lines.push_back(Point2(ifl * s.width, h * s.height)); - lines.push_back(Point2(iflp * s.width, prev * s.height)); - prev = h; + points.push_back(Point2(ifl * s.width, h * s.height)); } - easing_draw->draw_multiline(lines, line_color, 1.0); + easing_draw->draw_polyline(points, line_color, 1.0, true); // Draw more decimals for small numbers since higher precision is usually required for fine adjustments. int decimals; if (Math::abs(exp) < 0.1 - CMP_EPSILON) { @@ -1096,15 +1363,15 @@ void EditorPropertyEasing::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { preset->clear(); - preset->add_icon_item(get_theme_icon("CurveConstant", "EditorIcons"), "Zero", EASING_ZERO); - preset->add_icon_item(get_theme_icon("CurveLinear", "EditorIcons"), "Linear", EASING_LINEAR); - preset->add_icon_item(get_theme_icon("CurveIn", "EditorIcons"), "In", EASING_IN); - preset->add_icon_item(get_theme_icon("CurveOut", "EditorIcons"), "Out", EASING_OUT); + preset->add_icon_item(get_theme_icon(SNAME("CurveConstant"), SNAME("EditorIcons")), "Zero", EASING_ZERO); + preset->add_icon_item(get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")), "Linear", EASING_LINEAR); + preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "In", EASING_IN); + preset->add_icon_item(get_theme_icon(SNAME("CurveOut"), SNAME("EditorIcons")), "Out", EASING_OUT); if (full) { - preset->add_icon_item(get_theme_icon("CurveInOut", "EditorIcons"), "In-Out", EASING_IN_OUT); - preset->add_icon_item(get_theme_icon("CurveOutIn", "EditorIcons"), "Out-In", EASING_OUT_IN); + preset->add_icon_item(get_theme_icon(SNAME("CurveInOut"), SNAME("EditorIcons")), "In-Out", EASING_IN_OUT); + preset->add_icon_item(get_theme_icon(SNAME("CurveOutIn"), SNAME("EditorIcons")), "Out-In", EASING_OUT_IN); } - easing_draw->set_custom_minimum_size(Size2(0, get_theme_font("font", "Label")->get_height(get_theme_font_size("font_size", "Label")) * 2)); + easing_draw->set_custom_minimum_size(Size2(0, get_theme_font(SNAME("font"), SNAME("Label"))->get_height(get_theme_font_size(SNAME("font_size"), SNAME("Label"))) * 2)); } break; } } @@ -1164,7 +1431,7 @@ void EditorPropertyVector2::update_property() { void EditorPropertyVector2::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 2; i++) { Color c = base; c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1176,7 +1443,7 @@ void EditorPropertyVector2::_notification(int p_what) { void EditorPropertyVector2::_bind_methods() { } -void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 2; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1184,6 +1451,7 @@ void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, boo spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -1250,7 +1518,7 @@ void EditorPropertyRect2::update_property() { void EditorPropertyRect2::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 4; i++) { Color c = base; c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1262,7 +1530,7 @@ void EditorPropertyRect2::_notification(int p_what) { void EditorPropertyRect2::_bind_methods() { } -void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 4; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1270,6 +1538,7 @@ void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -1330,6 +1599,11 @@ void EditorPropertyVector3::_value_changed(double val, const String &p_name) { v3.x = spin[0]->get_value(); v3.y = spin[1]->get_value(); v3.z = spin[2]->get_value(); + if (angle_in_radians) { + v3.x = Math::deg2rad(v3.x); + v3.y = Math::deg2rad(v3.y); + v3.z = Math::deg2rad(v3.z); + } emit_changed(get_edited_property(), v3, p_name); } @@ -1338,6 +1612,11 @@ void EditorPropertyVector3::update_property() { } void EditorPropertyVector3::update_using_vector(Vector3 p_vector) { + if (angle_in_radians) { + p_vector.x = Math::rad2deg(p_vector.x); + p_vector.y = Math::rad2deg(p_vector.y); + p_vector.z = Math::rad2deg(p_vector.z); + } setting = true; spin[0]->set_value(p_vector.x); spin[1]->set_value(p_vector.y); @@ -1350,12 +1629,18 @@ Vector3 EditorPropertyVector3::get_vector() { v3.x = spin[0]->get_value(); v3.y = spin[1]->get_value(); v3.z = spin[2]->get_value(); + if (angle_in_radians) { + v3.x = Math::deg2rad(v3.x); + v3.y = Math::deg2rad(v3.y); + v3.z = Math::deg2rad(v3.z); + } + return v3; } void EditorPropertyVector3::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 3; i++) { Color c = base; c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1367,7 +1652,8 @@ void EditorPropertyVector3::_notification(int p_what) { void EditorPropertyVector3::_bind_methods() { } -void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix, bool p_angle_in_radians) { + angle_in_radians = p_angle_in_radians; for (int i = 0; i < 3; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1375,6 +1661,7 @@ void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, boo spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -1411,7 +1698,6 @@ EditorPropertyVector3::EditorPropertyVector3(bool p_force_wide) { if (!horizontal) { set_label_reference(spin[0]); //show text and buttons around this } - setting = false; } ///////////////////// VECTOR2i ///////////////////////// @@ -1437,7 +1723,7 @@ void EditorPropertyVector2i::update_property() { void EditorPropertyVector2i::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 2; i++) { Color c = base; c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1449,7 +1735,7 @@ void EditorPropertyVector2i::_notification(int p_what) { void EditorPropertyVector2i::_bind_methods() { } -void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider) { +void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 2; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1457,6 +1743,7 @@ void EditorPropertyVector2i::setup(int p_min, int p_max, bool p_no_slider) { spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -1523,7 +1810,7 @@ void EditorPropertyRect2i::update_property() { void EditorPropertyRect2i::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 4; i++) { Color c = base; c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1535,7 +1822,7 @@ void EditorPropertyRect2i::_notification(int p_what) { void EditorPropertyRect2i::_bind_methods() { } -void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_no_slider) { +void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 4; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1543,6 +1830,7 @@ void EditorPropertyRect2i::setup(int p_min, int p_max, bool p_no_slider) { spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -1617,7 +1905,7 @@ void EditorPropertyVector3i::update_property() { void EditorPropertyVector3i::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 3; i++) { Color c = base; c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1629,7 +1917,7 @@ void EditorPropertyVector3i::_notification(int p_what) { void EditorPropertyVector3i::_bind_methods() { } -void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider) { +void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 3; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1637,6 +1925,7 @@ void EditorPropertyVector3i::setup(int p_min, int p_max, bool p_no_slider) { spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -1702,7 +1991,7 @@ void EditorPropertyPlane::update_property() { void EditorPropertyPlane::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 3; i++) { Color c = base; c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1714,7 +2003,7 @@ void EditorPropertyPlane::_notification(int p_what) { void EditorPropertyPlane::_bind_methods() { } -void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 4; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1722,6 +2011,7 @@ void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -1761,14 +2051,14 @@ EditorPropertyPlane::EditorPropertyPlane(bool p_force_wide) { setting = false; } -///////////////////// QUAT ///////////////////////// +///////////////////// QUATERNION ///////////////////////// -void EditorPropertyQuat::_value_changed(double val, const String &p_name) { +void EditorPropertyQuaternion::_value_changed(double val, const String &p_name) { if (setting) { return; } - Quat p; + Quaternion p; p.x = spin[0]->get_value(); p.y = spin[1]->get_value(); p.z = spin[2]->get_value(); @@ -1776,8 +2066,8 @@ void EditorPropertyQuat::_value_changed(double val, const String &p_name) { emit_changed(get_edited_property(), p, p_name); } -void EditorPropertyQuat::update_property() { - Quat val = get_edited_object()->get(get_edited_property()); +void EditorPropertyQuaternion::update_property() { + Quaternion val = get_edited_object()->get(get_edited_property()); setting = true; spin[0]->set_value(val.x); spin[1]->set_value(val.y); @@ -1786,9 +2076,9 @@ void EditorPropertyQuat::update_property() { setting = false; } -void EditorPropertyQuat::_notification(int p_what) { +void EditorPropertyQuaternion::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 3; i++) { Color c = base; c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1797,10 +2087,10 @@ void EditorPropertyQuat::_notification(int p_what) { } } -void EditorPropertyQuat::_bind_methods() { +void EditorPropertyQuaternion::_bind_methods() { } -void EditorPropertyQuat::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyQuaternion::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 4; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1808,10 +2098,11 @@ void EditorPropertyQuat::setup(double p_min, double p_max, double p_step, bool p spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } -EditorPropertyQuat::EditorPropertyQuat() { +EditorPropertyQuaternion::EditorPropertyQuaternion() { bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing"); BoxContainer *bc; @@ -1832,7 +2123,7 @@ EditorPropertyQuat::EditorPropertyQuat() { spin[i]->set_label(desc[i]); bc->add_child(spin[i]); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyQuat::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyQuaternion::_value_changed), varray(desc[i])); if (horizontal) { spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); } @@ -1877,7 +2168,7 @@ void EditorPropertyAABB::update_property() { void EditorPropertyAABB::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 6; i++) { Color c = base; c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1889,7 +2180,7 @@ void EditorPropertyAABB::_notification(int p_what) { void EditorPropertyAABB::_bind_methods() { } -void EditorPropertyAABB::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyAABB::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 6; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1897,6 +2188,7 @@ void EditorPropertyAABB::setup(double p_min, double p_max, double p_step, bool p spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -1953,7 +2245,7 @@ void EditorPropertyTransform2D::update_property() { void EditorPropertyTransform2D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 6; i++) { Color c = base; c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -1965,7 +2257,7 @@ void EditorPropertyTransform2D::_notification(int p_what) { void EditorPropertyTransform2D::_bind_methods() { } -void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 6; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -1973,6 +2265,7 @@ void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step, spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -2034,7 +2327,7 @@ void EditorPropertyBasis::update_property() { void EditorPropertyBasis::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 9; i++) { Color c = base; c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -2046,7 +2339,7 @@ void EditorPropertyBasis::_notification(int p_what) { void EditorPropertyBasis::_bind_methods() { } -void EditorPropertyBasis::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyBasis::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 9; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -2054,6 +2347,7 @@ void EditorPropertyBasis::setup(double p_min, double p_max, double p_step, bool spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } @@ -2078,12 +2372,12 @@ EditorPropertyBasis::EditorPropertyBasis() { ///////////////////// TRANSFORM ///////////////////////// -void EditorPropertyTransform::_value_changed(double val, const String &p_name) { +void EditorPropertyTransform3D::_value_changed(double val, const String &p_name) { if (setting) { return; } - Transform p; + Transform3D p; p.basis[0][0] = spin[0]->get_value(); p.basis[1][0] = spin[1]->get_value(); p.basis[2][0] = spin[2]->get_value(); @@ -2100,11 +2394,11 @@ void EditorPropertyTransform::_value_changed(double val, const String &p_name) { emit_changed(get_edited_property(), p, p_name); } -void EditorPropertyTransform::update_property() { +void EditorPropertyTransform3D::update_property() { update_using_transform(get_edited_object()->get(get_edited_property())); } -void EditorPropertyTransform::update_using_transform(Transform p_transform) { +void EditorPropertyTransform3D::update_using_transform(Transform3D p_transform) { setting = true; spin[0]->set_value(p_transform.basis[0][0]); spin[1]->set_value(p_transform.basis[1][0]); @@ -2121,9 +2415,9 @@ void EditorPropertyTransform::update_using_transform(Transform p_transform) { setting = false; } -void EditorPropertyTransform::_notification(int p_what) { +void EditorPropertyTransform3D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color("accent_color", "Editor"); + Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); for (int i = 0; i < 12; i++) { Color c = base; c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); @@ -2132,10 +2426,10 @@ void EditorPropertyTransform::_notification(int p_what) { } } -void EditorPropertyTransform::_bind_methods() { +void EditorPropertyTransform3D::_bind_methods() { } -void EditorPropertyTransform::setup(double p_min, double p_max, double p_step, bool p_no_slider) { +void EditorPropertyTransform3D::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) { for (int i = 0; i < 12; i++) { spin[i]->set_min(p_min); spin[i]->set_max(p_max); @@ -2143,10 +2437,11 @@ void EditorPropertyTransform::setup(double p_min, double p_max, double p_step, b spin[i]->set_hide_slider(p_no_slider); spin[i]->set_allow_greater(true); spin[i]->set_allow_lesser(true); + spin[i]->set_suffix(p_suffix); } } -EditorPropertyTransform::EditorPropertyTransform() { +EditorPropertyTransform3D::EditorPropertyTransform3D() { GridContainer *g = memnew(GridContainer); g->set_columns(3); add_child(g); @@ -2159,7 +2454,7 @@ EditorPropertyTransform::EditorPropertyTransform() { g->add_child(spin[i]); spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); add_focusable(spin[i]); - spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform::_value_changed), varray(desc[i])); + spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform3D::_value_changed), varray(desc[i])); } set_bottom_editor(g); setting = false; @@ -2190,6 +2485,9 @@ void EditorPropertyColor::_picker_created() { } else if (default_color_mode == 2) { picker->get_picker()->set_raw_mode(true); } + + int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); + picker->get_picker()->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); } void EditorPropertyColor::_picker_opening() { @@ -2258,7 +2556,7 @@ void EditorPropertyNodePath::_node_selected(const NodePath &p_path) { base_node = get_edited_object()->call("get_root_path"); } - if (!base_node && Object::cast_to<Reference>(get_edited_object())) { + if (!base_node && Object::cast_to<RefCounted>(get_edited_object())) { Node *to_node = get_node(p_path); ERR_FAIL_COND(!to_node); path = get_tree()->get_edited_scene_root()->get_path_to(to_node); @@ -2335,7 +2633,7 @@ void EditorPropertyNodePath::setup(const NodePath &p_base_hint, Vector<StringNam void EditorPropertyNodePath::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Ref<Texture2D> t = get_theme_icon("Clear", "EditorIcons"); + Ref<Texture2D> t = get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")); clear->set_icon(t); } } @@ -2381,456 +2679,81 @@ EditorPropertyRID::EditorPropertyRID() { ////////////// RESOURCE ////////////////////// -void EditorPropertyResource::_file_selected(const String &p_path) { - RES res = ResourceLoader::load(p_path); - - ERR_FAIL_COND_MSG(res.is_null(), "Cannot load resource from path '" + p_path + "'."); - - List<PropertyInfo> prop_list; - get_edited_object()->get_property_list(&prop_list); - String property_types; - - for (List<PropertyInfo>::Element *E = prop_list.front(); E; E = E->next()) { - if (E->get().name == get_edited_property() && (E->get().hint & PROPERTY_HINT_RESOURCE_TYPE)) { - property_types = E->get().hint_string; - } - } - if (!property_types.is_empty()) { - bool any_type_matches = false; - const Vector<String> split_property_types = property_types.split(","); - for (int i = 0; i < split_property_types.size(); ++i) { - if (res->is_class(split_property_types[i])) { - any_type_matches = true; - break; - } - } - - if (!any_type_matches) { - EditorNode::get_singleton()->show_warning(vformat(TTR("The selected resource (%s) does not match any type expected for this property (%s)."), res->get_class(), property_types)); - } +void EditorPropertyResource::_resource_selected(const RES &p_resource) { + if (use_sub_inspector) { + bool unfold = !get_edited_object()->editor_is_section_unfolded(get_edited_property()); + get_edited_object()->editor_set_section_unfold(get_edited_property(), unfold); + update_property(); + } else { + emit_signal(SNAME("resource_selected"), get_edited_property(), p_resource); } - - emit_changed(get_edited_property(), res); - update_property(); } -void EditorPropertyResource::_menu_option(int p_which) { - //scene_tree->popup_scenetree_dialog(); - switch (p_which) { - case OBJ_MENU_LOAD: { - if (!file) { - file = memnew(EditorFileDialog); - file->connect("file_selected", callable_mp(this, &EditorPropertyResource::_file_selected)); - add_child(file); - } - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - String type = base_type; - - List<String> extensions; - for (int i = 0; i < type.get_slice_count(","); i++) { - ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",", i), &extensions); - } - - Set<String> valid_extensions; - for (List<String>::Element *E = extensions.front(); E; E = E->next()) { - valid_extensions.insert(E->get()); - } - - file->clear_filters(); - for (Set<String>::Element *E = valid_extensions.front(); E; E = E->next()) { - file->add_filter("*." + E->get() + " ; " + E->get().to_upper()); - } - - file->popup_file_dialog(); - } break; - - case OBJ_MENU_EDIT: { - RES res = get_edited_object()->get(get_edited_property()); +void EditorPropertyResource::_resource_changed(const RES &p_resource) { + // Make visual script the correct type. + Ref<Script> s = p_resource; + if (get_edited_object() && s.is_valid()) { + s->call("set_instance_base_type", get_edited_object()->get_class()); + } - if (!res.is_null()) { - emit_signal("resource_selected", get_edited_property(), res); - } - } break; - case OBJ_MENU_CLEAR: { + // Prevent the creation of invalid ViewportTextures when possible. + Ref<ViewportTexture> vpt = p_resource; + if (vpt.is_valid()) { + Resource *r = Object::cast_to<Resource>(get_edited_object()); + if (r && r->get_path().is_resource_file()) { + EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on resources saved as a file.\nResource needs to belong to a scene.")); emit_changed(get_edited_property(), RES()); update_property(); - - } break; - - case OBJ_MENU_MAKE_UNIQUE: { - RES res_orig = get_edited_object()->get(get_edited_property()); - if (res_orig.is_null()) { - return; - } - - List<PropertyInfo> property_list; - res_orig->get_property_list(&property_list); - List<Pair<String, Variant>> propvalues; - - for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) { - Pair<String, Variant> p; - PropertyInfo &pi = E->get(); - if (pi.usage & PROPERTY_USAGE_STORAGE) { - p.first = pi.name; - p.second = res_orig->get(pi.name); - } - - propvalues.push_back(p); - } - - String orig_type = res_orig->get_class(); - - Object *inst = ClassDB::instance(orig_type); - - Ref<Resource> res = Ref<Resource>(Object::cast_to<Resource>(inst)); - - ERR_FAIL_COND(res.is_null()); - - for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) { - Pair<String, Variant> &p = E->get(); - res->set(p.first, p.second); - } - - emit_changed(get_edited_property(), res); - update_property(); - - } break; - - case OBJ_MENU_SAVE: { - RES res = get_edited_object()->get(get_edited_property()); - if (res.is_null()) { - return; - } - EditorNode::get_singleton()->save_resource(res); - } break; - - case OBJ_MENU_COPY: { - RES res = get_edited_object()->get(get_edited_property()); - - EditorSettings::get_singleton()->set_resource_clipboard(res); - - } break; - case OBJ_MENU_PASTE: { - RES res = EditorSettings::get_singleton()->get_resource_clipboard(); - emit_changed(get_edited_property(), res); - update_property(); - - } break; - case OBJ_MENU_NEW_SCRIPT: { - if (Object::cast_to<Node>(get_edited_object())) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object()), false); - } - - } break; - case OBJ_MENU_EXTEND_SCRIPT: { - if (Object::cast_to<Node>(get_edited_object())) { - EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(Object::cast_to<Node>(get_edited_object()), true); - } - - } break; - case OBJ_MENU_SHOW_IN_FILE_SYSTEM: { - RES res = get_edited_object()->get(get_edited_property()); - - FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock(); - file_system_dock->navigate_to_path(res->get_path()); - // Ensure that the FileSystem dock is visible. - TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); - tab_container->set_current_tab(file_system_dock->get_index()); - } break; - default: { - RES res = get_edited_object()->get(get_edited_property()); - - if (p_which >= CONVERT_BASE_ID) { - int to_type = p_which - CONVERT_BASE_ID; - - Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(res); - - ERR_FAIL_INDEX(to_type, conversions.size()); - - Ref<Resource> new_res = conversions[to_type]->convert(res); - - emit_changed(get_edited_property(), new_res); - update_property(); - break; - } - ERR_FAIL_COND(inheritors_array.is_empty()); - - String intype = inheritors_array[p_which - TYPE_BASE_ID]; - - if (intype == "ViewportTexture") { - Resource *r = Object::cast_to<Resource>(get_edited_object()); - if (r && r->get_path().is_resource_file()) { - EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on resources saved as a file.\nResource needs to belong to a scene.")); - return; - } - - if (r && !r->is_local_to_scene()) { - EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on this resource because it's not set as local to scene.\nPlease switch on the 'local to scene' property on it (and all resources containing it up to a node).")); - return; - } - - if (!scene_tree) { - scene_tree = memnew(SceneTreeDialog); - Vector<StringName> valid_types; - valid_types.push_back("Viewport"); - scene_tree->get_scene_tree()->set_valid_types(valid_types); - scene_tree->get_scene_tree()->set_show_enabled_subscene(true); - add_child(scene_tree); - scene_tree->connect("selected", callable_mp(this, &EditorPropertyResource::_viewport_selected)); - scene_tree->set_title(TTR("Pick a Viewport")); - } - scene_tree->popup_scenetree_dialog(); - - return; - } - - Variant obj; - - if (ScriptServer::is_global_class(intype)) { - obj = ClassDB::instance(ScriptServer::get_global_class_native_base(intype)); - if (obj) { - Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(intype)); - if (script.is_valid()) { - ((Object *)obj)->set_script(script); - } - } - } else { - obj = ClassDB::instance(intype); - } - - if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); - } - - Resource *resp = Object::cast_to<Resource>(obj); - ERR_BREAK(!resp); - if (get_edited_object() && base_type != String() && base_type == "Script") { - //make visual script the right type - resp->call("set_instance_base_type", get_edited_object()->get_class()); - } - - res = RES(resp); - emit_changed(get_edited_property(), res); - update_property(); - - } break; - } -} - -void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, ObjectID p_obj) { - RES p = get_edited_object()->get(get_edited_property()); - if (p.is_valid() && p->get_instance_id() == p_obj) { - String type = p->get_class_name(); - - if (ClassDB::is_parent_class(type, "Script")) { - assign->set_text(p->get_path().get_file()); return; } - if (p_preview.is_valid()) { - preview->set_offset(SIDE_LEFT, assign->get_icon()->get_width() + assign->get_theme_stylebox("normal")->get_default_margin(SIDE_LEFT) + get_theme_constant("hseparation", "Button")); - if (type == "GradientTexture") { - preview->set_stretch_mode(TextureRect::STRETCH_SCALE); - assign->set_custom_minimum_size(Size2(1, 1)); - } else { - preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; - assign->set_custom_minimum_size(Size2(1, thumbnail_size)); - } - preview->set_texture(p_preview); - assign->set_text(""); - } - } -} - -void EditorPropertyResource::_update_menu_items() { - //////////////////// UPDATE MENU ////////////////////////// - RES res = get_edited_object()->get(get_edited_property()); - - menu->clear(); - - if (get_edited_property() == "script" && base_type == "Script" && Object::cast_to<Node>(get_edited_object())) { - menu->add_icon_item(get_theme_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); - menu->add_icon_item(get_theme_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT); - menu->add_separator(); - } else if (base_type != "") { - int idx = 0; - - Vector<EditorData::CustomType> custom_resources; - - if (EditorNode::get_editor_data().get_custom_types().has("Resource")) { - custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; - } - - for (int i = 0; i < base_type.get_slice_count(","); i++) { - String base = base_type.get_slice(",", i); - - Set<String> valid_inheritors; - valid_inheritors.insert(base); - List<StringName> inheritors; - ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors); - - for (int j = 0; j < custom_resources.size(); j++) { - inheritors.push_back(custom_resources[j].name); - } - - List<StringName>::Element *E = inheritors.front(); - while (E) { - valid_inheritors.insert(E->get()); - E = E->next(); - } - - List<StringName> global_classes; - ScriptServer::get_global_class_list(&global_classes); - E = global_classes.front(); - while (E) { - if (EditorNode::get_editor_data().script_class_is_parent(E->get(), base_type)) { - valid_inheritors.insert(E->get()); - } - E = E->next(); - } - - for (Set<String>::Element *F = valid_inheritors.front(); F; F = F->next()) { - const String &t = F->get(); - - bool is_custom_resource = false; - Ref<Texture2D> icon; - if (!custom_resources.is_empty()) { - for (int j = 0; j < custom_resources.size(); j++) { - if (custom_resources[j].name == t) { - is_custom_resource = true; - if (custom_resources[j].icon.is_valid()) { - icon = custom_resources[j].icon; - } - break; - } - } - } - - if (!is_custom_resource && !(ScriptServer::is_global_class(t) || ClassDB::can_instance(t))) { - continue; - } - - inheritors_array.push_back(t); - - if (!icon.is_valid()) { - icon = get_theme_icon(has_theme_icon(t, "EditorIcons") ? t : "Object", "EditorIcons"); - } - - int id = TYPE_BASE_ID + idx; - menu->add_icon_item(icon, vformat(TTR("New %s"), t), id); - - idx++; - } - } - - if (menu->get_item_count()) { - menu->add_separator(); - } - } - - menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD); - - if (!res.is_null()) { - menu->add_icon_item(get_theme_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT); - menu->add_icon_item(get_theme_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR); - menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); - menu->add_icon_item(get_theme_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE); - RES r = res; - if (r.is_valid() && r->get_path().is_resource_file()) { - menu->add_separator(); - menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); - } - } - - RES cb = EditorSettings::get_singleton()->get_resource_clipboard(); - bool paste_valid = false; - if (cb.is_valid()) { - if (base_type == "") { - paste_valid = true; - } else { - for (int i = 0; i < base_type.get_slice_count(","); i++) { - if (ClassDB::is_parent_class(cb->get_class(), base_type.get_slice(",", i))) { - paste_valid = true; - break; - } - } + if (r && !r->is_local_to_scene()) { + EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on this resource because it's not set as local to scene.\nPlease switch on the 'local to scene' property on it (and all resources containing it up to a node).")); + emit_changed(get_edited_property(), RES()); + update_property(); + return; } } - if (!res.is_null() || paste_valid) { - menu->add_separator(); + emit_changed(get_edited_property(), p_resource); + update_property(); - if (!res.is_null()) { - menu->add_item(TTR("Copy"), OBJ_MENU_COPY); - } + // Automatically suggest setting up the path for a ViewportTexture. + if (vpt.is_valid() && vpt->get_viewport_path_in_scene().is_empty()) { + if (!scene_tree) { + scene_tree = memnew(SceneTreeDialog); + scene_tree->set_title(TTR("Pick a Viewport")); - if (paste_valid) { - menu->add_item(TTR("Paste"), OBJ_MENU_PASTE); - } - } + Vector<StringName> valid_types; + valid_types.push_back("Viewport"); + scene_tree->get_scene_tree()->set_valid_types(valid_types); + scene_tree->get_scene_tree()->set_show_enabled_subscene(true); - if (!res.is_null()) { - Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(res); - if (conversions.size()) { - menu->add_separator(); + add_child(scene_tree); + scene_tree->connect("selected", callable_mp(this, &EditorPropertyResource::_viewport_selected)); } - for (int i = 0; i < conversions.size(); i++) { - String what = conversions[i]->converts_to(); - Ref<Texture2D> icon; - if (has_theme_icon(what, "EditorIcons")) { - icon = get_theme_icon(what, "EditorIcons"); - } else { - icon = get_theme_icon(what, "Resource"); - } - menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i); - } + scene_tree->popup_scenetree_dialog(); } } -void EditorPropertyResource::_update_menu() { - _update_menu_items(); - - Rect2 gt = edit->get_screen_rect(); - menu->set_as_minsize(); - int ms = menu->get_contents_minimum_size().width; - Vector2 popup_pos = gt.position + gt.size - Vector2(ms, 0); - menu->set_position(popup_pos); - menu->popup(); -} - void EditorPropertyResource::_sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool) { - emit_signal("property_keyed_with_value", String(get_edited_property()) + ":" + p_property, p_value, false); + emit_signal(SNAME("property_keyed_with_value"), String(get_edited_property()) + ":" + p_property, p_value, false); } void EditorPropertyResource::_sub_inspector_resource_selected(const RES &p_resource, const String &p_property) { - emit_signal("resource_selected", String(get_edited_property()) + ":" + p_property, p_resource); + emit_signal(SNAME("resource_selected"), String(get_edited_property()) + ":" + p_property, p_resource); } void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) { - emit_signal("object_id_selected", get_edited_property(), p_id); -} - -void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) { - Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { - _update_menu_items(); - Vector2 pos = get_screen_position() + mb->get_position(); - //pos = assign->get_global_transform().xform(pos); - menu->set_as_minsize(); - menu->set_position(pos); - menu->popup(); - } - } + emit_signal(SNAME("object_id_selected"), get_edited_property(), p_id); } void EditorPropertyResource::_open_editor_pressed() { RES res = get_edited_object()->get(get_edited_property()); if (res.is_valid()) { - EditorNode::get_singleton()->call_deferred("edit_item_resource", res); //may clear the editor so do it deferred + // May clear the editor so do it deferred. + EditorNode::get_singleton()->call_deferred(SNAME("edit_item_resource"), res); } } @@ -2840,28 +2763,28 @@ void EditorPropertyResource::_fold_other_editors(Object *p_self) { } RES res = get_edited_object()->get(get_edited_property()); - if (!res.is_valid()) { return; } + bool use_editor = false; for (int i = 0; i < EditorNode::get_editor_data().get_editor_plugin_count(); i++) { EditorPlugin *ep = EditorNode::get_editor_data().get_editor_plugin(i); if (ep->handles(res.ptr())) { use_editor = true; + break; } } - if (!use_editor) { return; } - bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); opened_editor = false; + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); if (unfolded) { - //refold - assign->set_pressed(false); + // Refold. + resource_picker->set_toggle_pressed(false); get_edited_object()->editor_set_section_unfold(get_edited_property(), false); update_property(); } @@ -2873,6 +2796,7 @@ void EditorPropertyResource::_update_property_bg() { } updating_theme = true; + if (sub_inspector != nullptr) { int count_subinspectors = 0; Node *n = get_parent(); @@ -2885,29 +2809,81 @@ void EditorPropertyResource::_update_property_bg() { } count_subinspectors = MIN(15, count_subinspectors); - add_theme_color_override("property_color", get_theme_color("sub_inspector_property_color", "Editor")); + add_theme_color_override("property_color", get_theme_color(SNAME("sub_inspector_property_color"), SNAME("Editor"))); add_theme_style_override("bg_selected", get_theme_stylebox("sub_inspector_property_bg_selected" + itos(count_subinspectors), "Editor")); add_theme_style_override("bg", get_theme_stylebox("sub_inspector_property_bg" + itos(count_subinspectors), "Editor")); - add_theme_constant_override("font_offset", get_theme_constant("sub_inspector_font_offset", "Editor")); + add_theme_constant_override("font_offset", get_theme_constant(SNAME("sub_inspector_font_offset"), SNAME("Editor"))); add_theme_constant_override("vseparation", 0); } else { - add_theme_color_override("property_color", get_theme_color("property_color", "EditorProperty")); - add_theme_style_override("bg_selected", get_theme_stylebox("bg_selected", "EditorProperty")); - add_theme_style_override("bg", get_theme_stylebox("bg", "EditorProperty")); - add_theme_constant_override("vseparation", get_theme_constant("vseparation", "EditorProperty")); - add_theme_constant_override("font_offset", get_theme_constant("font_offset", "EditorProperty")); + add_theme_color_override("property_color", get_theme_color(SNAME("property_color"), SNAME("EditorProperty"))); + add_theme_style_override("bg_selected", get_theme_stylebox(SNAME("bg_selected"), SNAME("EditorProperty"))); + add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("EditorProperty"))); + add_theme_constant_override("vseparation", get_theme_constant(SNAME("vseparation"), SNAME("EditorProperty"))); + add_theme_constant_override("font_offset", get_theme_constant(SNAME("font_offset"), SNAME("EditorProperty"))); } updating_theme = false; update(); } + +void EditorPropertyResource::_viewport_selected(const NodePath &p_path) { + Node *to_node = get_node(p_path); + if (!Object::cast_to<Viewport>(to_node)) { + EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!")); + return; + } + + Ref<ViewportTexture> vt; + vt.instantiate(); + vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node)); + vt->setup_local_to_scene(); + + emit_changed(get_edited_property(), vt); + update_property(); +} + +void EditorPropertyResource::setup(Object *p_object, const String &p_path, const String &p_base_type) { + if (resource_picker) { + resource_picker->disconnect("resource_selected", callable_mp(this, &EditorPropertyResource::_resource_selected)); + resource_picker->disconnect("resource_changed", callable_mp(this, &EditorPropertyResource::_resource_changed)); + memdelete(resource_picker); + } + + if (p_path == "script" && p_base_type == "Script" && Object::cast_to<Node>(p_object)) { + EditorScriptPicker *script_picker = memnew(EditorScriptPicker); + script_picker->set_script_owner(Object::cast_to<Node>(p_object)); + resource_picker = script_picker; + } else if (p_path == "shader" && p_base_type == "Shader" && Object::cast_to<ShaderMaterial>(p_object)) { + EditorShaderPicker *shader_picker = memnew(EditorShaderPicker); + shader_picker->set_edited_material(Object::cast_to<ShaderMaterial>(p_object)); + resource_picker = shader_picker; + } else { + resource_picker = memnew(EditorResourcePicker); + } + + resource_picker->set_base_type(p_base_type); + resource_picker->set_editable(true); + resource_picker->set_h_size_flags(SIZE_EXPAND_FILL); + add_child(resource_picker); + + resource_picker->connect("resource_selected", callable_mp(this, &EditorPropertyResource::_resource_selected)); + resource_picker->connect("resource_changed", callable_mp(this, &EditorPropertyResource::_resource_changed)); + + for (int i = 0; i < resource_picker->get_child_count(); i++) { + Button *b = Object::cast_to<Button>(resource_picker->get_child(i)); + if (b) { + add_focusable(b); + } + } +} + void EditorPropertyResource::update_property() { RES res = get_edited_object()->get(get_edited_property()); if (use_sub_inspector) { - if (res.is_valid() != assign->is_toggle_mode()) { - assign->set_toggle_mode(res.is_valid()); + if (res.is_valid() != resource_picker->is_toggle_mode()) { + resource_picker->set_toggle_mode(res.is_valid()); } if (res.is_valid() && get_edited_object()->editor_is_section_unfolded(get_edited_property())) { @@ -2932,7 +2908,7 @@ void EditorPropertyResource::update_property() { set_bottom_editor(sub_inspector_vbox); sub_inspector_vbox->add_child(sub_inspector); - assign->set_pressed(true); + resource_picker->set_toggle_pressed(true); bool use_editor = false; for (int i = 0; i < EditorNode::get_editor_data().get_editor_plugin_count(); i++) { @@ -2943,10 +2919,10 @@ void EditorPropertyResource::update_property() { } if (use_editor) { - //open editor directly and hide other open of these + // Open editor directly and hide other such editors which are currently open. _open_editor_pressed(); if (is_inside_tree()) { - get_tree()->call_deferred("call_group", "_editor_resource_properties", "_fold_other_editors", this); + get_tree()->call_deferred(SNAME("call_group"), "_editor_resource_properties", "_fold_other_editors", this); } opened_editor = true; } @@ -2964,102 +2940,18 @@ void EditorPropertyResource::update_property() { memdelete(sub_inspector_vbox); sub_inspector = nullptr; sub_inspector_vbox = nullptr; + if (opened_editor) { EditorNode::get_singleton()->hide_top_editors(); opened_editor = false; } + _update_property_bg(); } } } - preview->set_texture(Ref<Texture2D>()); - if (res == RES()) { - assign->set_icon(Ref<Texture2D>()); - assign->set_text(TTR("[empty]")); - assign->set_custom_minimum_size(Size2(1, 1)); - } else { - assign->set_icon(EditorNode::get_singleton()->get_object_icon(res.operator->(), "Object")); - - if (res->get_name() != String()) { - assign->set_text(res->get_name()); - } else if (res->get_path().is_resource_file()) { - assign->set_text(res->get_path().get_file()); - assign->set_tooltip(res->get_path()); - } else { - assign->set_text(res->get_class()); - } - - if (res->get_path().is_resource_file()) { - assign->set_tooltip(res->get_path()); - } - - //preview will override the above, so called at the end - EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_resource_preview", res->get_instance_id()); - } -} - -void EditorPropertyResource::_resource_selected() { - RES res = get_edited_object()->get(get_edited_property()); - - if (res.is_null()) { - edit->set_pressed(true); - _update_menu(); - return; - } - - if (use_sub_inspector) { - bool unfold = !get_edited_object()->editor_is_section_unfolded(get_edited_property()); - get_edited_object()->editor_set_section_unfold(get_edited_property(), unfold); - update_property(); - } else { - emit_signal("resource_selected", get_edited_property(), res); - } -} - -void EditorPropertyResource::setup(const String &p_base_type) { - base_type = p_base_type; -} - -void EditorPropertyResource::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - if (updating_theme) { - return; - } - Ref<Texture2D> t = get_theme_icon("select_arrow", "Tree"); - edit->set_icon(t); - _update_property_bg(); - } - - if (p_what == NOTIFICATION_DRAG_BEGIN) { - if (_is_drop_valid(get_viewport()->gui_get_drag_data())) { - dropping = true; - assign->update(); - } - } - - if (p_what == NOTIFICATION_DRAG_END) { - if (dropping) { - dropping = false; - assign->update(); - } - } -} - -void EditorPropertyResource::_viewport_selected(const NodePath &p_path) { - Node *to_node = get_node(p_path); - if (!Object::cast_to<Viewport>(to_node)) { - EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!")); - return; - } - - Ref<ViewportTexture> vt; - vt.instance(); - vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node)); - vt->setup_local_to_scene(); - - emit_changed(get_edited_property(), vt); - update_property(); + resource_picker->set_edited_resource(res); } void EditorPropertyResource::collapse_all_folding() { @@ -3074,202 +2966,29 @@ void EditorPropertyResource::expand_all_folding() { } } -void EditorPropertyResource::_button_draw() { - if (dropping) { - Color color = get_theme_color("accent_color", "Editor"); - assign->draw_rect(Rect2(Point2(), assign->get_size()), color, false); - } -} - -Variant EditorPropertyResource::get_drag_data_fw(const Point2 &p_point, Control *p_from) { - RES res = get_edited_object()->get(get_edited_property()); - if (res.is_valid()) { - return EditorNode::get_singleton()->drag_resource(res, p_from); - } - - return Variant(); -} - -bool EditorPropertyResource::_is_drop_valid(const Dictionary &p_drag_data) const { - Vector<String> allowed_types = base_type.split(","); - int size = allowed_types.size(); - for (int i = 0; i < size; i++) { - String at = allowed_types[i].strip_edges(); - if (at == "StandardMaterial3D") { - allowed_types.append("Texture2D"); - } else if (at == "ShaderMaterial") { - allowed_types.append("Shader"); - } else if (at == "Font") { - allowed_types.append("FontData"); - } - } - - Dictionary drag_data = p_drag_data; - - Ref<Resource> res; - if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { - ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); - res = se->get_edited_resource(); - } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - res = drag_data["resource"]; - } - - if (res.is_valid()) { - for (int i = 0; i < allowed_types.size(); i++) { - String at = allowed_types[i].strip_edges(); - if (ClassDB::is_parent_class(res->get_class(), at)) { - return true; - } - } - } - - if (drag_data.has("type") && String(drag_data["type"]) == "files") { - Vector<String> files = drag_data["files"]; - - if (files.size() == 1) { - String file = files[0]; - String ftype = EditorFileSystem::get_singleton()->get_file_type(file); - - if (ftype != "") { - for (int i = 0; i < allowed_types.size(); i++) { - String at = allowed_types[i].strip_edges(); - if (ClassDB::is_parent_class(ftype, at)) { - return true; - } - } - } - } - } - - return false; -} - -bool EditorPropertyResource::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { - return _is_drop_valid(p_data); +void EditorPropertyResource::set_use_sub_inspector(bool p_enable) { + use_sub_inspector = p_enable; } -void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { - ERR_FAIL_COND(!_is_drop_valid(p_data)); - - Dictionary drag_data = p_data; - - Ref<Resource> res; - if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { - ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); - res = se->get_edited_resource(); - } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - res = drag_data["resource"]; - } - - if (!res.is_valid() && drag_data.has("type") && String(drag_data["type"]) == "files") { - Vector<String> files = drag_data["files"]; - - if (files.size() == 1) { - String file = files[0]; - res = ResourceLoader::load(file); - } - } - - if (res.is_valid()) { - bool need_convert = true; - - Vector<String> allowed_types = base_type.split(","); - for (int i = 0; i < allowed_types.size(); i++) { - String at = allowed_types[i].strip_edges(); - if (ClassDB::is_parent_class(res->get_class(), at)) { - need_convert = false; - break; - } - } - - if (need_convert) { - for (int i = 0; i < allowed_types.size(); i++) { - String at = allowed_types[i].strip_edges(); - if (at == "StandardMaterial3D" && ClassDB::is_parent_class(res->get_class(), "Texture2D")) { - Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D); - mat->set_texture(StandardMaterial3D::TextureParam::TEXTURE_ALBEDO, res); - res = mat; - break; - } - - if (at == "ShaderMaterial" && ClassDB::is_parent_class(res->get_class(), "Shader")) { - Ref<ShaderMaterial> mat = memnew(ShaderMaterial); - mat->set_shader(res); - res = mat; - break; - } - - if (at == "Font" && ClassDB::is_parent_class(res->get_class(), "FontData")) { - Ref<Font> font = memnew(Font); - font->add_data(res); - res = font; - break; - } +void EditorPropertyResource::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + if (!updating_theme) { + _update_property_bg(); } - } - - emit_changed(get_edited_property(), res); - update_property(); - return; + } break; } } -void EditorPropertyResource::set_use_sub_inspector(bool p_enable) { - use_sub_inspector = p_enable; -} - void EditorPropertyResource::_bind_methods() { - ClassDB::bind_method(D_METHOD("_resource_preview"), &EditorPropertyResource::_resource_preview); - ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &EditorPropertyResource::get_drag_data_fw); - ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &EditorPropertyResource::can_drop_data_fw); - ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyResource::drop_data_fw); ClassDB::bind_method(D_METHOD("_open_editor_pressed"), &EditorPropertyResource::_open_editor_pressed); ClassDB::bind_method(D_METHOD("_fold_other_editors"), &EditorPropertyResource::_fold_other_editors); } EditorPropertyResource::EditorPropertyResource() { - opened_editor = false; - sub_inspector = nullptr; - sub_inspector_vbox = nullptr; use_sub_inspector = bool(EDITOR_GET("interface/inspector/open_resources_in_current_inspector")); - HBoxContainer *hbc = memnew(HBoxContainer); - add_child(hbc); - assign = memnew(Button); - assign->set_flat(true); - assign->set_h_size_flags(SIZE_EXPAND_FILL); - assign->set_clip_text(true); - assign->connect("pressed", callable_mp(this, &EditorPropertyResource::_resource_selected)); - assign->set_drag_forwarding(this); - assign->connect("draw", callable_mp(this, &EditorPropertyResource::_button_draw)); - hbc->add_child(assign); - add_focusable(assign); - - preview = memnew(TextureRect); - preview->set_expand(true); - preview->set_anchors_and_offsets_preset(PRESET_WIDE); - preview->set_offset(SIDE_TOP, 1); - preview->set_offset(SIDE_BOTTOM, -1); - preview->set_offset(SIDE_RIGHT, -1); - assign->add_child(preview); - assign->connect("gui_input", callable_mp(this, &EditorPropertyResource::_button_input)); - - menu = memnew(PopupMenu); - add_child(menu); - edit = memnew(Button); - edit->set_flat(true); - edit->set_toggle_mode(true); - menu->connect("id_pressed", callable_mp(this, &EditorPropertyResource::_menu_option)); - menu->connect("popup_hide", callable_mp((BaseButton *)edit, &BaseButton::set_pressed), varray(false)); - edit->connect("pressed", callable_mp(this, &EditorPropertyResource::_update_menu)); - hbc->add_child(edit); - edit->connect("gui_input", callable_mp(this, &EditorPropertyResource::_button_input)); - add_focusable(edit); - - file = nullptr; - scene_tree = nullptr; - dropping = false; - add_to_group("_editor_resource_properties"); } @@ -3283,31 +3002,97 @@ void EditorInspectorDefaultPlugin::parse_begin(Object *p_object) { //do none } -bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) { +bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { + Control *editor = EditorInspectorDefaultPlugin::get_editor_for_property(p_object, p_type, p_path, p_hint, p_hint_text, p_usage, p_wide); + if (editor) { + add_property_editor(p_path, editor); + } + return false; +} + +void EditorInspectorDefaultPlugin::parse_end() { + //do none +} + +struct EditorPropertyRangeHint { + bool angle_in_degrees = false; + bool greater = true; + bool lesser = true; + double min = -99999; + double max = 99999; + double step = 0; + String suffix; + bool exp_range = false; + bool hide_slider = true; + bool radians = false; +}; + +static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step) { + EditorPropertyRangeHint hint; + hint.step = p_default_step; + bool degrees = false; + if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { + hint.greater = false; //if using ranged, assume false by default + hint.lesser = false; + + hint.min = p_hint_text.get_slice(",", 0).to_float(); + hint.max = p_hint_text.get_slice(",", 1).to_float(); + if (p_hint_text.get_slice_count(",") >= 3) { + hint.step = p_hint_text.get_slice(",", 2).to_float(); + } + hint.hide_slider = false; + for (int i = 2; i < p_hint_text.get_slice_count(","); i++) { + String slice = p_hint_text.get_slice(",", i).strip_edges(); + if (slice == "radians") { + hint.radians = true; + } else if (slice == "degrees") { + degrees = true; + } else if (slice == "or_greater") { + hint.greater = true; + } else if (slice == "or_lesser") { + hint.lesser = true; + } else if (slice == "noslider") { + hint.hide_slider = true; + } else if (slice == "exp") { + hint.exp_range = true; + } else if (slice.begins_with("suffix:")) { + hint.suffix = " " + slice.replace_first("suffix:", "").strip_edges(); + } + } + } + + if ((hint.radians || degrees) && hint.suffix == String()) { + hint.suffix = U"\u00B0"; + } + + return hint; +} + +EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { double default_float_step = EDITOR_GET("interface/inspector/default_float_step"); switch (p_type) { // atomic types case Variant::NIL: { EditorPropertyNil *editor = memnew(EditorPropertyNil); - add_property_editor(p_path, editor); + return editor; } break; case Variant::BOOL: { EditorPropertyCheck *editor = memnew(EditorPropertyCheck); - add_property_editor(p_path, editor); + return editor; } break; case Variant::INT: { if (p_hint == PROPERTY_HINT_ENUM) { EditorPropertyEnum *editor = memnew(EditorPropertyEnum); Vector<String> options = p_hint_text.split(","); editor->setup(options); - add_property_editor(p_path, editor); + return editor; } else if (p_hint == PROPERTY_HINT_FLAGS) { EditorPropertyFlags *editor = memnew(EditorPropertyFlags); Vector<String> options = p_hint_text.split(","); editor->setup(options); - add_property_editor(p_path, editor); + return editor; } else if (p_hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || p_hint == PROPERTY_HINT_LAYERS_2D_RENDER || @@ -3340,41 +3125,20 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } EditorPropertyLayers *editor = memnew(EditorPropertyLayers); editor->setup(lt); - add_property_editor(p_path, editor); + return editor; } else if (p_hint == PROPERTY_HINT_OBJECT_ID) { EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID); editor->setup(p_hint_text); - add_property_editor(p_path, editor); + return editor; } else { EditorPropertyInteger *editor = memnew(EditorPropertyInteger); - int min = 0, max = 65535, step = 1; - bool greater = true, lesser = true; - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - greater = false; //if using ranged, assume false by default - lesser = false; - min = p_hint_text.get_slice(",", 0).to_int(); - max = p_hint_text.get_slice(",", 1).to_int(); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_int(); - } + editor->setup(hint.min, hint.max, hint.step, hint.greater, hint.lesser); - for (int i = 2; i < p_hint_text.get_slice_count(","); i++) { - String slice = p_hint_text.get_slice(",", i).strip_edges(); - if (slice == "or_greater") { - greater = true; - } - if (slice == "or_lesser") { - lesser = true; - } - } - } - - editor->setup(min, max, step, greater, lesser); - - add_property_editor(p_path, editor); + return editor; } } break; case Variant::FLOAT: { @@ -3394,54 +3158,30 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } editor->setup(full, flip); - add_property_editor(p_path, editor); + return editor; } else { EditorPropertyFloat *editor = memnew(EditorPropertyFloat); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - bool exp_range = false; - bool greater = true, lesser = true; - - if ((p_hint == PROPERTY_HINT_RANGE || p_hint == PROPERTY_HINT_EXP_RANGE) && p_hint_text.get_slice_count(",") >= 2) { - greater = false; //if using ranged, assume false by default - lesser = false; - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - exp_range = p_hint == PROPERTY_HINT_EXP_RANGE; - for (int i = 2; i < p_hint_text.get_slice_count(","); i++) { - String slice = p_hint_text.get_slice(",", i).strip_edges(); - if (slice == "or_greater") { - greater = true; - } - if (slice == "or_lesser") { - lesser = true; - } - } - } - editor->setup(min, max, step, hide_slider, exp_range, greater, lesser); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.exp_range, hint.greater, hint.lesser, hint.suffix, hint.radians); - add_property_editor(p_path, editor); + return editor; } } break; case Variant::STRING: { - if (p_hint == PROPERTY_HINT_ENUM) { + if (p_hint == PROPERTY_HINT_ENUM || p_hint == PROPERTY_HINT_ENUM_SUGGESTION) { EditorPropertyTextEnum *editor = memnew(EditorPropertyTextEnum); - Vector<String> options = p_hint_text.split(","); - editor->setup(options); - add_property_editor(p_path, editor); + Vector<String> options = p_hint_text.split(",", false); + editor->setup(options, false, (p_hint == PROPERTY_HINT_ENUM_SUGGESTION)); + return editor; } else if (p_hint == PROPERTY_HINT_MULTILINE_TEXT) { EditorPropertyMultilineText *editor = memnew(EditorPropertyMultilineText); - add_property_editor(p_path, editor); + return editor; } else if (p_hint == PROPERTY_HINT_TYPE_STRING) { EditorPropertyClassName *editor = memnew(EditorPropertyClassName); editor->setup("Object", p_hint_text); - add_property_editor(p_path, editor); + return editor; } else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) { Vector<String> extensions = p_hint_text.split(","); bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE; @@ -3452,7 +3192,7 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ if (save) { editor->set_save_mode(); } - add_property_editor(p_path, editor); + return editor; } else if (p_hint == PROPERTY_HINT_METHOD_OF_VARIANT_TYPE || p_hint == PROPERTY_HINT_METHOD_OF_BASE_TYPE || p_hint == PROPERTY_HINT_METHOD_OF_INSTANCE || @@ -3490,14 +3230,14 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } } editor->setup(type, p_hint_text); - add_property_editor(p_path, editor); + return editor; } else { EditorPropertyText *editor = memnew(EditorPropertyText); if (p_hint == PROPERTY_HINT_PLACEHOLDER_TEXT) { editor->set_placeholder(p_hint_text); } - add_property_editor(p_path, editor); + return editor; } } break; @@ -3505,204 +3245,82 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ case Variant::VECTOR2: { EditorPropertyVector2 *editor = memnew(EditorPropertyVector2(p_wide)); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; } break; case Variant::VECTOR2I: { EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i(p_wide)); - int min = -65535, max = 65535; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - hide_slider = false; - } - - editor->setup(min, max, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix); + return editor; } break; case Variant::RECT2: { EditorPropertyRect2 *editor = memnew(EditorPropertyRect2(p_wide)); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; } break; case Variant::RECT2I: { EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i(p_wide)); - int min = -65535, max = 65535; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - hide_slider = false; - } + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix); - editor->setup(min, max, hide_slider); - add_property_editor(p_path, editor); + return editor; } break; case Variant::VECTOR3: { EditorPropertyVector3 *editor = memnew(EditorPropertyVector3(p_wide)); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix, hint.radians); + return editor; } break; case Variant::VECTOR3I: { EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i(p_wide)); - int min = -65535, max = 65535; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - - hide_slider = false; - } - - editor->setup(min, max, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix); + return editor; } break; case Variant::TRANSFORM2D: { EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; } break; case Variant::PLANE: { EditorPropertyPlane *editor = memnew(EditorPropertyPlane(p_wide)); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; } break; - case Variant::QUAT: { - EditorPropertyQuat *editor = memnew(EditorPropertyQuat); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + case Variant::QUATERNION: { + EditorPropertyQuaternion *editor = memnew(EditorPropertyQuaternion); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; } break; case Variant::AABB: { EditorPropertyAABB *editor = memnew(EditorPropertyAABB); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; } break; case Variant::BASIS: { EditorPropertyBasis *editor = memnew(EditorPropertyBasis); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; } break; - case Variant::TRANSFORM: { - EditorPropertyTransform *editor = memnew(EditorPropertyTransform); - double min = -65535, max = 65535, step = default_float_step; - bool hide_slider = true; - - if (p_hint == PROPERTY_HINT_RANGE && p_hint_text.get_slice_count(",") >= 2) { - min = p_hint_text.get_slice(",", 0).to_float(); - max = p_hint_text.get_slice(",", 1).to_float(); - if (p_hint_text.get_slice_count(",") >= 3) { - step = p_hint_text.get_slice(",", 2).to_float(); - } - hide_slider = false; - } - - editor->setup(min, max, step, hide_slider); - add_property_editor(p_path, editor); + case Variant::TRANSFORM3D: { + EditorPropertyTransform3D *editor = memnew(EditorPropertyTransform3D); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); + editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); + return editor; } break; @@ -3710,21 +3328,21 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ case Variant::COLOR: { EditorPropertyColor *editor = memnew(EditorPropertyColor); editor->setup(p_hint != PROPERTY_HINT_COLOR_NO_ALPHA); - add_property_editor(p_path, editor); + return editor; } break; case Variant::STRING_NAME: { - if (p_hint == PROPERTY_HINT_ENUM) { + if (p_hint == PROPERTY_HINT_ENUM || p_hint == PROPERTY_HINT_ENUM_SUGGESTION) { EditorPropertyTextEnum *editor = memnew(EditorPropertyTextEnum); - Vector<String> options = p_hint_text.split(","); - editor->setup(options, true); - add_property_editor(p_path, editor); + Vector<String> options = p_hint_text.split(",", false); + editor->setup(options, true, (p_hint == PROPERTY_HINT_ENUM_SUGGESTION)); + return editor; } else { EditorPropertyText *editor = memnew(EditorPropertyText); if (p_hint == PROPERTY_HINT_PLACEHOLDER_TEXT) { editor->set_placeholder(p_hint_text); } editor->set_string_name(true); - add_property_editor(p_path, editor); + return editor; } } break; case Variant::NODE_PATH: { @@ -3737,16 +3355,16 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ Vector<StringName> sn = Variant(types); //convert via variant editor->setup(NodePath(), sn, (p_usage & PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT)); } - add_property_editor(p_path, editor); + return editor; } break; case Variant::RID: { EditorPropertyRID *editor = memnew(EditorPropertyRID); - add_property_editor(p_path, editor); + return editor; } break; case Variant::OBJECT: { EditorPropertyResource *editor = memnew(EditorPropertyResource); - editor->setup(p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource"); + editor->setup(p_object, p_path, p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource"); if (p_hint == PROPERTY_HINT_RESOURCE_TYPE) { String open_in_new = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); @@ -3761,70 +3379,66 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } } - add_property_editor(p_path, editor); + return editor; } break; case Variant::DICTIONARY: { EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary); - add_property_editor(p_path, editor); + return editor; } break; case Variant::ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::ARRAY, p_hint_text); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_BYTE_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_BYTE_ARRAY); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_INT32_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_INT32_ARRAY); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_INT64_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_INT64_ARRAY); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_FLOAT32_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_FLOAT32_ARRAY); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_FLOAT64_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_FLOAT64_ARRAY); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_STRING_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_STRING_ARRAY); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_VECTOR2_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_VECTOR2_ARRAY); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_VECTOR3_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_VECTOR3_ARRAY); - add_property_editor(p_path, editor); + return editor; } break; case Variant::PACKED_COLOR_ARRAY: { EditorPropertyArray *editor = memnew(EditorPropertyArray); editor->setup(Variant::PACKED_COLOR_ARRAY); - add_property_editor(p_path, editor); + } break; default: { } } - return false; //can be overridden, although it will most likely be last anyway -} - -void EditorInspectorDefaultPlugin::parse_end() { - //do none + return nullptr; } |