diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 38e74c126e..52e52dc823 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -37,7 +37,8 @@ #include "scene/resources/packed_scene.h" // TODO: -// arrays +// arrays and dictionary +// drag and drop Size2 EditorProperty::get_minimum_size() const { @@ -51,6 +52,9 @@ Size2 EditorProperty::get_minimum_size() const { continue; if (!c->is_visible()) continue; + if (c == bottom_editor) + continue; + Size2 minsize = c->get_combined_minimum_size(); ms.width = MAX(ms.width, minsize.width); ms.height = MAX(ms.height, minsize.height); @@ -66,10 +70,14 @@ Size2 EditorProperty::get_minimum_size() const { ms.width += check->get_width() + get_constant("hseparator", "Tree"); } - if (label_layout == LABEL_LAYOUT_TOP) { + if (bottom_editor != NULL) { Ref font = get_font("font", "Tree"); ms.height += font->get_height(); ms.height += get_constant("vseparation", "Tree"); + Size2 bems = bottom_editor->get_combined_minimum_size(); + bems.width += get_constant("item_margin", "Tree"); + ms.height += bems.height; + ms.width = MAX(ms.width, bems.width); } return ms; @@ -81,9 +89,12 @@ void EditorProperty::_notification(int p_what) { Size2 size = get_size(); Rect2 rect; + Rect2 bottom_rect; - if (label_layout == LABEL_LAYOUT_LEFT) { + { int child_room = size.width / 2; + Ref font = get_font("font", "Tree"); + int height = font->get_height(); //compute room needed for (int i = 0; i < get_child_count(); i++) { @@ -93,22 +104,23 @@ void EditorProperty::_notification(int p_what) { continue; if (c->is_set_as_toplevel()) continue; + if (c == bottom_editor) + continue; Size2 minsize = c->get_combined_minimum_size(); child_room = MAX(child_room, minsize.width); + height = MAX(height, minsize.height); } text_size = MAX(0, size.width - child_room + 4 * EDSCALE); - rect = Rect2(text_size, 0, size.width - text_size, size.height); - } else { - Ref font = get_font("font", "Tree"); + rect = Rect2(text_size, 0, size.width - text_size, height); - text_size = size.width; - rect.position.x = 0; - rect.position.y = font->get_height() + get_constant("vseparation", "Tree"); - rect.size = get_size(); - rect.size.height -= rect.position.y; + if (bottom_editor) { + + int m = get_constant("item_margin", "Tree"); + bottom_rect = Rect2(m, rect.size.height + get_constant("vseparation", "Tree"), size.width - m, bottom_editor->get_combined_minimum_size().height); + } } if (keying) { @@ -131,10 +143,16 @@ void EditorProperty::_notification(int p_what) { continue; if (c->is_set_as_toplevel()) continue; + if (c == bottom_editor) + continue; fit_child_in_rect(c, rect); } + if (bottom_editor) { + fit_child_in_rect(bottom_editor, bottom_rect); + } + update(); //need to redraw text } @@ -142,8 +160,8 @@ void EditorProperty::_notification(int p_what) { Ref font = get_font("font", "Tree"); Size2 size = get_size(); - if (label_layout == LABEL_LAYOUT_TOP) { - size.height = font->get_height(); + if (bottom_editor) { + size.height = bottom_editor->get_margin(MARGIN_TOP); } else if (label_reference) { size.height = label_reference->get_size().height; } @@ -626,7 +644,10 @@ void EditorProperty::set_label_reference(Control *p_control) { label_reference = p_control; } +void EditorProperty::set_bottom_editor(Control *p_control) { + bottom_editor = p_control; +} Variant EditorProperty::get_drag_data(const Point2 &p_point) { if (property == StringName()) @@ -644,10 +665,20 @@ Variant EditorProperty::get_drag_data(const Point2 &p_point) { return dp; } -void EditorProperty::set_label_layout(LabelLayout p_layout) { - label_layout = p_layout; - queue_sort(); - update(); +void EditorProperty::set_use_folding(bool p_use_folding) { + + use_folding = p_use_folding; +} + +bool EditorProperty::is_using_folding() const { + + return use_folding; +} + +void EditorProperty::expand_all_folding() { +} + +void EditorProperty::collapse_all_folding() { } void EditorProperty::_bind_methods() { @@ -685,6 +716,7 @@ void EditorProperty::_bind_methods() { ADD_SIGNAL(MethodInfo("property_changed", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); ADD_SIGNAL(MethodInfo("multiple_properties_changed", PropertyInfo(Variant::POOL_STRING_ARRAY, "properties"), PropertyInfo(Variant::ARRAY, "value"))); ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING, "property"))); + ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::STRING, "bool"))); ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::INT, "id"))); @@ -707,11 +739,12 @@ EditorProperty::EditorProperty() { revert_hover = false; check_hover = false; can_revert = false; + use_folding = false; property_usage = 0; selected = false; selected_focusable = -1; label_reference = NULL; - label_layout = LABEL_LAYOUT_LEFT; + bottom_editor = NULL; } //////////////////////////////////////////////// //////////////////////////////////////////////// @@ -755,6 +788,14 @@ void EditorInspectorPlugin::parse_begin(Object *p_object) { get_script_instance()->call("parse_begin", p_object); } } + +void EditorInspectorPlugin::parse_category(Object *p_object, const String &p_parse_category) { + + if (get_script_instance()) { + get_script_instance()->call("parse_category", p_object, p_parse_category); + } +} + bool EditorInspectorPlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) { if (get_script_instance()) { @@ -789,6 +830,10 @@ void EditorInspectorPlugin::_bind_methods() { BIND_VMETHOD(vm); vm.name = "parse_begin"; BIND_VMETHOD(vm); + vm.name = "parse_category"; + vm.arguments.push_back(PropertyInfo(Variant::STRING, "category")); + BIND_VMETHOD(vm); + vm.arguments.pop_back(); vm.name = "parse_property"; vm.return_val.type = Variant::BOOL; vm.arguments.push_back(PropertyInfo(Variant::INT, "type")); @@ -1096,6 +1141,55 @@ String EditorInspector::get_selected_path() const { return property_selected; } +void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref ped) { + + for (List::Element *F = ped->added_editors.front(); F; F = F->next()) { + + EditorProperty *ep = Object::cast_to(F->get().property_editor); + current_vbox->add_child(F->get().property_editor); + + if (ep) { + + ep->object = object; + ep->connect("property_changed", this, "_property_changed"); + ep->connect("property_keyed", this, "_property_keyed"); + ep->connect("property_keyed_with_value", this, "_property_keyed_with_value"); + ep->connect("property_checked", this, "_property_checked"); + ep->connect("selected", this, "_property_selected"); + ep->connect("multiple_properties_changed", this, "_multiple_properties_changed"); + ep->connect("resource_selected", this, "_resource_selected", varray(), CONNECT_DEFERRED); + ep->connect("object_id_selected", this, "_object_id_selected", varray(), CONNECT_DEFERRED); + + if (F->get().properties.size()) { + + if (F->get().properties.size() == 1) { + //since it's one, associate: + ep->property = F->get().properties[0]; + ep->property_usage = 0; + } + + if (F->get().label != String()) { + ep->set_label(F->get().label); + } + + for (int i = 0; i < F->get().properties.size(); i++) { + String prop = F->get().properties[i]; + + if (!editor_property_map.has(prop)) { + editor_property_map[prop] = List(); + } + editor_property_map[prop].push_back(ep); + } + } + + ep->set_read_only(read_only); + ep->update_property(); + ep->update_reload_status(); + } + } + ped->added_editors.clear(); +} + void EditorInspector::update_tree() { //to update properly if all is refreshed @@ -1139,6 +1233,12 @@ void EditorInspector::update_tree() { Color sscolor = get_color("prop_subsection", "Editor"); + for (List >::Element *E = valid_plugins.front(); E; E = E->next()) { + Ref ped = E->get(); + ped->parse_begin(object); + _parse_added_editors(main_vbox, ped); + } + for (List::Element *I = plist.front(); I; I = I->next()) { PropertyInfo &p = I->get(); @@ -1201,6 +1301,13 @@ void EditorInspector::update_tree() { category->set_tooltip(TTR("Class:") + " " + p.name + (class_descr_cache[type] == "" ? "" : "\n\n" + class_descr_cache[type])); } + + for (List >::Element *E = valid_plugins.front(); E; E = E->next()) { + Ref ped = E->get(); + ped->parse_category(object, p.name); + _parse_added_editors(main_vbox, ped); + } + continue; } else if (!(p.usage & PROPERTY_USAGE_EDITOR)) @@ -1339,7 +1446,10 @@ void EditorInspector::update_tree() { for (List >::Element *E = valid_plugins.front(); E; E = E->next()) { Ref ped = E->get(); ped->parse_property(object, p.type, p.name, p.hint, p.hint_string, p.usage); - for (List::Element *F = ped->added_editors.front(); F; F = F->next()) { + List editors = ped->added_editors; //make a copy, since plugins may be used again in a sub-inspector + ped->added_editors.clear(); + + for (List::Element *F = editors.front(); F; F = F->next()) { EditorProperty *ep = Object::cast_to(F->get().property_editor); current_vbox->add_child(F->get().property_editor); @@ -1349,6 +1459,7 @@ void EditorInspector::update_tree() { ep->object = object; ep->connect("property_changed", this, "_property_changed"); ep->connect("property_keyed", this, "_property_keyed"); + ep->connect("property_keyed_with_value", this, "_property_keyed_with_value"); ep->connect("property_checked", this, "_property_checked"); ep->connect("selected", this, "_property_selected"); ep->connect("multiple_properties_changed", this, "_multiple_properties_changed"); @@ -1360,6 +1471,7 @@ void EditorInspector::update_tree() { ep->set_tooltip(TTR("Property: ") + p.name); } ep->set_draw_red(draw_red); + ep->set_use_folding(use_folding); ep->set_checkable(checkable); ep->set_checked(checked); ep->set_keying(keying); @@ -1398,10 +1510,15 @@ void EditorInspector::update_tree() { } } } - ped->added_editors.clear(); } } + for (List >::Element *E = valid_plugins.front(); E; E = E->next()) { + Ref ped = E->get(); + ped->parse_end(); + _parse_added_editors(main_vbox, ped); + } + //see if this property exists and should be kept } void EditorInspector::update_property(const String &p_prop) { @@ -1416,14 +1533,14 @@ void EditorInspector::update_property(const String &p_prop) { void EditorInspector::_clear() { - editor_property_map.clear(); - sections.clear(); - pending.clear(); - property_selected = StringName(); - property_focusable = -1; while (main_vbox->get_child_count()) { memdelete(main_vbox->get_child(0)); } + property_selected = StringName(); + property_focusable = -1; + editor_property_map.clear(); + sections.clear(); + pending.clear(); } void EditorInspector::refresh() { @@ -1433,17 +1550,21 @@ void EditorInspector::refresh() { refresh_countdown = EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval"); } -void EditorInspector::edit(Object *p_object) { - if (object != p_object) { - _clear(); - } +Object *EditorInspector::get_edited_object() { + return object; +} +void EditorInspector::edit(Object *p_object) { + if (object == p_object) + return; if (object) { + _clear(); object->remove_change_receptor(this); } object = p_object; + if (object) { object->add_change_receptor(this); update_tree(); @@ -1518,12 +1639,23 @@ void EditorInspector::collapse_all_folding() { for (List::Element *E = sections.front(); E; E = E->next()) { E->get()->fold(); } + + for (Map >::Element *F = editor_property_map.front(); F; F = F->next()) { + for (List::Element *E = F->get().front(); E; E = E->next()) { + E->get()->collapse_all_folding(); + } + } } void EditorInspector::expand_all_folding() { for (List::Element *E = sections.front(); E; E = E->next()) { E->get()->unfold(); } + for (Map >::Element *F = editor_property_map.front(); F; F = F->next()) { + for (List::Element *E = F->get().front(); E; E = E->next()) { + E->get()->expand_all_folding(); + } + } } void EditorInspector::set_scroll_offset(int p_offset) { @@ -1653,6 +1785,14 @@ void EditorInspector::_property_keyed(const String &p_path) { emit_signal("property_keyed", p_path, object->get(p_path), false); //second param is deprecated } +void EditorInspector::_property_keyed_with_value(const String &p_path, const Variant &p_value) { + + if (!object) + return; + + emit_signal("property_keyed", p_path, p_value, false); //second param is deprecated +} + void EditorInspector::_property_checked(const String &p_path, bool p_checked) { if (!object) @@ -1791,6 +1931,7 @@ void EditorInspector::_bind_methods() { ClassDB::bind_method("_node_removed", &EditorInspector::_node_removed); ClassDB::bind_method("_filter_changed", &EditorInspector::_filter_changed); ClassDB::bind_method("_property_keyed", &EditorInspector::_property_keyed); + ClassDB::bind_method("_property_keyed_with_value", &EditorInspector::_property_keyed_with_value); ClassDB::bind_method("_property_checked", &EditorInspector::_property_checked); ClassDB::bind_method("_property_selected", &EditorInspector::_property_selected); ClassDB::bind_method("_resource_selected", &EditorInspector::_resource_selected); @@ -1807,9 +1948,8 @@ EditorInspector::EditorInspector() { main_vbox = memnew(VBoxContainer); main_vbox->set_h_size_flags(SIZE_EXPAND_FILL); add_child(main_vbox); - main_vbox->set_name("pipirulo"); - set_h_scroll(false); - set_v_scroll(true); + set_enable_h_scroll(false); + set_enable_v_scroll(true); show_categories = false; hide_script = true; diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 410c76dbb6..14387c46df 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -31,18 +31,15 @@ #ifndef EDITOR_INSPECTOR_H #define EDITOR_INSPECTOR_H -#include "editor_data.h" +#include "scene/gui/box_container.h" +#include "scene/gui/line_edit.h" #include "scene/gui/scroll_container.h" +class UndoRedo; + class EditorProperty : public Container { GDCLASS(EditorProperty, Container) -public: - enum LabelLayout { - LABEL_LAYOUT_LEFT, - LABEL_LAYOUT_TOP, - }; - private: String label; int text_size; @@ -50,8 +47,6 @@ private: Object *object; StringName property; - LabelLayout label_layout; - int property_usage; bool read_only; @@ -69,6 +64,8 @@ private: bool can_revert; + bool use_folding; + bool _might_be_in_instance(); bool _is_property_different(const Variant &p_current, const Variant &p_orig, int p_usage); bool _is_instanced_node_with_original_property_different(); @@ -80,6 +77,7 @@ private: Vector focusables; Control *label_reference; + Control *bottom_editor; protected: void _notification(int p_what); @@ -122,10 +120,16 @@ public: bool is_selected() const; void set_label_reference(Control *p_control); + void set_bottom_editor(Control *p_editor); + + void set_use_folding(bool p_use_folding); + bool is_using_folding() const; + + virtual void expand_all_folding(); + virtual void collapse_all_folding(); virtual Variant get_drag_data(const Point2 &p_point); - void set_label_layout(LabelLayout p_layout); EditorProperty(); }; @@ -151,6 +155,7 @@ public: virtual bool can_handle(Object *p_object); virtual void parse_begin(Object *p_object); + virtual void parse_category(Object *p_object, const String &p_parse_category); virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage); virtual void parse_end(); }; @@ -249,6 +254,8 @@ class EditorInspector : public ScrollContainer { void _property_changed(const String &p_path, const Variant &p_value); void _multiple_properties_changed(Vector p_paths, Array p_values); void _property_keyed(const String &p_path); + void _property_keyed_with_value(const String &p_path, const Variant &p_value); + void _property_checked(const String &p_path, bool p_checked); void _resource_selected(const String &p_path, RES p_resource); @@ -261,6 +268,7 @@ class EditorInspector : public ScrollContainer { void _edit_request_change(Object *p_changed, const String &p_prop); void _filter_changed(const String &p_text); + void _parse_added_editors(VBoxContainer *current_vbox, Ref ped); protected: static void _bind_methods(); @@ -281,6 +289,7 @@ public: void refresh(); void edit(Object *p_object); + Object *get_edited_object(); void set_keying(bool p_active); void set_read_only(bool p_read_only); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 49f70e3215..2256c6fa85 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -324,7 +324,7 @@ void EditorNode::_notification(int p_what) { } if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); + scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); Ref theme = create_editor_theme(theme_base->get_theme()); theme_base->set_theme(theme); @@ -343,8 +343,8 @@ void EditorNode::_notification(int p_what) { settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); - if (bool(EDITOR_DEF("interface/scene_tabs/resize_if_many_tabs", true))) { - scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE); + if (EDITOR_GET("interface/scene_tabs/resize_if_many_tabs")) { + scene_tabs->set_min_width(int(EDITOR_GET("interface/scene_tabs/minimum_width")) * EDSCALE); } else { scene_tabs->set_min_width(0); } @@ -1527,7 +1527,7 @@ void EditorNode::_edit_current() { object_menu->set_disabled(true); - bool capitalize = bool(EDITOR_DEF("interface/editor/capitalize_properties", true)); + bool capitalize = bool(EDITOR_GET("interface/inspector/capitalize_properties")); bool is_resource = current_obj->is_class("Resource"); bool is_node = current_obj->is_class("Node"); resource_save_button->set_disabled(!is_resource); @@ -1796,7 +1796,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { } } - if (bool(EDITOR_DEF("run/auto_save/save_before_running", true))) { + if (bool(EDITOR_GET("run/auto_save/save_before_running"))) { if (unsaved_cache) { @@ -1823,11 +1823,11 @@ void EditorNode::_run(bool p_current, const String &p_custom) { if (!call_build()) return; - if (bool(EDITOR_DEF("run/output/always_clear_output_on_play", true))) { + if (bool(EDITOR_GET("run/output/always_clear_output_on_play"))) { log->clear(); } - if (bool(EDITOR_DEF("run/output/always_open_output_on_play", true))) { + if (bool(EDITOR_GET("run/output/always_open_output_on_play"))) { make_bottom_panel_item_visible(log); } @@ -2326,7 +2326,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons")); stop_button->set_disabled(true); - if (bool(EDITOR_DEF("run/output/always_close_output_on_stop", true))) { + if (bool(EDITOR_GET("run/output/always_close_output_on_stop"))) { for (int i = 0; i < bottom_panel_items.size(); i++) { if (bottom_panel_items[i].control == log) { _bottom_panel_switch(false, i); @@ -2346,7 +2346,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_PLAY_NATIVE: { - bool autosave = EDITOR_DEF("run/auto_save/save_before_running", true); + bool autosave = EDITOR_GET("run/auto_save/save_before_running"); if (autosave) { _menu_option_confirm(FILE_SAVE_ALL_SCENES, false); } @@ -2372,10 +2372,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case RUN_PROJECT_MANAGER: { if (!p_confirmed) { - bool save_each = EDITOR_DEF("interface/editor/save_each_scene_on_quit", true); + bool save_each = EDITOR_GET("interface/editor/save_each_scene_on_quit"); if (_next_unsaved_scene(!save_each) == -1) { - bool confirm = EDITOR_DEF("interface/editor/quit_confirmation", true); + bool confirm = EDITOR_GET("interface/editor/quit_confirmation"); if (confirm) { confirmation->get_ok()->set_text(p_option == FILE_QUIT ? TTR("Quit") : TTR("Yes")); @@ -4044,7 +4044,7 @@ void EditorNode::_load_docks_from_config(Ref p_layout, const String } void EditorNode::_load_open_scenes_from_config(Ref p_layout, const String &p_section) { - if (!bool(EDITOR_DEF("interface/scene_tabs/restore_scenes_on_load", false))) { + if (!bool(EDITOR_GET("interface/scene_tabs/restore_scenes_on_load"))) { return; } @@ -4166,7 +4166,7 @@ void EditorNode::_scene_tab_closed(int p_tab) { } void EditorNode::_scene_tab_hover(int p_tab) { - if (bool(EDITOR_DEF("interface/scene_tabs/show_thumbnail_on_hover", true)) == false) { + if (bool(EDITOR_GET("interface/scene_tabs/show_thumbnail_on_hover")) == false) { return; } int current_tab = scene_tabs->get_current_tab(); @@ -5042,6 +5042,22 @@ EditorNode::EditorNode() { ClassDB::set_class_enabled("CollisionShape2D", true); ClassDB::set_class_enabled("CollisionPolygon2D", true); + //defs here, use EDITOR_GET in logic + EDITOR_DEF("interface/scene_tabs/always_show_close_button", false); + EDITOR_DEF("interface/scene_tabs/resize_if_many_tabs", true); + EDITOR_DEF("interface/scene_tabs/minimum_width", 50); + EDITOR_DEF("run/output/always_clear_output_on_play", true); + EDITOR_DEF("run/output/always_open_output_on_play", true); + EDITOR_DEF("run/output/always_close_output_on_stop", true); + EDITOR_DEF("run/auto_save/save_before_running", true); + EDITOR_DEF("interface/editor/save_each_scene_on_quit", true); + EDITOR_DEF("interface/editor/quit_confirmation", true); + EDITOR_DEF("interface/scene_tabs/restore_scenes_on_load", false); + EDITOR_DEF("interface/scene_tabs/show_thumbnail_on_hover", true); + EDITOR_DEF("interface/inspector/capitalize_properties", true); + EDITOR_DEF("interface/inspector/open_resources_in_new_inspector", false); + EDITOR_DEF("run/auto_save/save_before_running", true); + theme_base = memnew(Control); add_child(theme_base); theme_base->set_anchors_and_margins_preset(Control::PRESET_WIDE); @@ -5679,8 +5695,8 @@ EditorNode::EditorNode() { inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); inspector->set_use_doc_hints(true); inspector->set_hide_script(false); - inspector->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true))); - inspector->set_use_folding(!bool(EDITOR_DEF("interface/editor/disable_inspector_folding", false))); + inspector->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/inspector/capitalize_properties", true))); + inspector->set_use_folding(!bool(EDITOR_DEF("interface/inspector/disable_inspector_folding", false))); // inspector->hide_top_label(); inspector->register_text_enter(search_box); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 2e4e887165..674c3ecc2b 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -659,6 +659,14 @@ void EditorPlugin::remove_export_plugin(const Ref &p_exporte EditorExport::get_singleton()->remove_export_plugin(p_exporter); } +void EditorPlugin::add_inspector_plugin(const Ref &p_plugin) { + EditorInspector::add_inspector_plugin(p_plugin); +} + +void EditorPlugin::remove_inspector_plugin(const Ref &p_plugin) { + EditorInspector::remove_inspector_plugin(p_plugin); +} + void EditorPlugin::add_scene_import_plugin(const Ref &p_importer) { ResourceImporterScene::get_singleton()->add_importer(p_importer); } @@ -728,8 +736,10 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_import_plugin", "importer"), &EditorPlugin::remove_import_plugin); ClassDB::bind_method(D_METHOD("add_scene_import_plugin", "scene_importer"), &EditorPlugin::add_scene_import_plugin); ClassDB::bind_method(D_METHOD("remove_scene_import_plugin", "scene_importer"), &EditorPlugin::remove_scene_import_plugin); - ClassDB::bind_method(D_METHOD("add_export_plugin", "exporter"), &EditorPlugin::add_export_plugin); - ClassDB::bind_method(D_METHOD("remove_export_plugin", "exporter"), &EditorPlugin::remove_export_plugin); + ClassDB::bind_method(D_METHOD("add_export_plugin", "plugin"), &EditorPlugin::add_export_plugin); + ClassDB::bind_method(D_METHOD("remove_export_plugin", "plugin"), &EditorPlugin::remove_export_plugin); + ClassDB::bind_method(D_METHOD("add_inspector_plugin", "plugin"), &EditorPlugin::add_inspector_plugin); + ClassDB::bind_method(D_METHOD("remove_inspector_plugin", "plugin"), &EditorPlugin::remove_inspector_plugin); ClassDB::bind_method(D_METHOD("set_input_event_forwarding_always_enabled"), &EditorPlugin::set_input_event_forwarding_always_enabled); ClassDB::bind_method(D_METHOD("set_force_draw_over_forwarding_enabled"), &EditorPlugin::set_force_draw_over_forwarding_enabled); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index ebc4afdfeb..8af7f83771 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -31,6 +31,7 @@ #ifndef EDITOR_PLUGIN_H #define EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/import/editor_import_plugin.h" #include "editor/import/resource_importer_scene.h" #include "io/config_file.h" @@ -210,6 +211,9 @@ public: void add_export_plugin(const Ref &p_exporter); void remove_export_plugin(const Ref &p_exporter); + void add_inspector_plugin(const Ref &p_plugin); + void remove_inspector_plugin(const Ref &p_plugin); + void add_scene_import_plugin(const Ref &p_importer); void remove_scene_import_plugin(const Ref &p_importer); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index f3397d7980..bc9ddd6be8 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -118,8 +118,8 @@ void EditorPropertyMultilineText::_bind_methods() { EditorPropertyMultilineText::EditorPropertyMultilineText() { HBoxContainer *hb = memnew(HBoxContainer); - set_label_layout(LABEL_LAYOUT_TOP); add_child(hb); + set_bottom_editor(hb); text = memnew(TextEdit); text->connect("text_changed", this, "_text_changed"); add_focusable(text); @@ -622,6 +622,7 @@ void EditorPropertyLayers::_button_pressed() { } Rect2 gp = button->get_global_rect(); + layers->set_as_minsize(); Vector2 popup_pos = gp.position - Vector2(layers->get_combined_minimum_size().x, 0); layers->set_global_position(popup_pos); layers->popup(); @@ -656,7 +657,7 @@ EditorPropertyLayers::EditorPropertyLayers() { button->set_text(".."); button->connect("pressed", this, "_button_pressed"); hb->add_child(button); - set_label_layout(LABEL_LAYOUT_TOP); + set_bottom_editor(hb); layers = memnew(PopupMenu); add_child(layers); layers->connect("id_pressed", this, "_menu_pressed"); @@ -1267,8 +1268,7 @@ EditorPropertyAABB::EditorPropertyAABB() { add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); } - set_label_reference(spin[0]); //show text and buttons around this - set_label_layout(LABEL_LAYOUT_TOP); + set_bottom_editor(g); setting = false; } @@ -1330,8 +1330,7 @@ EditorPropertyTransform2D::EditorPropertyTransform2D() { add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); } - set_label_reference(spin[0]); //show text and buttons around this - set_label_layout(LABEL_LAYOUT_TOP); + set_bottom_editor(g); setting = false; } @@ -1399,8 +1398,7 @@ EditorPropertyBasis::EditorPropertyBasis() { add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); } - set_label_reference(spin[0]); //show text and buttons around this - set_label_layout(LABEL_LAYOUT_TOP); + set_bottom_editor(g); setting = false; } @@ -1474,8 +1472,7 @@ EditorPropertyTransform::EditorPropertyTransform() { add_focusable(spin[i]); spin[i]->connect("value_changed", this, "_value_changed"); } - set_label_reference(spin[0]); //show text and buttons around this - set_label_layout(LABEL_LAYOUT_TOP); + set_bottom_editor(g); setting = false; } @@ -1952,23 +1949,75 @@ void EditorPropertyResource::_update_menu() { } } - Rect2 gt = get_global_rect(); + Rect2 gt = edit->get_global_rect(); + menu->set_as_minsize(); int ms = menu->get_combined_minimum_size().width; Vector2 popup_pos = gt.position + gt.size - Vector2(ms, 0); - menu->set_position(popup_pos); + menu->set_global_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); +} + +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); +} + +void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) { + + emit_signal("object_id_selected", get_edited_property(), p_id); +} + 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()); + } +#ifdef TOOLS_ENABLED + if (res.is_valid() && get_edited_object()->editor_is_section_unfolded(get_edited_property())) { + + if (!sub_inspector) { + sub_inspector = memnew(EditorInspector); + sub_inspector->set_enable_v_scroll(false); + + sub_inspector->connect("property_keyed", this, "_sub_inspector_property_keyed"); + sub_inspector->connect("resource_selected", this, "_sub_inspector_resource_selected"); + sub_inspector->connect("object_id_selected", this, "_sub_inspector_object_id_selected"); + sub_inspector->set_keying(is_keying()); + sub_inspector->set_read_only(is_read_only()); + sub_inspector->set_use_folding(is_using_folding()); + + add_child(sub_inspector); + set_bottom_editor(sub_inspector); + assign->set_pressed(true); + } + + if (res.ptr() != sub_inspector->get_edited_object()) { + sub_inspector->edit(res.ptr()); + } + + } else { + if (sub_inspector) { + set_bottom_editor(NULL); + memdelete(sub_inspector); + sub_inspector = NULL; + } + } +#endif + } + if (res == RES()) { assign->set_icon(Ref()); assign->set_text(TTR("[empty]")); - assign->set_disabled(true); } else { - assign->set_disabled(false); Ref icon; if (has_icon(res->get_class(), "EditorIcons")) @@ -1999,7 +2048,16 @@ void EditorPropertyResource::update_property() { void EditorPropertyResource::_resource_selected() { RES res = get_edited_object()->get(get_edited_property()); - if (!res.is_null()) { + if (res.is_null()) { + _update_menu(); + return; + } + + if (use_sub_inspector) { + + get_edited_object()->editor_set_section_unfold(get_edited_property(), assign->is_pressed()); + update_property(); + } else { emit_signal("resource_selected", get_edited_property(), res); } @@ -2033,6 +2091,20 @@ void EditorPropertyResource::_viewport_selected(const NodePath &p_path) { emit_signal("property_changed", get_edited_property(), vt); update_property(); } + +void EditorPropertyResource::collapse_all_folding() { + if (sub_inspector) { + sub_inspector->collapse_all_folding(); + } +} + +void EditorPropertyResource::expand_all_folding() { + + if (sub_inspector) { + sub_inspector->expand_all_folding(); + } +} + void EditorPropertyResource::_bind_methods() { ClassDB::bind_method(D_METHOD("_file_selected"), &EditorPropertyResource::_file_selected); @@ -2041,10 +2113,15 @@ void EditorPropertyResource::_bind_methods() { ClassDB::bind_method(D_METHOD("_resource_preview"), &EditorPropertyResource::_resource_preview); ClassDB::bind_method(D_METHOD("_resource_selected"), &EditorPropertyResource::_resource_selected); ClassDB::bind_method(D_METHOD("_viewport_selected"), &EditorPropertyResource::_viewport_selected); + ClassDB::bind_method(D_METHOD("_sub_inspector_property_keyed"), &EditorPropertyResource::_sub_inspector_property_keyed); + ClassDB::bind_method(D_METHOD("_sub_inspector_resource_selected"), &EditorPropertyResource::_sub_inspector_resource_selected); + ClassDB::bind_method(D_METHOD("_sub_inspector_object_id_selected"), &EditorPropertyResource::_sub_inspector_object_id_selected); } EditorPropertyResource::EditorPropertyResource() { + sub_inspector = NULL; + use_sub_inspector = !bool(EDITOR_GET("interface/inspector/open_resources_in_new_inspector")); HBoxContainer *hbc = memnew(HBoxContainer); add_child(hbc); assign = memnew(Button); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index cf0c735b37..7cd94f25f8 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -481,7 +481,9 @@ class EditorPropertyResource : public EditorProperty { PopupMenu *menu; EditorFileDialog *file; Vector inheritors_array; + EditorInspector *sub_inspector; + bool use_sub_inspector; String base_type; SceneTreeDialog *scene_tree; @@ -494,6 +496,10 @@ class EditorPropertyResource : public EditorProperty { void _update_menu(); + void _sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool); + void _sub_inspector_resource_selected(const RES &p_resource, const String &p_property); + void _sub_inspector_object_id_selected(int p_id); + protected: static void _bind_methods(); void _notification(int p_what); @@ -501,6 +507,10 @@ protected: public: virtual void update_property(); void setup(const String &p_base_type); + + void collapse_all_folding(); + void expand_all_folding(); + EditorPropertyResource(); }; diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp index b624d69810..672337ba2f 100644 --- a/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp @@ -42,6 +42,7 @@ void CollisionPolygon2DEditor::_set_node(Node *p_polygon) { CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) : AbstractPolygon2DEditor(p_editor) { + node = NULL; } CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) : diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 7c49408c35..29720b3cdb 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -91,7 +91,7 @@ void CurveEditor::set_curve(Ref curve) { } Size2 CurveEditor::get_minimum_size() const { - return Vector2(64, 64); + return Vector2(64, 150) * EDSCALE; } void CurveEditor::_notification(int p_what) { @@ -639,7 +639,7 @@ void CurveEditor::_draw() { Ref font = get_font("font", "Label"); float font_height = font->get_height(); - const Color text_color = get_color("font_color", "Editor"); + Color text_color = get_color("font_color", "Editor"); { // X axis @@ -720,6 +720,7 @@ void CurveEditor::_draw() { // Help text if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) { + text_color.a *= 0.4; draw_string(font, Vector2(50, font_height), TTR("Hold Shift to edit tangents individually"), text_color); } } @@ -750,89 +751,30 @@ void CurveEditor::_bind_methods() { //--------------- +bool EditorInspectorPluginCurve::can_handle(Object *p_object) { + + return Object::cast_to(p_object) != NULL; +} + +void EditorInspectorPluginCurve::parse_begin(Object *p_object) { + + Curve *curve = Object::cast_to(p_object); + ERR_FAIL_COND(!curve); + Ref c(curve); + + CurveEditor *editor = memnew(CurveEditor); + editor->set_curve(curve); + add_custom_control(editor); +} + CurveEditorPlugin::CurveEditorPlugin(EditorNode *p_node) { - _editor_node = p_node; - - _view = memnew(CurveEditor); - _view->set_custom_minimum_size(Size2(100, 128 * EDSCALE)); - _view->hide(); - - _toggle_button = _editor_node->add_bottom_panel_item(get_name(), _view); - _toggle_button->hide(); + Ref curve_plugin; + curve_plugin.instance(); + EditorInspector::add_inspector_plugin(curve_plugin); get_editor_interface()->get_resource_previewer()->add_preview_generator(memnew(CurvePreviewGenerator)); } -CurveEditorPlugin::~CurveEditorPlugin() { -} - -void CurveEditorPlugin::edit(Object *p_object) { - - Ref curve_ref; - - if (_current_ref.is_valid()) { - CurveTexture *ct = Object::cast_to(*_current_ref); - if (ct) - ct->disconnect(CoreStringNames::get_singleton()->changed, this, "_curve_texture_changed"); - } - - if (p_object) { - Resource *res = Object::cast_to(p_object); - ERR_FAIL_COND(res == NULL); - ERR_FAIL_COND(!handles(p_object)); - - _current_ref = Ref(Object::cast_to(p_object)); - - if (_current_ref.is_valid()) { - Curve *curve = Object::cast_to(*_current_ref); - if (curve) - curve_ref = Ref(curve); - else { - CurveTexture *ct = Object::cast_to(*_current_ref); - if (ct) { - ct->connect(CoreStringNames::get_singleton()->changed, this, "_curve_texture_changed"); - curve_ref = ct->get_curve(); - } - } - } - - } else { - _current_ref = Ref(); - } - - _view->set_curve(curve_ref); -} - -bool CurveEditorPlugin::handles(Object *p_object) const { - // Both handled so that we can keep the curve editor open - return Object::cast_to(p_object) || Object::cast_to(p_object); -} - -void CurveEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - _toggle_button->show(); - _editor_node->make_bottom_panel_item_visible(_view); - } else { - _toggle_button->hide(); - if (_view->is_visible_in_tree()) - _editor_node->hide_bottom_panel(); - } -} - -void CurveEditorPlugin::_curve_texture_changed() { - // If the curve is shown indirectly as a CurveTexture is edited, - // we need to monitor when the curve property gets assigned - CurveTexture *ct = Object::cast_to(*_current_ref); - if (ct) { - _view->set_curve(ct->get_curve()); - } -} - -void CurveEditorPlugin::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_curve_texture_changed"), &CurveEditorPlugin::_curve_texture_changed); -} - //----------------------------------- // Preview generator diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h index 97f1ba2fa1..255f359ed2 100644 --- a/editor/plugins/curve_editor_plugin.h +++ b/editor/plugins/curve_editor_plugin.h @@ -119,28 +119,19 @@ private: float _tangents_length; }; +class EditorInspectorPluginCurve : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginCurve, EditorInspectorPlugin) +public: + virtual bool can_handle(Object *p_object); + virtual void parse_begin(Object *p_object); +}; + class CurveEditorPlugin : public EditorPlugin { GDCLASS(CurveEditorPlugin, EditorPlugin) public: CurveEditorPlugin(EditorNode *p_node); - ~CurveEditorPlugin(); String get_name() const { return "Curve"; } - bool has_main_screen() const { return false; } - void edit(Object *p_object); - bool handles(Object *p_object) const; - void make_visible(bool p_visible); - -private: - static void _bind_methods(); - - void _curve_texture_changed(); - -private: - CurveEditor *_view; - Ref _current_ref; - EditorNode *_editor_node; - ToolButton *_toggle_button; }; class CurvePreviewGenerator : public EditorResourcePreviewGenerator { diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp index e89cb68935..442bd52ea7 100644 --- a/editor/plugins/gradient_editor_plugin.cpp +++ b/editor/plugins/gradient_editor_plugin.cpp @@ -33,77 +33,70 @@ #include "canvas_item_editor_plugin.h" #include "spatial_editor_plugin.h" -GradientEditorPlugin::GradientEditorPlugin(EditorNode *p_node) { +Size2 GradientEditor::get_minimum_size() const { + return Size2(0, 60) * EDSCALE; +} +void GradientEditor::_gradient_changed() { - editor = p_node; - ramp_editor = memnew(GradientEdit); + if (editing) + return; - add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM, ramp_editor); - - ramp_editor->set_custom_minimum_size(Size2(100, 48)); - ramp_editor->hide(); - ramp_editor->connect("ramp_changed", this, "ramp_changed"); + editing = true; + Vector points = gradient->get_points(); + set_points(points); + editing = false; } -void GradientEditorPlugin::edit(Object *p_object) { +void GradientEditor::_ramp_changed() { + + editing = true; + UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); + undo_redo->create_action("Gradient Edited"); + undo_redo->add_do_method(gradient.ptr(), "set_offsets", get_offsets()); + undo_redo->add_do_method(gradient.ptr(), "set_colors", get_colors()); + undo_redo->add_undo_method(gradient.ptr(), "set_offsets", gradient->get_offsets()); + undo_redo->add_undo_method(gradient.ptr(), "set_colors", gradient->get_colors()); + undo_redo->commit_action(); + editing = false; +} + +void GradientEditor::_bind_methods() { + + ClassDB::bind_method("_gradient_changed", &GradientEditor::_gradient_changed); + ClassDB::bind_method("_ramp_changed", &GradientEditor::_ramp_changed); +} + +void GradientEditor::set_gradient(const Ref &p_gradient) { + gradient = p_gradient; + connect("ramp_changed", this, "_ramp_changed"); + gradient->connect("changed", this, "_gradient_changed"); + set_points(gradient->get_points()); +} + +GradientEditor::GradientEditor() { + editing = false; +} + +/////////////////////// + +bool EditorInspectorPluginGradient::can_handle(Object *p_object) { + + return Object::cast_to(p_object) != NULL; +} + +void EditorInspectorPluginGradient::parse_begin(Object *p_object) { Gradient *gradient = Object::cast_to(p_object); - if (!gradient) - return; - gradient_ref = Ref(gradient); - ramp_editor->set_points(gradient_ref->get_points()); + Ref g(gradient); + + GradientEditor *editor = memnew(GradientEditor); + editor->set_gradient(g); + add_custom_control(editor); } -bool GradientEditorPlugin::handles(Object *p_object) const { +GradientEditorPlugin::GradientEditorPlugin(EditorNode *p_node) { - return p_object->is_class("Gradient"); -} - -void GradientEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - ramp_editor->show(); - } else { - ramp_editor->hide(); - } -} - -void GradientEditorPlugin::_ramp_changed() { - - if (gradient_ref.is_valid()) { - - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - - //Not sure if I should convert this data to PoolVector - Vector new_offsets = ramp_editor->get_offsets(); - Vector new_colors = ramp_editor->get_colors(); - Vector old_offsets = gradient_ref->get_offsets(); - Vector old_colors = gradient_ref->get_colors(); - - if (old_offsets.size() != new_offsets.size()) - ur->create_action(TTR("Add/Remove Color Ramp Point")); - else - ur->create_action(TTR("Modify Color Ramp"), UndoRedo::MERGE_ENDS); - ur->add_do_method(this, "undo_redo_gradient", new_offsets, new_colors); - ur->add_undo_method(this, "undo_redo_gradient", old_offsets, old_colors); - ur->commit_action(); - - //color_ramp_ref->set_points(ramp_editor->get_points()); - } -} - -void GradientEditorPlugin::_undo_redo_gradient(const Vector &offsets, const Vector &colors) { - - gradient_ref->set_offsets(offsets); - gradient_ref->set_colors(colors); - ramp_editor->set_points(gradient_ref->get_points()); - ramp_editor->update(); -} - -GradientEditorPlugin::~GradientEditorPlugin() { -} - -void GradientEditorPlugin::_bind_methods() { - ClassDB::bind_method(D_METHOD("ramp_changed"), &GradientEditorPlugin::_ramp_changed); - ClassDB::bind_method(D_METHOD("undo_redo_gradient", "offsets", "colors"), &GradientEditorPlugin::_undo_redo_gradient); + Ref plugin; + plugin.instance(); + add_inspector_plugin(plugin); } diff --git a/editor/plugins/gradient_editor_plugin.h b/editor/plugins/gradient_editor_plugin.h index 52f4c59575..0c878b168f 100644 --- a/editor/plugins/gradient_editor_plugin.h +++ b/editor/plugins/gradient_editor_plugin.h @@ -35,28 +35,39 @@ #include "editor/editor_plugin.h" #include "scene/gui/gradient_edit.h" +class GradientEditor : public GradientEdit { + GDCLASS(GradientEditor, GradientEdit) + + bool editing; + Ref gradient; + + void _gradient_changed(); + void _ramp_changed(); + +protected: + static void _bind_methods(); + +public: + virtual Size2 get_minimum_size() const; + void set_gradient(const Ref &p_gradient); + GradientEditor(); +}; + +class EditorInspectorPluginGradient : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginGradient, EditorInspectorPlugin) +public: + virtual bool can_handle(Object *p_object); + virtual void parse_begin(Object *p_object); +}; + class GradientEditorPlugin : public EditorPlugin { GDCLASS(GradientEditorPlugin, EditorPlugin); - Ref gradient_ref; - GradientEdit *ramp_editor; - EditorNode *editor; - -protected: - static void _bind_methods(); - void _ramp_changed(); - void _undo_redo_gradient(const Vector &offsets, const Vector &colors); - public: virtual String get_name() const { return "ColorRamp"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); GradientEditorPlugin(EditorNode *p_node); - ~GradientEditorPlugin(); }; #endif /* TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ */ diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp index 47d5a73078..ba6452c1d1 100644 --- a/editor/plugins/line_2d_editor_plugin.cpp +++ b/editor/plugins/line_2d_editor_plugin.cpp @@ -64,6 +64,7 @@ void Line2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, con Line2DEditor::Line2DEditor(EditorNode *p_editor) : AbstractPolygon2DEditor(p_editor) { + node = NULL; } Line2DEditorPlugin::Line2DEditorPlugin(EditorNode *p_node) : diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp index d1edf1ae10..0332e15b0e 100644 --- a/editor/plugins/navigation_polygon_editor_plugin.cpp +++ b/editor/plugins/navigation_polygon_editor_plugin.cpp @@ -123,6 +123,7 @@ void NavigationPolygonEditor::_create_resource() { NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) : AbstractPolygon2DEditor(p_editor) { + node = NULL; } NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) : diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index f04e0a801c..ed41e1931e 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -1035,6 +1035,7 @@ Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const { Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : AbstractPolygon2DEditor(p_editor) { + node = NULL; snap_step = Vector2(10, 10); use_snap = false; snap_show_grid = false; diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp index f4faab69ed..f6d98cb4c7 100644 --- a/editor/plugins/style_box_editor_plugin.cpp +++ b/editor/plugins/style_box_editor_plugin.cpp @@ -30,7 +30,26 @@ #include "style_box_editor_plugin.h" -void StyleBoxEditor::edit(const Ref &p_stylebox) { +bool EditorInspectorPluginStyleBox::can_handle(Object *p_object) { + + return Object::cast_to(p_object) != NULL; +} + +void EditorInspectorPluginStyleBox::parse_begin(Object *p_object) { + + Ref sb = Ref(Object::cast_to(p_object)); + + StyleBoxPreview *preview = memnew(StyleBoxPreview); + preview->edit(sb); + add_custom_control(preview); +} +bool EditorInspectorPluginStyleBox::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) { + return false; //do not want +} +void EditorInspectorPluginStyleBox::parse_end() { +} + +void StyleBoxPreview::edit(const Ref &p_stylebox) { if (stylebox.is_valid()) stylebox->disconnect("changed", this, "_sb_changed"); @@ -39,71 +58,33 @@ void StyleBoxEditor::edit(const Ref &p_stylebox) { preview->add_style_override("panel", stylebox); stylebox->connect("changed", this, "_sb_changed"); } + _sb_changed(); } -void StyleBoxEditor::_sb_changed() { +void StyleBoxPreview::_sb_changed() { preview->update(); + if (stylebox.is_valid()) { + Size2 ms = stylebox->get_minimum_size() * 4 / 3; + ms.height = MAX(ms.height, 150 * EDSCALE); + preview->set_custom_minimum_size(ms); + } } -void StyleBoxEditor::_bind_methods() { +void StyleBoxPreview::_bind_methods() { - ClassDB::bind_method("_sb_changed", &StyleBoxEditor::_sb_changed); - //ClassDB::bind_method("_import",&StyleBoxEditor::_import); - //ClassDB::bind_method("_import_accept",&StyleBoxEditor::_import_accept); - //ClassDB::bind_method("_preview_text_changed",&StyleBoxEditor::_preview_text_changed); + ClassDB::bind_method("_sb_changed", &StyleBoxPreview::_sb_changed); } -StyleBoxEditor::StyleBoxEditor() { - - panel = memnew(Panel); - add_child(panel); - panel->set_anchors_and_margins_preset(Control::PRESET_WIDE); - - Label *l = memnew(Label); - l->set_text(TTR("StyleBox Preview:")); - l->set_position(Point2(5, 5)); - panel->add_child(l); +StyleBoxPreview::StyleBoxPreview() { preview = memnew(Panel); - panel->add_child(preview); - preview->set_position(Point2(50, 50)); - preview->set_size(Size2(200, 100)); -} - -void StyleBoxEditorPlugin::edit(Object *p_node) { - - if (Object::cast_to(p_node)) { - stylebox_editor->edit(Object::cast_to(p_node)); - stylebox_editor->show(); - } else - stylebox_editor->hide(); -} - -bool StyleBoxEditorPlugin::handles(Object *p_node) const { - - return p_node->is_class("StyleBox"); -} - -void StyleBoxEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - button->show(); - EditorNode::get_singleton()->make_bottom_panel_item_visible(stylebox_editor); - - } else { - if (stylebox_editor->is_visible_in_tree()) - EditorNode::get_singleton()->hide_bottom_panel(); - button->hide(); - } + add_margin_child(TTR("Preview:"), preview); } StyleBoxEditorPlugin::StyleBoxEditorPlugin(EditorNode *p_node) { - stylebox_editor = memnew(StyleBoxEditor); - stylebox_editor->set_custom_minimum_size(Size2(0, 250)); - - //p_node->get_viewport()->add_child(stylebox_editor); - button = p_node->add_bottom_panel_item(TTR("StyleBox"), stylebox_editor); - button->hide(); + Ref inspector_plugin; + inspector_plugin.instance(); + add_inspector_plugin(inspector_plugin); } diff --git a/editor/plugins/style_box_editor_plugin.h b/editor/plugins/style_box_editor_plugin.h index 34d8caaeb6..6b0d7e57a8 100644 --- a/editor/plugins/style_box_editor_plugin.h +++ b/editor/plugins/style_box_editor_plugin.h @@ -31,18 +31,17 @@ #ifndef STYLE_BOX_EDITOR_PLUGIN_H #define STYLE_BOX_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "scene/gui/option_button.h" #include "scene/gui/texture_rect.h" #include "scene/resources/style_box.h" -class StyleBoxEditor : public Control { +class StyleBoxPreview : public VBoxContainer { - GDCLASS(StyleBoxEditor, Control); + GDCLASS(StyleBoxPreview, VBoxContainer); - Panel *panel; Panel *preview; - Ref stylebox; void _sb_changed(); @@ -53,23 +52,24 @@ protected: public: void edit(const Ref &p_stylebox); - StyleBoxEditor(); + StyleBoxPreview(); +}; + +class EditorInspectorPluginStyleBox : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginStyleBox, EditorInspectorPlugin) +public: + virtual bool can_handle(Object *p_object); + virtual void parse_begin(Object *p_object); + virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage); + virtual void parse_end(); }; class StyleBoxEditorPlugin : public EditorPlugin { GDCLASS(StyleBoxEditorPlugin, EditorPlugin); - StyleBoxEditor *stylebox_editor; - EditorNode *editor; - Button *button; - public: virtual String get_name() const { return "StyleBox"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_node); - virtual bool handles(Object *p_node) const; - virtual void make_visible(bool p_visible); StyleBoxEditorPlugin(EditorNode *p_node); }; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 5ba3931689..e4fdd1f251 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -601,6 +601,17 @@ void TextureRegionEditor::apply_rect(const Rect2 &rect) { void TextureRegionEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_PROCESS: { + if (node_sprite) { + if (node_sprite->is_region()) { + + set_process(false); + EditorNode::get_singleton()->make_bottom_panel_item_visible(this); + } + } else { + set_process(false); + } + } break; case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_READY: { zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons")); @@ -640,6 +651,23 @@ void TextureRegionEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_zoom_out"), &TextureRegionEditor::_zoom_out); } +bool TextureRegionEditor::is_stylebox() { + return obj_styleBox.is_valid(); +} + +bool TextureRegionEditor::is_atlas_texture() { + + return atlas_tex.is_valid(); +} + +bool TextureRegionEditor::is_ninepatch() { + return node_ninepatch != NULL; +} + +Sprite *TextureRegionEditor::get_sprite() { + return node_sprite; +} + void TextureRegionEditor::edit(Object *p_obj) { if (node_sprite) node_sprite->remove_change_receptor(this); @@ -670,6 +698,12 @@ void TextureRegionEditor::edit(Object *p_obj) { tile_set = Ref(NULL); } edit_draw->update(); + if (node_sprite && !node_sprite->is_region()) { + set_process(true); + } + if (!p_obj) { + set_process(false); + } } void TextureRegionEditor::_changed_callback(Object *p_changed, const char *p_prop) { @@ -932,8 +966,12 @@ bool TextureRegionEditorPlugin::handles(Object *p_object) const { void TextureRegionEditorPlugin::make_visible(bool p_visible) { if (p_visible) { texture_region_button->show(); - if (texture_region_button->is_pressed()) - region_editor->show(); + if (region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region())) { + editor->make_bottom_panel_item_visible(region_editor); + } else { + if (texture_region_button->is_pressed()) + region_editor->show(); + } } else { texture_region_button->hide(); region_editor->edit(NULL); @@ -989,10 +1027,10 @@ TextureRegionEditorPlugin::TextureRegionEditorPlugin(EditorNode *p_node) { editor = p_node; region_editor = memnew(TextureRegionEditor(p_node)); - texture_region_button = p_node->add_bottom_panel_item(TTR("Texture Region"), region_editor); + texture_region_button = p_node->add_bottom_panel_item(TTR("TextureRegion"), region_editor); texture_region_button->set_tooltip(TTR("Texture Region Editor")); - region_editor->set_custom_minimum_size(Size2(0, 200)); + region_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); region_editor->hide(); texture_region_button->hide(); } diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index 1244953a3f..eeba1987a6 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -131,6 +131,10 @@ public: void _region_draw(); void _region_input(const Ref &p_input); void _scroll_changed(float); + bool is_stylebox(); + bool is_atlas_texture(); + bool is_ninepatch(); + Sprite *get_sprite(); void edit(Object *p_obj); TextureRegionEditor(EditorNode *p_editor); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 08338b0b2d..b82a036130 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1936,6 +1936,12 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); } + + if (selection.size() > 1) { + //this is not a commonly used action, it makes no sense for it to be where it was nor always present. + menu->add_separator(); + menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME); + } menu->add_separator(); menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE); menu->set_size(Size2(1, 1)); diff --git a/scene/3d/scenario_fx.cpp b/scene/3d/scenario_fx.cpp index d5bff676cb..26cbfc0b11 100644 --- a/scene/3d/scenario_fx.cpp +++ b/scene/3d/scenario_fx.cpp @@ -93,9 +93,10 @@ String WorldEnvironment::get_configuration_warning() const { return TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes)."); } - if (environment.is_valid() && get_viewport() && !get_viewport()->get_camera() && environment->get_background() != Environment::BG_CANVAS) { - return TTR("This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set this environment's Background Mode to Canvas (for 2D scenes)."); - } + // Commenting this warning for now, I think it makes no sense. If anyone can figure out what its supposed to do, feedback welcome. Else it should be deprecated. + //if (environment.is_valid() && get_viewport() && !get_viewport()->get_camera() && environment->get_background() != Environment::BG_CANVAS) { + // return TTR("This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set this environment's Background Mode to Canvas (for 2D scenes)."); + //} return String(); } diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 177582c87c..7df03bf7c6 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -51,6 +51,8 @@ void Container::add_child_notify(Node *p_child) { control->connect("size_flags_changed", this, "queue_sort"); control->connect("minimum_size_changed", this, "_child_minsize_changed"); control->connect("visibility_changed", this, "_child_minsize_changed"); + + minimum_size_changed(); queue_sort(); } @@ -61,6 +63,7 @@ void Container::move_child_notify(Node *p_child) { if (!Object::cast_to(p_child)) return; + minimum_size_changed(); queue_sort(); } @@ -75,6 +78,8 @@ void Container::remove_child_notify(Node *p_child) { control->disconnect("size_flags_changed", this, "queue_sort"); control->disconnect("minimum_size_changed", this, "_child_minsize_changed"); control->disconnect("visibility_changed", this, "_child_minsize_changed"); + + minimum_size_changed(); queue_sort(); } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 3097ecaf16..d07b5a9f65 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -277,6 +277,7 @@ void Control::_update_minimum_size() { data.updating_last_minimum_size = false; if (minsize != data.last_minimum_size) { + data.last_minimum_size = minsize; emit_signal(SceneStringNames::get_singleton()->minimum_size_changed); } } diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 9fc8e98a7f..b5622604e2 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -147,6 +147,7 @@ void GradientEdit::_gui_input(const Ref &p_event) { grabbed = _get_point_from_pos(x); //grab or select if (grabbed != -1) { + grabbed = false; return; } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index fd2466407e..93865cebde 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -533,6 +533,7 @@ void PopupMenu::add_icon_item(const Ref &p_icon, const String &p_label, item.ID = p_ID; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_item(const String &p_label, int p_ID, uint32_t p_accel) { @@ -543,6 +544,7 @@ void PopupMenu::add_item(const String &p_label, int p_ID, uint32_t p_accel) { item.ID = p_ID; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, int p_ID) { @@ -554,6 +556,7 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, item.submenu = p_submenu; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_icon_check_item(const Ref &p_icon, const String &p_label, int p_ID, uint32_t p_accel) { @@ -567,6 +570,7 @@ void PopupMenu::add_icon_check_item(const Ref &p_icon, const String &p_ item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_check_item(const String &p_label, int p_ID, uint32_t p_accel) { @@ -579,6 +583,7 @@ void PopupMenu::add_check_item(const String &p_label, int p_ID, uint32_t p_accel item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_radio_check_item(const String &p_label, int p_ID, uint32_t p_accel) { @@ -586,6 +591,7 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_ID, uint32_t p add_check_item(p_label, p_ID, p_accel); items[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; update(); + minimum_size_changed(); } void PopupMenu::add_icon_radio_check_item(const Ref &p_icon, const String &p_label, int p_ID, uint32_t p_accel) { @@ -593,6 +599,7 @@ void PopupMenu::add_icon_radio_check_item(const Ref &p_icon, const Stri add_icon_check_item(p_icon, p_label, p_ID, p_accel); items[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; update(); + minimum_size_changed(); } void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_ID, bool p_global) { @@ -608,6 +615,7 @@ void PopupMenu::add_icon_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_ID, bool p_global) { @@ -622,6 +630,7 @@ void PopupMenu::add_shortcut(const Ref &p_shortcut, int p_ID, bool p_g item.shortcut_is_global = p_global; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_icon_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_ID, bool p_global) { @@ -638,6 +647,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref &p_icon, const Ref &p_shortcut, int p_ID, bool p_global) { @@ -653,6 +663,7 @@ void PopupMenu::add_check_shortcut(const Ref &p_shortcut, int p_ID, bo item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_radio_check_shortcut(const Ref &p_shortcut, int p_ID, bool p_global) { @@ -660,6 +671,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref &p_shortcut, int p_ add_check_shortcut(p_shortcut, p_ID, p_global); items[items.size() - 1].checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; update(); + minimum_size_changed(); } void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_ID, uint32_t p_accel) { @@ -673,6 +685,7 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int item.state = p_default_state; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::set_item_text(int p_idx, const String &p_text) { @@ -682,6 +695,7 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) { items[p_idx].xl_text = tr(p_text); update(); + minimum_size_changed(); } void PopupMenu::set_item_icon(int p_idx, const Ref &p_icon) { @@ -689,6 +703,7 @@ void PopupMenu::set_item_icon(int p_idx, const Ref &p_icon) { items[p_idx].icon = p_icon; update(); + minimum_size_changed(); } void PopupMenu::set_item_checked(int p_idx, bool p_checked) { @@ -697,6 +712,7 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) { items[p_idx].checked = p_checked; update(); + minimum_size_changed(); } void PopupMenu::set_item_id(int p_idx, int p_ID) { @@ -704,6 +720,7 @@ void PopupMenu::set_item_id(int p_idx, int p_ID) { items[p_idx].ID = p_ID; update(); + minimum_size_changed(); } void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) { @@ -712,6 +729,7 @@ void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) { items[p_idx].accel = p_accel; update(); + minimum_size_changed(); } void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) { @@ -719,6 +737,7 @@ void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) { ERR_FAIL_INDEX(p_idx, items.size()); items[p_idx].metadata = p_meta; update(); + minimum_size_changed(); } void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) { @@ -726,6 +745,7 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) { ERR_FAIL_INDEX(p_idx, items.size()); items[p_idx].disabled = p_disabled; update(); + minimum_size_changed(); } void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) { @@ -733,6 +753,7 @@ void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) { ERR_FAIL_INDEX(p_idx, items.size()); items[p_idx].submenu = p_submenu; update(); + minimum_size_changed(); } void PopupMenu::toggle_item_checked(int p_idx) { @@ -740,6 +761,7 @@ void PopupMenu::toggle_item_checked(int p_idx) { ERR_FAIL_INDEX(p_idx, items.size()); items[p_idx].checked = !items[p_idx].checked; update(); + minimum_size_changed(); } String PopupMenu::get_item_text(int p_idx) const { @@ -881,6 +903,7 @@ void PopupMenu::set_item_h_offset(int p_idx, int p_offset) { ERR_FAIL_INDEX(p_idx, items.size()); items[p_idx].h_ofs = p_offset; update(); + minimum_size_changed(); } void PopupMenu::set_item_multistate(int p_idx, int p_state) { @@ -1045,6 +1068,7 @@ void PopupMenu::clear() { items.clear(); mouse_over = -1; update(); + minimum_size_changed(); } Array PopupMenu::_get_items() const { diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 7da65ac984..ebad00b068 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -136,8 +136,17 @@ Ref StyleBoxTexture::get_normal_map() const { void StyleBoxTexture::set_margin_size(Margin p_margin, float p_size) { + ERR_FAIL_INDEX(p_margin, 4); + margin[p_margin] = p_size; emit_changed(); + static const char *margin_prop[4] = { + "content_margin_left", + "content_margin_top", + "content_margin_right", + "content_margin_bottom", + }; + _change_notify(margin_prop[p_margin]); } float StyleBoxTexture::get_margin_size(Margin p_margin) const {