diff options
36 files changed, 1477 insertions, 951 deletions
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 38e74c126e..c2d2f7ddcc 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 +// replace property editor in sectionedpropertyeditor 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> 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> 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> font = get_font("font", "Tree"); + rect = Rect2(text_size, 0, size.width - text_size, height); + + if (bottom_editor) { - 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; + 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> 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<EditorInspectorPlugin> ped) { + + for (List<EditorInspectorPlugin::AddedEditor>::Element *F = ped->added_editors.front(); F; F = F->next()) { + + EditorProperty *ep = Object::cast_to<EditorProperty>(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<EditorProperty *>(); + } + 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<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) { + Ref<EditorInspectorPlugin> ped = E->get(); + ped->parse_begin(object); + _parse_added_editors(main_vbox, ped); + } + for (List<PropertyInfo>::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<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) { + Ref<EditorInspectorPlugin> 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<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) { Ref<EditorInspectorPlugin> ped = E->get(); ped->parse_property(object, p.type, p.name, p.hint, p.hint_string, p.usage); - for (List<EditorInspectorPlugin::AddedEditor>::Element *F = ped->added_editors.front(); F; F = F->next()) { + List<EditorInspectorPlugin::AddedEditor> editors = ped->added_editors; //make a copy, since plugins may be used again in a sub-inspector + ped->added_editors.clear(); + + for (List<EditorInspectorPlugin::AddedEditor>::Element *F = editors.front(); F; F = F->next()) { EditorProperty *ep = Object::cast_to<EditorProperty>(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<Ref<EditorInspectorPlugin> >::Element *E = valid_plugins.front(); E; E = E->next()) { + Ref<EditorInspectorPlugin> 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<EditorInspectorSection *>::Element *E = sections.front(); E; E = E->next()) { E->get()->fold(); } + + for (Map<StringName, List<EditorProperty *> >::Element *F = editor_property_map.front(); F; F = F->next()) { + for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) { + E->get()->collapse_all_folding(); + } + } } void EditorInspector::expand_all_folding() { for (List<EditorInspectorSection *>::Element *E = sections.front(); E; E = E->next()) { E->get()->unfold(); } + for (Map<StringName, List<EditorProperty *> >::Element *F = editor_property_map.front(); F; F = F->next()) { + for (List<EditorProperty *>::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<Control *> 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<String> 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<EditorInspectorPlugin> 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..dd3b6c2c4c 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -295,7 +295,6 @@ void EditorNode::_notification(int p_what) { get_tree()->get_root()->set_as_audio_listener_2d(false); get_tree()->set_auto_accept_quit(false); get_tree()->connect("files_dropped", this, "_dropped_files"); - property_editable_warning->set_icon(gui_base->get_icon("NodeWarning", "EditorIcons")); } if (p_what == NOTIFICATION_EXIT_TREE) { @@ -324,7 +323,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> theme = create_editor_theme(theme_base->get_theme()); theme_base->set_theme(theme); @@ -343,8 +342,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); } @@ -382,16 +381,6 @@ void EditorNode::_notification(int p_what) { distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons")); scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons")); - resource_new_button->set_icon(gui_base->get_icon("New", "EditorIcons")); - resource_load_button->set_icon(gui_base->get_icon("Load", "EditorIcons")); - resource_save_button->set_icon(gui_base->get_icon("Save", "EditorIcons")); - - property_back->set_icon(gui_base->get_icon("Back", "EditorIcons")); - property_forward->set_icon(gui_base->get_icon("Forward", "EditorIcons")); - editor_history_menu->set_icon(gui_base->get_icon("History", "EditorIcons")); - - search_button->set_icon(gui_base->get_icon("Search", "EditorIcons")); - object_menu->set_icon(gui_base->get_icon("Tools", "EditorIcons")); // clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property update_menu->set_icon(gui_base->get_icon("Collapse", "EditorIcons")); dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons")); @@ -549,8 +538,8 @@ void EditorNode::_vp_resized() { void EditorNode::_node_renamed() { - if (inspector) - inspector->update_tree(); + if (get_inspector()) + get_inspector()->update_tree(); } void EditorNode::_editor_select_next() { @@ -582,38 +571,16 @@ Error EditorNode::load_resource(const String &p_scene) { RES res = ResourceLoader::load(p_scene); ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN); - edit_resource(res); + inspector_dock->edit_resource(res); return OK; } -void EditorNode::edit_resource(const Ref<Resource> &p_resource) { - - _resource_selected(p_resource, ""); -} - void EditorNode::edit_node(Node *p_node) { push_item(p_node); } -void EditorNode::open_resource(const String &p_type) { - - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); - - List<String> extensions; - ResourceLoader::get_recognized_extensions_for_type(p_type, &extensions); - - file->clear_filters(); - for (int i = 0; i < extensions.size(); i++) { - - file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); - } - - file->popup_centered_ratio(); - current_option = RESOURCE_LOAD; -} - void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) { editor_data.apply_changes_in_editors(); @@ -1145,20 +1112,6 @@ void EditorNode::_mark_unsaved_scenes() { void EditorNode::_dialog_action(String p_file) { switch (current_option) { - - case RESOURCE_LOAD: { - - RES res = ResourceLoader::load(p_file); - if (res.is_null()) { - - current_option = -1; - accept->get_ok()->set_text("Ugh"); - accept->set_text(TTR("Failed to load resource.")); - return; - }; - - push_item(res.operator->()); - } break; case FILE_NEW_INHERITED_SCENE: { load_scene(p_file, false, true); @@ -1352,7 +1305,7 @@ void EditorNode::_dialog_action(String p_file) { void EditorNode::push_item(Object *p_object, const String &p_property) { if (!p_object) { - inspector->edit(NULL); + get_inspector()->edit(NULL); node_dock->set_node(NULL); scene_tree_dock->set_selected(NULL); return; @@ -1370,89 +1323,6 @@ void EditorNode::push_item(Object *p_object, const String &p_property) { _edit_current(); } -void EditorNode::_select_history(int p_idx) { - - //push it to the top, it is not correct, but it's more useful - ObjectID id = editor_history.get_history_obj(p_idx); - Object *obj = ObjectDB::get_instance(id); - if (!obj) - return; - push_item(obj); -} - -void EditorNode::_prepare_history() { - - int history_to = MAX(0, editor_history.get_history_len() - 25); - - editor_history_menu->get_popup()->clear(); - - Ref<Texture> base_icon = gui_base->get_icon("Object", "EditorIcons"); - Set<ObjectID> already; - for (int i = editor_history.get_history_len() - 1; i >= history_to; i--) { - - ObjectID id = editor_history.get_history_obj(i); - Object *obj = ObjectDB::get_instance(id); - if (!obj || already.has(id)) { - if (history_to > 0) { - history_to--; - } - continue; - } - - already.insert(id); - - Ref<Texture> icon = gui_base->get_icon("Object", "EditorIcons"); - if (gui_base->has_icon(obj->get_class(), "EditorIcons")) - icon = gui_base->get_icon(obj->get_class(), "EditorIcons"); - else - icon = base_icon; - - String text; - if (Object::cast_to<Resource>(obj)) { - Resource *r = Object::cast_to<Resource>(obj); - if (r->get_path().is_resource_file()) - text = r->get_path().get_file(); - else if (r->get_name() != String()) { - text = r->get_name(); - } else { - text = r->get_class(); - } - } else if (Object::cast_to<Node>(obj)) { - text = Object::cast_to<Node>(obj)->get_name(); - } else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) { - text = obj->call("get_title"); - } else { - text = obj->get_class(); - } - - if (i == editor_history.get_history_pos()) { - text = "[" + text + "]"; - } - editor_history_menu->get_popup()->add_icon_item(icon, text, i); - } -} - -void EditorNode::_property_editor_forward() { - - if (editor_history.next()) - _edit_current(); -} -void EditorNode::_property_editor_back() { - - if (editor_history.previous() || editor_history.get_path_size() == 1) - _edit_current(); -} - -void EditorNode::_menu_collapseall() { - - inspector->collapse_all_folding(); -} - -void EditorNode::_menu_expandall() { - - inspector->expand_all_folding(); -} - void EditorNode::_save_default_environment() { Ref<Environment> fallback = get_tree()->get_root()->get_world()->get_fallback_environment(); @@ -1494,52 +1364,38 @@ static bool overrides_external_editor(Object *p_object) { return script->get_language()->overrides_external_editor(); } -void EditorNode::_property_editable_warning_pressed() { - - property_editable_warning_dialog->popup_centered_minsize(); -} - void EditorNode::_edit_current() { uint32_t current = editor_history.get_current(); Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; - property_back->set_disabled(editor_history.is_at_beginning()); - property_forward->set_disabled(editor_history.is_at_end()); - this->current = current_obj; - editor_path->update_path(); - - String editable_warning; //none by default - property_editable_warning->hide(); //hide by default if (!current_obj) { scene_tree_dock->set_selected(NULL); - inspector->edit(NULL); + get_inspector()->edit(NULL); node_dock->set_node(NULL); - object_menu->set_disabled(true); + inspector_dock->update(NULL); _display_top_editors(false); return; } - object_menu->set_disabled(true); - bool capitalize = bool(EDITOR_DEF("interface/editor/capitalize_properties", true)); bool is_resource = current_obj->is_class("Resource"); bool is_node = current_obj->is_class("Node"); - resource_save_button->set_disabled(!is_resource); + + String editable_warning; //none by default if (is_resource) { Resource *current_res = Object::cast_to<Resource>(current_obj); ERR_FAIL_COND(!current_res); scene_tree_dock->set_selected(NULL); - inspector->edit(current_res); + get_inspector()->edit(current_res); node_dock->set_node(NULL); - object_menu->set_disabled(false); EditorNode::get_singleton()->get_import_dock()->set_edit_path(current_res->get_path()); int subr_idx = current_res->get_path().find("::"); @@ -1562,7 +1418,7 @@ void EditorNode::_edit_current() { Node *current_node = Object::cast_to<Node>(current_obj); ERR_FAIL_COND(!current_node); - inspector->edit(current_node); + get_inspector()->edit(current_node); if (current_node->is_inside_tree()) { node_dock->set_node(current_node); scene_tree_dock->set_selected(current_node); @@ -1570,7 +1426,6 @@ void EditorNode::_edit_current() { node_dock->set_node(NULL); scene_tree_dock->set_selected(NULL); } - object_menu->get_popup()->clear(); if (get_edited_scene() && get_edited_scene()->get_filename() != String()) { String source_scene = get_edited_scene()->get_filename(); @@ -1586,17 +1441,14 @@ void EditorNode::_edit_current() { capitalize = false; } - inspector->edit(current_obj); + get_inspector()->edit(current_obj); node_dock->set_node(NULL); } - if (editable_warning != String()) { - property_editable_warning->show(); //hide by default - property_editable_warning_dialog->set_text(editable_warning); - } + inspector_dock->set_warning(editable_warning); - if (inspector->is_capitalize_paths_enabled() != capitalize) { - inspector->set_enable_capitalize_paths(capitalize); + if (get_inspector()->is_capitalize_paths_enabled() != capitalize) { + get_inspector()->set_enable_capitalize_paths(capitalize); } /* Take care of PLUGIN EDITOR */ @@ -1654,75 +1506,8 @@ void EditorNode::_edit_current() { _hide_top_editors(); } - object_menu->set_disabled(false); - - PopupMenu *p = object_menu->get_popup(); - - p->clear(); - p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand all properties")), EXPAND_ALL); - p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse all properties")), COLLAPSE_ALL); - p->add_separator(); - p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS); - p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS); - p->add_separator(); - p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Paste Resource")), RESOURCE_PASTE); - if (is_resource) { - p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY); - p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_UNREF); - } - - if (is_resource || is_node) { - p->add_separator(); - p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES); - p->add_separator(); - p->add_icon_shortcut(gui_base->get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP); - } - - List<MethodInfo> methods; - current_obj->get_method_list(&methods); - - if (!methods.empty()) { - - bool found = false; - List<MethodInfo>::Element *I = methods.front(); - int i = 0; - while (I) { - - if (I->get().flags & METHOD_FLAG_EDITOR) { - if (!found) { - p->add_separator(); - found = true; - } - p->add_item(I->get().name.capitalize(), OBJECT_METHOD_BASE + i); - } - i++; - I = I->next(); - } - } - - update_keying(); -} - -void EditorNode::_resource_created() { - - Object *c = create_dialog->instance_selected(); - - ERR_FAIL_COND(!c); - Resource *r = Object::cast_to<Resource>(c); - ERR_FAIL_COND(!r); - - REF res(r); - - push_item(c); -} - -void EditorNode::_resource_selected(const RES &p_res, const String &p_property) { - - if (p_res.is_null()) - return; - - RES r = p_res; - push_item(r.operator->(), p_property); + inspector_dock->update(current_obj); + inspector_dock->update_keying(); } void EditorNode::_run(bool p_current, const String &p_custom) { @@ -1796,7 +1581,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 +1608,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); } @@ -2163,136 +1948,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { scene_tabs->set_current_tab(cur_idx); } break; - case RESOURCE_NEW: { - - create_dialog->popup_create(true); - } break; - case RESOURCE_LOAD: { - - open_resource(); - } break; - case RESOURCE_SAVE: { - - uint32_t current = editor_history.get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; - - ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)) - - RES current_res = RES(Object::cast_to<Resource>(current_obj)); - - save_resource(current_res); - - } break; - case RESOURCE_SAVE_AS: { - - uint32_t current = editor_history.get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; - - ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)) - - RES current_res = RES(Object::cast_to<Resource>(current_obj)); - - save_resource_as(current_res); - - } break; - case RESOURCE_UNREF: { - - uint32_t current = editor_history.get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; - - ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)) - - RES current_res = RES(Object::cast_to<Resource>(current_obj)); - current_res->set_path(""); - _edit_current(); - } break; - case RESOURCE_COPY: { - - uint32_t current = editor_history.get_current(); - Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; - - ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)) - - RES current_res = RES(Object::cast_to<Resource>(current_obj)); - - EditorSettings::get_singleton()->set_resource_clipboard(current_res); - - } break; - case RESOURCE_PASTE: { - - RES r = EditorSettings::get_singleton()->get_resource_clipboard(); - if (r.is_valid()) { - push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(), String()); - } - - } break; - case OBJECT_REQUEST_HELP: { - - if (current) { - _editor_select(EDITOR_SCRIPT); - emit_signal("request_help", current->get_class()); - } - - } break; - case OBJECT_COPY_PARAMS: { - - editor_data.apply_changes_in_editors(); - if (current) - editor_data.copy_object_params(current); - } break; - case OBJECT_PASTE_PARAMS: { - - editor_data.apply_changes_in_editors(); - if (current) - editor_data.paste_object_params(current); - editor_data.get_undo_redo().clear_history(); - } break; - case OBJECT_UNIQUE_RESOURCES: { - - editor_data.apply_changes_in_editors(); - if (current) { - List<PropertyInfo> props; - current->get_property_list(&props); - Map<RES, RES> duplicates; - for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) - continue; - - Variant v = current->get(E->get().name); - if (v.is_ref()) { - REF ref = v; - if (ref.is_valid()) { - - RES res = ref; - if (res.is_valid()) { - - if (!duplicates.has(res)) { - duplicates[res] = res->duplicate(); - } - res = duplicates[res]; - - current->set(E->get().name, res); - } - } - } - } - } - - editor_data.get_undo_redo().clear_history(); - - _set_editing_top_editors(NULL); - _set_editing_top_editors(current); - - } break; - case COLLAPSE_ALL: { - _menu_collapseall(); - - } break; - case EXPAND_ALL: { - _menu_expandall(); - - } break; case RUN_PLAY: { _menu_option_confirm(RUN_STOP, true); _run(false); @@ -2326,7 +1981,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 +2001,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 +2027,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")); @@ -2555,22 +2210,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; default: { - - if (p_option >= OBJECT_METHOD_BASE) { - - ERR_FAIL_COND(!current); - - int idx = p_option - OBJECT_METHOD_BASE; - - List<MethodInfo> methods; - current->get_method_list(&methods); - - ERR_FAIL_INDEX(idx, methods.size()); - String name = methods[idx].name; - - if (current) - current->call(name); - } else if (p_option >= IMPORT_PLUGIN_BASE) { + if (p_option >= IMPORT_PLUGIN_BASE) { } } } @@ -3244,42 +2884,14 @@ SceneTreeDock *EditorNode::get_scene_tree_dock() { return scene_tree_dock; } +InspectorDock *EditorNode::get_inspector_dock() { -void EditorNode::_instance_request(const Vector<String> &p_files) { - - request_instance_scenes(p_files); -} - -void EditorNode::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) { - - AnimationPlayerEditor::singleton->get_key_editor()->insert_value_key(p_keyed, p_value, p_advance); -} - -void EditorNode::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) { - - Spatial *s = Object::cast_to<Spatial>(sp); - if (!s) - return; - AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s, p_sub, p_key); + return inspector_dock; } -void EditorNode::update_keying() { - - bool valid = false; - - if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) { - - if (editor_history.get_path_size() >= 1) { - - Object *obj = ObjectDB::get_instance(editor_history.get_path_object(0)); - if (Object::cast_to<Node>(obj)) { - - valid = true; - } - } - } +void EditorNode::_instance_request(const Vector<String> &p_files) { - inspector->set_keying(valid); + request_instance_scenes(p_files); } void EditorNode::_close_messages() { @@ -4044,7 +3656,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String } void EditorNode::_load_open_scenes_from_config(Ref<ConfigFile> 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; } @@ -4138,7 +3750,7 @@ void EditorNode::_scene_tab_script_edited(int p_tab) { Ref<Script> script = editor_data.get_scene_root_script(p_tab); if (script.is_valid()) - edit_resource(script); + inspector_dock->edit_resource(script); } void EditorNode::_scene_tab_closed(int p_tab) { @@ -4166,7 +3778,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(); @@ -4236,30 +3848,6 @@ void EditorNode::_scene_tab_changed(int p_tab) { editor_data.get_undo_redo().commit_action(); } -void EditorNode::_toggle_search_bar(bool p_pressed) { - - inspector->set_use_filter(p_pressed); - - if (p_pressed) { - - search_bar->show(); - search_box->grab_focus(); - search_box->select_all(); - } else { - - search_bar->hide(); - } -} - -void EditorNode::_clear_search_box() { - - if (search_box->get_text() == "") - return; - - search_box->clear(); - inspector->update_tree(); -} - ToolButton *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) { ToolButton *tb = memnew(ToolButton); @@ -4778,9 +4366,6 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_tool_menu_option", &EditorNode::_tool_menu_option); ClassDB::bind_method("_menu_confirm_current", &EditorNode::_menu_confirm_current); ClassDB::bind_method("_dialog_action", &EditorNode::_dialog_action); - ClassDB::bind_method("_resource_selected", &EditorNode::_resource_selected, DEFVAL("")); - ClassDB::bind_method("_property_editor_forward", &EditorNode::_property_editor_forward); - ClassDB::bind_method("_property_editor_back", &EditorNode::_property_editor_back); ClassDB::bind_method("_editor_select", &EditorNode::_editor_select); ClassDB::bind_method("_node_renamed", &EditorNode::_node_renamed); ClassDB::bind_method("edit_node", &EditorNode::edit_node); @@ -4790,16 +4375,12 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("set_edited_scene", &EditorNode::set_edited_scene); ClassDB::bind_method("open_request", &EditorNode::open_request); ClassDB::bind_method("_instance_request", &EditorNode::_instance_request); - ClassDB::bind_method("update_keying", &EditorNode::update_keying); - ClassDB::bind_method("_property_keyed", &EditorNode::_property_keyed); - ClassDB::bind_method("_transform_keyed", &EditorNode::_transform_keyed); ClassDB::bind_method("_close_messages", &EditorNode::_close_messages); ClassDB::bind_method("_show_messages", &EditorNode::_show_messages); ClassDB::bind_method("_vp_resized", &EditorNode::_vp_resized); ClassDB::bind_method("_quick_opened", &EditorNode::_quick_opened); ClassDB::bind_method("_quick_run", &EditorNode::_quick_run); - ClassDB::bind_method("_resource_created", &EditorNode::_resource_created); ClassDB::bind_method("_open_recent_scene", &EditorNode::_open_recent_scene); ClassDB::bind_method("stop_child_process", &EditorNode::stop_child_process); @@ -4833,15 +4414,9 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_discard_changes", &EditorNode::_discard_changes); ClassDB::bind_method("_update_recent_scenes", &EditorNode::_update_recent_scenes); - ClassDB::bind_method("_prepare_history", &EditorNode::_prepare_history); - ClassDB::bind_method("_select_history", &EditorNode::_select_history); - - ClassDB::bind_method("_toggle_search_bar", &EditorNode::_toggle_search_bar); - ClassDB::bind_method("_clear_search_box", &EditorNode::_clear_search_box); ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history); ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files); ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode); - ClassDB::bind_method("_property_editable_warning_pressed", &EditorNode::_property_editable_warning_pressed); ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base); ClassDB::bind_method(D_METHOD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch); @@ -4855,7 +4430,6 @@ void EditorNode::_bind_methods() { ADD_SIGNAL(MethodInfo("play_pressed")); ADD_SIGNAL(MethodInfo("pause_pressed")); ADD_SIGNAL(MethodInfo("stop_pressed")); - ADD_SIGNAL(MethodInfo("request_help")); ADD_SIGNAL(MethodInfo("request_help_search")); ADD_SIGNAL(MethodInfo("request_help_index")); ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::POOL_STRING_ARRAY, "args"))); @@ -5042,6 +4616,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); @@ -5565,129 +5155,11 @@ EditorNode::EditorNode() { dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene")); dock_slot[DOCK_SLOT_LEFT_BR]->hide(); - VBoxContainer *prop_editor_base = memnew(VBoxContainer); - prop_editor_base->set_name("Inspector"); - dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(prop_editor_base); - dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(prop_editor_base->get_index(), TTR("Inspector")); - - HBoxContainer *prop_editor_hb = memnew(HBoxContainer); - - prop_editor_base->add_child(prop_editor_hb); - prop_editor_vb = prop_editor_base; - - resource_new_button = memnew(ToolButton); - resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it.")); - resource_new_button->set_icon(gui_base->get_icon("New", "EditorIcons")); - prop_editor_hb->add_child(resource_new_button); - resource_new_button->connect("pressed", this, "_menu_option", varray(RESOURCE_NEW)); - resource_new_button->set_focus_mode(Control::FOCUS_NONE); - - resource_load_button = memnew(ToolButton); - resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it.")); - resource_load_button->set_icon(gui_base->get_icon("Load", "EditorIcons")); - prop_editor_hb->add_child(resource_load_button); - resource_load_button->connect("pressed", this, "_menu_option", varray(RESOURCE_LOAD)); - resource_load_button->set_focus_mode(Control::FOCUS_NONE); - - resource_save_button = memnew(MenuButton); - resource_save_button->set_tooltip(TTR("Save the currently edited resource.")); - resource_save_button->set_icon(gui_base->get_icon("Save", "EditorIcons")); - prop_editor_hb->add_child(resource_save_button); - resource_save_button->get_popup()->add_item(TTR("Save"), RESOURCE_SAVE); - resource_save_button->get_popup()->add_item(TTR("Save As..."), RESOURCE_SAVE_AS); - resource_save_button->get_popup()->connect("id_pressed", this, "_menu_option"); - resource_save_button->set_focus_mode(Control::FOCUS_NONE); - resource_save_button->set_disabled(true); - - prop_editor_hb->add_spacer(); - - property_back = memnew(ToolButton); - property_back->set_icon(gui_base->get_icon("Back", "EditorIcons")); - property_back->set_flat(true); - property_back->set_tooltip(TTR("Go to the previous edited object in history.")); - property_back->set_disabled(true); - - prop_editor_hb->add_child(property_back); - - property_forward = memnew(ToolButton); - property_forward->set_icon(gui_base->get_icon("Forward", "EditorIcons")); - property_forward->set_flat(true); - property_forward->set_tooltip(TTR("Go to the next edited object in history.")); - property_forward->set_disabled(true); - - prop_editor_hb->add_child(property_forward); - - editor_history_menu = memnew(MenuButton); - editor_history_menu->set_tooltip(TTR("History of recently edited objects.")); - editor_history_menu->set_icon(gui_base->get_icon("History", "EditorIcons")); - prop_editor_hb->add_child(editor_history_menu); - editor_history_menu->connect("about_to_show", this, "_prepare_history"); - editor_history_menu->get_popup()->connect("id_pressed", this, "_select_history"); - - prop_editor_hb = memnew(HBoxContainer); //again... - prop_editor_base->add_child(prop_editor_hb); - - editor_path = memnew(EditorPath(&editor_history)); - editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); - prop_editor_hb->add_child(editor_path); - - search_button = memnew(ToolButton); - search_button->set_toggle_mode(true); - search_button->set_pressed(false); - search_button->set_icon(gui_base->get_icon("Search", "EditorIcons")); - prop_editor_hb->add_child(search_button); - search_button->connect("toggled", this, "_toggle_search_bar"); - - object_menu = memnew(MenuButton); - object_menu->set_icon(gui_base->get_icon("Tools", "EditorIcons")); - prop_editor_hb->add_child(object_menu); - object_menu->set_tooltip(TTR("Object properties.")); - - create_dialog = memnew(CreateDialog); - gui_base->add_child(create_dialog); - create_dialog->set_base_type("Resource"); - create_dialog->connect("create", this, "_resource_created"); - - search_bar = memnew(HBoxContainer); - search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); - prop_editor_base->add_child(search_bar); - search_bar->hide(); - - Label *l = memnew(Label(TTR("Search:") + " ")); - search_bar->add_child(l); - - search_box = memnew(LineEdit); - search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); - search_bar->add_child(search_box); - - ToolButton *clear_button = memnew(ToolButton); - clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); - search_bar->add_child(clear_button); - clear_button->connect("pressed", this, "_clear_search_box"); - - property_editable_warning = memnew(Button); - property_editable_warning->set_text(TTR("Changes may be lost!")); - prop_editor_base->add_child(property_editable_warning); - property_editable_warning_dialog = memnew(AcceptDialog); - gui_base->add_child(property_editable_warning_dialog); - property_editable_warning->hide(); - property_editable_warning->connect("pressed", this, "_property_editable_warning_pressed"); - - inspector = memnew(EditorInspector); - inspector->set_autoclear(true); - inspector->set_show_categories(true); - 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->hide_top_label(); - inspector->register_text_enter(search_box); + inspector_dock = memnew(InspectorDock(this, editor_data)); + dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(inspector_dock); + dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector")); Button *property_editable_warning; - prop_editor_base->add_child(inspector); - inspector->set_undo_redo(&editor_data.get_undo_redo()); import_dock = memnew(ImportDock); dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock); @@ -5813,18 +5285,12 @@ EditorNode::EditorNode() { gui_base->add_child(file_script); file_script->connect("file_selected", this, "_dialog_action"); - property_forward->connect("pressed", this, "_property_editor_forward"); - property_back->connect("pressed", this, "_property_editor_back"); - file_menu->get_popup()->connect("id_pressed", this, "_menu_option"); - object_menu->get_popup()->connect("id_pressed", this, "_menu_option"); settings_menu->get_popup()->connect("id_pressed", this, "_menu_option"); file->connect("file_selected", this, "_dialog_action"); file_templates->connect("file_selected", this, "_dialog_action"); - inspector->connect("resource_selected", this, "_resource_selected"); - inspector->connect("property_keyed", this, "_property_keyed"); //plugin stuff diff --git a/editor/editor_node.h b/editor/editor_node.h index 86b85663ab..bef5bc816c 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -40,7 +40,6 @@ #include "editor/editor_inspector.h" #include "editor/editor_log.h" #include "editor/editor_name_dialog.h" -#include "editor/editor_path.h" #include "editor/editor_plugin.h" #include "editor/editor_resource_preview.h" #include "editor/editor_run.h" @@ -53,6 +52,7 @@ #include "editor/filesystem_dock.h" #include "editor/groups_editor.h" #include "editor/import_dock.h" +#include "editor/inspector_dock.h" #include "editor/node_dock.h" #include "editor/pane_drag.h" #include "editor/progress_dialog.h" @@ -142,22 +142,10 @@ private: EDIT_REVERT, TOOLS_ORPHAN_RESOURCES, TOOLS_CUSTOM, - RESOURCE_NEW, - RESOURCE_LOAD, RESOURCE_SAVE, RESOURCE_SAVE_AS, - RESOURCE_UNREF, - RESOURCE_COPY, - RESOURCE_PASTE, - OBJECT_COPY_PARAMS, - OBJECT_PASTE_PARAMS, - OBJECT_UNIQUE_RESOURCES, - OBJECT_REQUEST_HELP, RUN_PLAY, - COLLAPSE_ALL, - EXPAND_ALL, - RUN_STOP, RUN_PLAY_SCENE, RUN_PLAY_NATIVE, @@ -195,8 +183,6 @@ private: IMPORT_PLUGIN_BASE = 100, - OBJECT_METHOD_BASE = 500, - TOOL_MENU_BASE = 1000 }; @@ -247,7 +233,6 @@ private: PopupMenu *tool_menu; ToolButton *export_button; ToolButton *prev_scene; - MenuButton *object_menu; ToolButton *play_button; MenuButton *native_play_button; ToolButton *pause_button; @@ -264,24 +249,13 @@ private: Ref<Theme> theme; PopupMenu *recent_scenes; - Button *property_back; - Button *property_forward; SceneTreeDock *scene_tree_dock; - EditorInspector *inspector; - Button *property_editable_warning; - AcceptDialog *property_editable_warning_dialog; - void _property_editable_warning_pressed(); + InspectorDock *inspector_dock; NodeDock *node_dock; ImportDock *import_dock; - VBoxContainer *prop_editor_vb; FileSystemDock *filesystem_dock; EditorRunNative *run_native; - HBoxContainer *search_bar; - LineEdit *search_box; - - CreateDialog *create_dialog; - ConfirmationDialog *confirmation; ConfirmationDialog *save_confirmation; ConfirmationDialog *import_confirmation; @@ -314,11 +288,6 @@ private: String defer_export_platform; bool defer_export_debug; Node *_last_instanced_scene; - EditorPath *editor_path; - ToolButton *resource_new_button; - ToolButton *resource_load_button; - MenuButton *resource_save_button; - MenuButton *editor_history_menu; EditorLog *log; CenterContainer *tabs_center; @@ -422,23 +391,12 @@ private: void _dialog_display_load_error(String p_file, Error p_error); int current_option; - void _resource_created(); - void _resource_selected(const RES &p_res, const String &p_property = ""); void _menu_option(int p_option); void _menu_confirm_current(); void _menu_option_confirm(int p_option, bool p_confirmed); void _tool_menu_option(int p_idx); void _update_debug_options(); - void _property_editor_forward(); - void _property_editor_back(); - - void _menu_collapseall(); - void _menu_expandall(); - - void _select_history(int p_idx); - void _prepare_history(); - void _fs_changed(); void _resources_reimported(const Vector<String> &p_resources); void _sources_changed(bool p_exist); @@ -462,9 +420,6 @@ private: void _instance_request(const Vector<String> &p_files); - void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance); - void _transform_keyed(Object *sp, const String &p_sub, const Transform &p_key); - void _hide_top_editors(); void _display_top_editors(bool p_display); void _set_top_editors(Vector<EditorPlugin *> p_editor_plugins_over); @@ -578,8 +533,6 @@ private: void _update_layouts_menu(); void _layout_menu_option(int p_id); - void _toggle_search_bar(bool p_pressed); - void _clear_search_box(); void _clear_undo_history(); void _update_addon_config(); @@ -640,8 +593,8 @@ public: EditorPluginList *get_editor_plugins_over() { return editor_plugins_over; } EditorPluginList *get_editor_plugins_force_over() { return editor_plugins_force_over; } EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; } - EditorInspector *get_inspector() { return inspector; } - VBoxContainer *get_property_editor_vb() { return prop_editor_vb; } + EditorInspector *get_inspector() { return inspector_dock->get_inspector(); } + Container *get_inspector_dock_addon_area() { return inspector_dock->get_addon_area(); } ProjectSettingsEditor *get_project_settings() { return project_settings; } @@ -663,8 +616,8 @@ public: bool is_addon_plugin_enabled(const String &p_addon) const; void edit_node(Node *p_node); - void edit_resource(const Ref<Resource> &p_resource); - void open_resource(const String &p_type = ""); + void edit_resource(const Ref<Resource> &p_resource) { inspector_dock->edit_resource(p_resource); }; + void open_resource(const String &p_type) { inspector_dock->open_resource(p_type); }; void save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path); void save_resource(const Ref<Resource> &p_resource); @@ -713,6 +666,7 @@ public: FileSystemDock *get_filesystem_dock(); ImportDock *get_import_dock(); SceneTreeDock *get_scene_tree_dock(); + InspectorDock *get_inspector_dock(); static UndoRedo *get_undo_redo() { return &singleton->editor_data.get_undo_redo(); } EditorSelection *get_editor_selection() { return editor_selection; } @@ -759,8 +713,6 @@ public: void save_layout(); - void update_keying(); - void open_export_template_manager(); void reload_scene(const String &p_path); @@ -785,6 +737,10 @@ public: void dim_editor(bool p_dimming); + void edit_current() { _edit_current(); }; + + void update_keying() const { inspector_dock->update_keying(); }; + EditorNode(); ~EditorNode(); void get_singleton(const char *arg1, bool arg2); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 2e4e887165..24d0592ee7 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -375,7 +375,7 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C } break; case CONTAINER_PROPERTY_EDITOR_BOTTOM: { - EditorNode::get_singleton()->get_property_editor_vb()->add_child(p_control); + EditorNode::get_singleton()->get_inspector_dock_addon_area()->add_child(p_control); } break; } @@ -422,7 +422,7 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati } break; case CONTAINER_PROPERTY_EDITOR_BOTTOM: { - EditorNode::get_singleton()->get_property_editor_vb()->remove_child(p_control); + EditorNode::get_singleton()->get_inspector_dock_addon_area()->remove_child(p_control); } break; } @@ -659,6 +659,14 @@ void EditorPlugin::remove_export_plugin(const Ref<EditorExportPlugin> &p_exporte EditorExport::get_singleton()->remove_export_plugin(p_exporter); } +void EditorPlugin::add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) { + EditorInspector::add_inspector_plugin(p_plugin); +} + +void EditorPlugin::remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) { + EditorInspector::remove_inspector_plugin(p_plugin); +} + void EditorPlugin::add_scene_import_plugin(const Ref<EditorSceneImporter> &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<EditorExportPlugin> &p_exporter); void remove_export_plugin(const Ref<EditorExportPlugin> &p_exporter); + void add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin); + void remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin); + void add_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer); void remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index f3397d7980..812e461a14 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<Texture>()); assign->set_text(TTR("[empty]")); - assign->set_disabled(true); } else { - assign->set_disabled(false); Ref<Texture> 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); } @@ -2015,6 +2073,23 @@ void EditorPropertyResource::_notification(int p_what) { Ref<Texture> t = get_icon("select_arrow", "Tree"); edit->set_icon(t); } + + if (p_what == NOTIFICATION_DRAG_BEGIN) { + + if (is_visible_in_tree()) { + 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) { @@ -2033,6 +2108,111 @@ 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::_button_draw() { + + if (dropping) { + Color color = get_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 { + + String allowed_type = base_type; + + Dictionary drag_data = p_drag_data; + if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + Ref<Resource> res = drag_data["resource"]; + for (int i = 0; i < allowed_type.get_slice_count(","); i++) { + String at = allowed_type.get_slice(",", i).strip_edges(); + if (res.is_valid() && 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_type.get_slice_count(","); i++) { + String at = allowed_type.get_slice(",", 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::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; + if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + Ref<Resource> res = drag_data["resource"]; + if (res.is_valid()) { + emit_signal("property_changed", get_edited_property(), res); + update_property(); + return; + } + } + + if (drag_data.has("type") && String(drag_data["type"]) == "files") { + + Vector<String> files = drag_data["files"]; + + if (files.size() == 1) { + String file = files[0]; + RES res = ResourceLoader::load(file); + if (res.is_valid()) { + emit_signal("property_changed", get_edited_property(), res); + update_property(); + return; + } + } + } +} + void EditorPropertyResource::_bind_methods() { ClassDB::bind_method(D_METHOD("_file_selected"), &EditorPropertyResource::_file_selected); @@ -2041,10 +2221,19 @@ 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); + 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("_button_draw"), &EditorPropertyResource::_button_draw); } 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); @@ -2052,6 +2241,8 @@ EditorPropertyResource::EditorPropertyResource() { assign->set_h_size_flags(SIZE_EXPAND_FILL); assign->set_clip_text(true); assign->connect("pressed", this, "_resource_selected"); + assign->set_drag_forwarding(this); + assign->connect("draw", this, "_button_draw"); hbc->add_child(assign); menu = memnew(PopupMenu); @@ -2064,6 +2255,7 @@ EditorPropertyResource::EditorPropertyResource() { file = NULL; scene_tree = NULL; + dropping = false; } ////////////// DEFAULT PLUGIN ////////////////////// diff --git a/editor/editor_properties.h b/editor/editor_properties.h index cf0c735b37..19884cc9dc 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -481,7 +481,10 @@ class EditorPropertyResource : public EditorProperty { PopupMenu *menu; EditorFileDialog *file; Vector<String> inheritors_array; + EditorInspector *sub_inspector; + bool use_sub_inspector; + bool dropping; String base_type; SceneTreeDialog *scene_tree; @@ -494,6 +497,16 @@ 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); + + void _button_draw(); + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool _is_drop_valid(const Dictionary &p_drag_data) const; + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + protected: static void _bind_methods(); void _notification(int p_what); @@ -501,6 +514,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/groups_editor.cpp b/editor/groups_editor.cpp index 8443311a54..e42f9780a6 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -286,6 +286,9 @@ void GroupDialog::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { add_button->set_icon(get_icon("Forward", "EditorIcons")); remove_button->set_icon(get_icon("Back", "EditorIcons")); + + add_filter->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + remove_filter->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); } break; } } diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp new file mode 100644 index 0000000000..4159a3658e --- /dev/null +++ b/editor/inspector_dock.cpp @@ -0,0 +1,564 @@ +/*************************************************************************/ +/* inspector_dock.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "inspector_dock.h" + +#include "editor/editor_node.h" +#include "editor/editor_settings.h" +#include "editor/plugins/animation_player_editor_plugin.h" + +void InspectorDock::_menu_option(int p_option) { + switch (p_option) { + case RESOURCE_SAVE: { + _save_resource(false); + } break; + case RESOURCE_SAVE_AS: { + _save_resource(true); + } break; + + case OBJECT_REQUEST_HELP: { + if (current) { + editor->set_visible_editor(EditorNode::EDITOR_SCRIPT); + emit_signal("request_help", current->get_class()); + } + } break; + + case OBJECT_COPY_PARAMS: { + editor_data->apply_changes_in_editors(); + if (current) + editor_data->copy_object_params(current); + } break; + + case OBJECT_PASTE_PARAMS: { + editor_data->apply_changes_in_editors(); + if (current) + editor_data->paste_object_params(current); + editor_data->get_undo_redo().clear_history(); + } break; + + case OBJECT_UNIQUE_RESOURCES: { + editor_data->apply_changes_in_editors(); + if (current) { + List<PropertyInfo> props; + current->get_property_list(&props); + Map<RES, RES> duplicates; + for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { + + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + continue; + + Variant v = current->get(E->get().name); + if (v.is_ref()) { + REF ref = v; + if (ref.is_valid()) { + + RES res = ref; + if (res.is_valid()) { + + if (!duplicates.has(res)) { + duplicates[res] = res->duplicate(); + } + res = duplicates[res]; + + current->set(E->get().name, res); + } + } + } + } + } + + editor_data->get_undo_redo().clear_history(); + + editor->get_editor_plugins_over()->edit(NULL); + editor->get_editor_plugins_over()->edit(current); + + } break; + + default: { + if (p_option >= OBJECT_METHOD_BASE) { + ERR_FAIL_COND(!current); + + int idx = p_option - OBJECT_METHOD_BASE; + + List<MethodInfo> methods; + current->get_method_list(&methods); + + ERR_FAIL_INDEX(idx, methods.size()); + String name = methods[idx].name; + + if (current) + current->call(name); + } + } + } +} + +void InspectorDock::_new_resource() { + new_resource_dialog->popup_create(true); +} + +void InspectorDock::_load_resource(const String &p_type) { + load_resource_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + + List<String> extensions; + ResourceLoader::get_recognized_extensions_for_type(p_type, &extensions); + + load_resource_dialog->clear_filters(); + for (int i = 0; i < extensions.size(); i++) { + load_resource_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); + } + + load_resource_dialog->popup_centered_ratio(); +} + +void InspectorDock::_resource_file_selected(String p_file) { + RES res = ResourceLoader::load(p_file); + if (res.is_null()) { + warning_dialog->get_ok()->set_text("Ugh"); + warning_dialog->set_text(TTR("Failed to load resource.")); + return; + }; + + editor->push_item(res.operator->()); +} + +void InspectorDock::_save_resource(bool save_as) const { + uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current(); + Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; + + ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)) + + RES current_res = RES(Object::cast_to<Resource>(current_obj)); + + if (save_as) + editor->save_resource_as(current_res); + else + editor->save_resource(current_res); +} + +void InspectorDock::_unref_resource() const { + uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current(); + Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; + + ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)) + + RES current_res = RES(Object::cast_to<Resource>(current_obj)); + current_res->set_path(""); + editor->edit_current(); +} + +void InspectorDock::_copy_resource() const { + uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current(); + Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL; + + ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj)) + + RES current_res = RES(Object::cast_to<Resource>(current_obj)); + + EditorSettings::get_singleton()->set_resource_clipboard(current_res); +} + +void InspectorDock::_paste_resource() const { + RES r = EditorSettings::get_singleton()->get_resource_clipboard(); + if (r.is_valid()) { + editor->push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(), String()); + } +} + +void InspectorDock::_prepare_history() { + EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); + + int history_to = MAX(0, editor_history->get_history_len() - 25); + + history_menu->get_popup()->clear(); + + Ref<Texture> base_icon = get_icon("Object", "EditorIcons"); + Set<ObjectID> already; + for (int i = editor_history->get_history_len() - 1; i >= history_to; i--) { + + ObjectID id = editor_history->get_history_obj(i); + Object *obj = ObjectDB::get_instance(id); + if (!obj || already.has(id)) { + if (history_to > 0) { + history_to--; + } + continue; + } + + already.insert(id); + + Ref<Texture> icon = get_icon("Object", "EditorIcons"); + if (has_icon(obj->get_class(), "EditorIcons")) + icon = get_icon(obj->get_class(), "EditorIcons"); + else + icon = base_icon; + + String text; + if (Object::cast_to<Resource>(obj)) { + Resource *r = Object::cast_to<Resource>(obj); + if (r->get_path().is_resource_file()) + text = r->get_path().get_file(); + else if (r->get_name() != String()) { + text = r->get_name(); + } else { + text = r->get_class(); + } + } else if (Object::cast_to<Node>(obj)) { + text = Object::cast_to<Node>(obj)->get_name(); + } else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) { + text = obj->call("get_title"); + } else { + text = obj->get_class(); + } + + if (i == editor_history->get_history_pos()) { + text = "[" + text + "]"; + } + history_menu->get_popup()->add_icon_item(icon, text, i); + } +} + +void InspectorDock::_select_history(int p_idx) const { + //push it to the top, it is not correct, but it's more useful + ObjectID id = EditorNode::get_singleton()->get_editor_history()->get_history_obj(p_idx); + Object *obj = ObjectDB::get_instance(id); + if (!obj) + return; + editor->push_item(obj); +} + +void InspectorDock::_resource_created() const { + Object *c = new_resource_dialog->instance_selected(); + + ERR_FAIL_COND(!c); + Resource *r = Object::cast_to<Resource>(c); + ERR_FAIL_COND(!r); + + REF res(r); + editor->push_item(c); +} + +void InspectorDock::_resource_selected(const RES &p_res, const String &p_property) const { + if (p_res.is_null()) + return; + + RES r = p_res; + editor->push_item(r.operator->(), p_property); +} + +void InspectorDock::_edit_forward() { + if (EditorNode::get_singleton()->get_editor_history()->next()) + editor->edit_current(); +} +void InspectorDock::_edit_back() { + EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); + if (editor_history->previous() || editor_history->get_path_size() == 1) + editor->edit_current(); +} + +void InspectorDock::_menu_collapseall() { + inspector->collapse_all_folding(); +} + +void InspectorDock::_menu_expandall() { + inspector->expand_all_folding(); +} + +void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) { + AnimationPlayerEditor::singleton->get_key_editor()->insert_value_key(p_keyed, p_value, p_advance); +} + +void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) { + Spatial *s = Object::cast_to<Spatial>(sp); + if (!s) + return; + AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s, p_sub, p_key); +} + +void InspectorDock::_warning_pressed() { + warning_dialog->get_ok()->set_text(TTR("Ok")); + warning_dialog->popup_centered_minsize(); +} + +Container *InspectorDock::get_addon_area() { + return this; +} + +void InspectorDock::_bind_methods() { + ClassDB::bind_method("_menu_option", &InspectorDock::_menu_option); + + ClassDB::bind_method("update_keying", &InspectorDock::update_keying); + ClassDB::bind_method("_property_keyed", &InspectorDock::_property_keyed); + ClassDB::bind_method("_transform_keyed", &InspectorDock::_transform_keyed); + + ClassDB::bind_method("_new_resource", &InspectorDock::_new_resource); + ClassDB::bind_method("_resource_file_selected", &InspectorDock::_resource_file_selected); + ClassDB::bind_method("_open_resource_selector", &InspectorDock::_open_resource_selector); + ClassDB::bind_method("_unref_resource", &InspectorDock::_unref_resource); + ClassDB::bind_method("_paste_resource", &InspectorDock::_paste_resource); + ClassDB::bind_method("_copy_resource", &InspectorDock::_copy_resource); + + ClassDB::bind_method("_select_history", &InspectorDock::_select_history); + ClassDB::bind_method("_prepare_history", &InspectorDock::_prepare_history); + ClassDB::bind_method("_resource_created", &InspectorDock::_resource_created); + ClassDB::bind_method("_resource_selected", &InspectorDock::_resource_selected, DEFVAL("")); + ClassDB::bind_method("_menu_collapseall", &InspectorDock::_menu_collapseall); + ClassDB::bind_method("_menu_expandall", &InspectorDock::_menu_expandall); + ClassDB::bind_method("_warning_pressed", &InspectorDock::_warning_pressed); + ClassDB::bind_method("_edit_forward", &InspectorDock::_edit_forward); + ClassDB::bind_method("_edit_back", &InspectorDock::_edit_back); + + ADD_SIGNAL(MethodInfo("request_help")); +} + +void InspectorDock::edit_resource(const Ref<Resource> &p_resource) { + _resource_selected(p_resource, ""); +} + +void InspectorDock::open_resource(const String &p_type) { + _load_resource(p_type); +} + +void InspectorDock::set_warning(const String &p_message) { + warning->hide(); + if (p_message != String()) { + warning->show(); + warning_dialog->set_text(p_message); + } +} + +void InspectorDock::clear() { +} + +void InspectorDock::update(Object *p_object) { + + EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); + backward_button->set_disabled(editor_history->is_at_beginning()); + forward_button->set_disabled(editor_history->is_at_end()); + + history_menu->set_disabled(true); + if (editor_history->get_history_len() > 0) { + history_menu->set_disabled(false); + } + editor_path->update_path(); + + current = p_object; + + if (!p_object) { + object_menu->set_disabled(true); + warning->hide(); + search->set_editable(false); + + return; + } + + bool is_resource = p_object->is_class("Resource"); + bool is_node = p_object->is_class("Node"); + + object_menu->set_disabled(false); + search->set_editable(true); + + PopupMenu *p = object_menu->get_popup(); + + p->clear(); + p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand all properties")), EXPAND_ALL); + p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse all properties")), COLLAPSE_ALL); + p->add_separator(); + if (is_resource) { + p->add_item(TTR("Save"), RESOURCE_SAVE); + p->add_item(TTR("Save As..."), RESOURCE_SAVE_AS); + p->add_separator(); + } + p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS); + p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS); + p->add_separator(); + p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Paste Resource")), RESOURCE_PASTE); + if (is_resource) { + p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY); + p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_UNREF); + } + + if (is_resource || is_node) { + p->add_separator(); + p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES); + p->add_separator(); + p->add_icon_shortcut(get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP); + } + + List<MethodInfo> methods; + p_object->get_method_list(&methods); + + if (!methods.empty()) { + + bool found = false; + List<MethodInfo>::Element *I = methods.front(); + int i = 0; + while (I) { + + if (I->get().flags & METHOD_FLAG_EDITOR) { + if (!found) { + p->add_separator(); + found = true; + } + p->add_item(I->get().name.capitalize(), OBJECT_METHOD_BASE + i); + } + i++; + I = I->next(); + } + } +} + +void InspectorDock::update_keying() { + bool valid = false; + + if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) { + + EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); + if (editor_history->get_path_size() >= 1) { + + Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0)); + if (Object::cast_to<Node>(obj)) { + + valid = true; + } + } + } + + inspector->set_keying(valid); +} + +InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { + set_name("Inspector"); + set_theme(p_editor->get_gui_base()->get_theme()); + + editor = p_editor; + editor_data = &p_editor_data; + + HBoxContainer *general_options_hb = memnew(HBoxContainer); + add_child(general_options_hb); + + resource_new_button = memnew(ToolButton); + resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it.")); + resource_new_button->set_icon(get_icon("New", "EditorIcons")); + general_options_hb->add_child(resource_new_button); + resource_new_button->connect("pressed", this, "_new_resource"); + resource_new_button->set_focus_mode(Control::FOCUS_NONE); + + resource_load_button = memnew(ToolButton); + resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it.")); + resource_load_button->set_icon(get_icon("Load", "EditorIcons")); + general_options_hb->add_child(resource_load_button); + resource_load_button->connect("pressed", this, "_open_resource_selector"); + resource_load_button->set_focus_mode(Control::FOCUS_NONE); + + general_options_hb->add_spacer(); + + backward_button = memnew(ToolButton); + general_options_hb->add_child(backward_button); + backward_button->set_icon(get_icon("Back", "EditorIcons")); + backward_button->set_flat(true); + backward_button->set_tooltip(TTR("Go to the previous edited object in history.")); + backward_button->set_disabled(true); + backward_button->connect("pressed", this, "_edit_back"); + + forward_button = memnew(ToolButton); + general_options_hb->add_child(forward_button); + forward_button->set_icon(get_icon("Forward", "EditorIcons")); + forward_button->set_flat(true); + forward_button->set_tooltip(TTR("Go to the next edited object in history.")); + forward_button->set_disabled(true); + forward_button->connect("pressed", this, "_edit_forward"); + + history_menu = memnew(MenuButton); + history_menu->set_tooltip(TTR("History of recently edited objects.")); + history_menu->set_icon(get_icon("History", "EditorIcons")); + general_options_hb->add_child(history_menu); + history_menu->connect("about_to_show", this, "_prepare_history"); + history_menu->get_popup()->connect("id_pressed", this, "_select_history"); + + HBoxContainer *node_info_hb = memnew(HBoxContainer); + add_child(node_info_hb); + + editor_path = memnew(EditorPath(editor->get_editor_history())); + editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); + node_info_hb->add_child(editor_path); + + object_menu = memnew(MenuButton); + object_menu->set_icon(get_icon("Tools", "EditorIcons")); + node_info_hb->add_child(object_menu); + object_menu->set_tooltip(TTR("Object properties.")); + object_menu->get_popup()->connect("id_pressed", this, "_menu_option"); + + new_resource_dialog = memnew(CreateDialog); + editor->get_gui_base()->add_child(new_resource_dialog); + new_resource_dialog->set_base_type("Resource"); + new_resource_dialog->connect("create", this, "_resource_created"); + + search = memnew(LineEdit); + search->set_h_size_flags(Control::SIZE_EXPAND_FILL); + search->set_placeholder(TTR("Filter properties")); + search->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); + add_child(search); + + warning = memnew(Button); + add_child(warning); + warning->set_text(TTR("Changes may be lost!")); + warning->set_icon(get_icon("NodeWarning", "EditorIcons")); + warning->hide(); + warning->connect("pressed", this, "_warning_pressed"); + + warning_dialog = memnew(AcceptDialog); + editor->get_gui_base()->add_child(warning_dialog); + + load_resource_dialog = memnew(EditorFileDialog); + add_child(load_resource_dialog); + load_resource_dialog->set_current_dir("res://"); + load_resource_dialog->connect("file_selected", this, "_resource_file_selected"); + + inspector = memnew(EditorInspector); + add_child(inspector); + inspector->set_autoclear(true); + inspector->set_show_categories(true); + 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->register_text_enter(search); + inspector->set_undo_redo(&editor_data->get_undo_redo()); + + inspector->set_use_filter(true); // TODO: check me + + inspector->connect("resource_selected", this, "_resource_selected"); + inspector->connect("property_keyed", this, "_property_keyed"); +} + +InspectorDock::~InspectorDock() { +} diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h new file mode 100644 index 0000000000..688c8beed7 --- /dev/null +++ b/editor/inspector_dock.h @@ -0,0 +1,137 @@ +/*************************************************************************/ +/* inspector_dock.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef INSPECTOR_DOCK_H +#define INSPECTOR_DOCK_H + +#include "editor/animation_editor.h" +#include "editor/connections_dialog.h" +#include "editor/create_dialog.h" +#include "editor/editor_data.h" +#include "editor/editor_inspector.h" +#include "editor/editor_path.h" +#include "scene/gui/box_container.h" +#include "scene/gui/button.h" +#include "scene/gui/control.h" +#include "scene/gui/label.h" +#include "scene/gui/popup_menu.h" +#include "scene/gui/tool_button.h" + +class EditorNode; + +class InspectorDock : public VBoxContainer { + + GDCLASS(InspectorDock, VBoxContainer); + + enum MenuOptions { + RESOURCE_NEW, + RESOURCE_LOAD, + RESOURCE_SAVE, + RESOURCE_SAVE_AS, + RESOURCE_UNREF, + RESOURCE_COPY, + RESOURCE_PASTE, + OBJECT_COPY_PARAMS, + OBJECT_PASTE_PARAMS, + OBJECT_UNIQUE_RESOURCES, + OBJECT_REQUEST_HELP, + + COLLAPSE_ALL, + EXPAND_ALL, + + OBJECT_METHOD_BASE = 500 + }; + + EditorNode *editor; + EditorData *editor_data; + + EditorInspector *inspector; + + Object *current; + + ToolButton *backward_button; + ToolButton *forward_button; + + EditorFileDialog *load_resource_dialog; + CreateDialog *new_resource_dialog; + ToolButton *resource_new_button; + ToolButton *resource_load_button; + MenuButton *resource_save_button; + MenuButton *history_menu; + LineEdit *search; + + MenuButton *object_menu; + EditorPath *editor_path; + + Button *warning; + AcceptDialog *warning_dialog; + + void _menu_option(int p_option); + + void _new_resource(); + void _load_resource(const String &p_type = ""); + void _open_resource_selector() { _load_resource(); }; // just used to call from arg-less signal + void _resource_file_selected(String p_file); + void _save_resource(bool save_as) const; + void _unref_resource() const; + void _copy_resource() const; + void _paste_resource() const; + + void _warning_pressed(); + void _resource_created() const; + void _resource_selected(const RES &p_res, const String &p_property = "") const; + void _edit_forward(); + void _edit_back(); + void _menu_collapseall(); + void _menu_expandall(); + void _select_history(int p_idx) const; + void _prepare_history(); + + void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance); + void _transform_keyed(Object *sp, const String &p_sub, const Transform &p_key); + +protected: + static void _bind_methods(); + +public: + void update_keying(); + void edit_resource(const Ref<Resource> &p_resource); + void open_resource(const String &p_type); + void clear(); + void set_warning(const String &p_message); + void update(Object *p_object); + Container *get_addon_area(); + EditorInspector *get_inspector() { return inspector; } + + InspectorDock(EditorNode *p_editor, EditorData &p_editor_data); + ~InspectorDock(); +}; + +#endif 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> 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> 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,87 +751,28 @@ void CurveEditor::_bind_methods() { //--------------- -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(); - - get_editor_interface()->get_resource_previewer()->add_preview_generator(memnew(CurvePreviewGenerator)); -} - -CurveEditorPlugin::~CurveEditorPlugin() { -} - -void CurveEditorPlugin::edit(Object *p_object) { - - Ref<Curve> curve_ref; - - if (_current_ref.is_valid()) { - CurveTexture *ct = Object::cast_to<CurveTexture>(*_current_ref); - if (ct) - ct->disconnect(CoreStringNames::get_singleton()->changed, this, "_curve_texture_changed"); - } - - if (p_object) { - Resource *res = Object::cast_to<Resource>(p_object); - ERR_FAIL_COND(res == NULL); - ERR_FAIL_COND(!handles(p_object)); - - _current_ref = Ref<Resource>(Object::cast_to<Resource>(p_object)); - - if (_current_ref.is_valid()) { - Curve *curve = Object::cast_to<Curve>(*_current_ref); - if (curve) - curve_ref = Ref<Curve>(curve); - else { - CurveTexture *ct = Object::cast_to<CurveTexture>(*_current_ref); - if (ct) { - ct->connect(CoreStringNames::get_singleton()->changed, this, "_curve_texture_changed"); - curve_ref = ct->get_curve(); - } - } - } +bool EditorInspectorPluginCurve::can_handle(Object *p_object) { - } else { - _current_ref = Ref<Resource>(); - } - - _view->set_curve(curve_ref); + return Object::cast_to<Curve>(p_object) != NULL; } -bool CurveEditorPlugin::handles(Object *p_object) const { - // Both handled so that we can keep the curve editor open - return Object::cast_to<Curve>(p_object) || Object::cast_to<CurveTexture>(p_object); -} +void EditorInspectorPluginCurve::parse_begin(Object *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(); - } -} + Curve *curve = Object::cast_to<Curve>(p_object); + ERR_FAIL_COND(!curve); + Ref<Curve> c(curve); -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<CurveTexture>(*_current_ref); - if (ct) { - _view->set_curve(ct->get_curve()); - } + CurveEditor *editor = memnew(CurveEditor); + editor->set_curve(curve); + add_custom_control(editor); } -void CurveEditorPlugin::_bind_methods() { +CurveEditorPlugin::CurveEditorPlugin(EditorNode *p_node) { + Ref<EditorInspectorPluginCurve> curve_plugin; + curve_plugin.instance(); + EditorInspector::add_inspector_plugin(curve_plugin); - ClassDB::bind_method(D_METHOD("_curve_texture_changed"), &CurveEditorPlugin::_curve_texture_changed); + get_editor_interface()->get_resource_previewer()->add_preview_generator(memnew(CurvePreviewGenerator)); } //----------------------------------- 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<Resource> _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) { - - editor = p_node; - ramp_editor = memnew(GradientEdit); - - 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"); +Size2 GradientEditor::get_minimum_size() const { + return Size2(0, 60) * EDSCALE; } +void GradientEditor::_gradient_changed() { -void GradientEditorPlugin::edit(Object *p_object) { - - Gradient *gradient = Object::cast_to<Gradient>(p_object); - if (!gradient) + if (editing) return; - gradient_ref = Ref<Gradient>(gradient); - ramp_editor->set_points(gradient_ref->get_points()); -} -bool GradientEditorPlugin::handles(Object *p_object) const { + editing = true; + Vector<Gradient::Point> points = gradient->get_points(); + set_points(points); + editing = false; +} - return p_object->is_class("Gradient"); +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 GradientEditorPlugin::make_visible(bool p_visible) { +void GradientEditor::_bind_methods() { - if (p_visible) { - ramp_editor->show(); - } else { - ramp_editor->hide(); - } + ClassDB::bind_method("_gradient_changed", &GradientEditor::_gradient_changed); + ClassDB::bind_method("_ramp_changed", &GradientEditor::_ramp_changed); } -void GradientEditorPlugin::_ramp_changed() { - - if (gradient_ref.is_valid()) { +void GradientEditor::set_gradient(const Ref<Gradient> &p_gradient) { + gradient = p_gradient; + connect("ramp_changed", this, "_ramp_changed"); + gradient->connect("changed", this, "_gradient_changed"); + set_points(gradient->get_points()); +} - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); +GradientEditor::GradientEditor() { + editing = false; +} - //Not sure if I should convert this data to PoolVector - Vector<float> new_offsets = ramp_editor->get_offsets(); - Vector<Color> new_colors = ramp_editor->get_colors(); - Vector<float> old_offsets = gradient_ref->get_offsets(); - Vector<Color> 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(); +bool EditorInspectorPluginGradient::can_handle(Object *p_object) { - //color_ramp_ref->set_points(ramp_editor->get_points()); - } + return Object::cast_to<Gradient>(p_object) != NULL; } -void GradientEditorPlugin::_undo_redo_gradient(const Vector<float> &offsets, const Vector<Color> &colors) { +void EditorInspectorPluginGradient::parse_begin(Object *p_object) { - gradient_ref->set_offsets(offsets); - gradient_ref->set_colors(colors); - ramp_editor->set_points(gradient_ref->get_points()); - ramp_editor->update(); -} + Gradient *gradient = Object::cast_to<Gradient>(p_object); + Ref<Gradient> g(gradient); -GradientEditorPlugin::~GradientEditorPlugin() { + GradientEditor *editor = memnew(GradientEditor); + editor->set_gradient(g); + add_custom_control(editor); } -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); +GradientEditorPlugin::GradientEditorPlugin(EditorNode *p_node) { + + Ref<EditorInspectorPluginGradient> 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 GradientEditorPlugin : public EditorPlugin { +class GradientEditor : public GradientEdit { + GDCLASS(GradientEditor, GradientEdit) - GDCLASS(GradientEditorPlugin, EditorPlugin); + bool editing; + Ref<Gradient> gradient; - Ref<Gradient> gradient_ref; - GradientEdit *ramp_editor; - EditorNode *editor; + void _gradient_changed(); + void _ramp_changed(); protected: static void _bind_methods(); - void _ramp_changed(); - void _undo_redo_gradient(const Vector<float> &offsets, const Vector<Color> &colors); + +public: + virtual Size2 get_minimum_size() const; + void set_gradient(const Ref<Gradient> &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); 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/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index c0f91455fa..422d19c0e4 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1188,7 +1188,7 @@ void ScriptEditor::_notification(int p_what) { case NOTIFICATION_READY: { get_tree()->connect("tree_changed", this, "_tree_changed"); - editor->connect("request_help", this, "_request_help"); + editor->get_inspector_dock()->connect("request_help", this, "_request_help"); editor->connect("request_help_search", this, "_help_search"); editor->connect("request_help_index", this, "_help_index"); } break; 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<StyleBox> &p_stylebox) { +bool EditorInspectorPluginStyleBox::can_handle(Object *p_object) { + + return Object::cast_to<StyleBox>(p_object) != NULL; +} + +void EditorInspectorPluginStyleBox::parse_begin(Object *p_object) { + + Ref<StyleBox> sb = Ref<StyleBox>(Object::cast_to<StyleBox>(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<StyleBox> &p_stylebox) { if (stylebox.is_valid()) stylebox->disconnect("changed", this, "_sb_changed"); @@ -39,71 +58,33 @@ void StyleBoxEditor::edit(const Ref<StyleBox> &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<StyleBox>(p_node)) { - stylebox_editor->edit(Object::cast_to<StyleBox>(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<EditorInspectorPluginStyleBox> 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> stylebox; void _sb_changed(); @@ -53,23 +52,24 @@ protected: public: void edit(const Ref<StyleBox> &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<TileSet>(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<InputEvent> &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/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 7d94cad49b..c79cf02062 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -667,7 +667,7 @@ void TileSetEditor::_on_workspace_draw() { if (mask & TileSet::BIND_BOTTOMRIGHT) { workspace->draw_rect(Rect2(anchor + size / 2, size / 2), c); } - } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { + } else { if (mask & TileSet::BIND_TOPLEFT) { workspace->draw_rect(Rect2(anchor, size / 3), c); } @@ -821,7 +821,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { bit = TileSet::BIND_BOTTOMRIGHT; } } - } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { + } else { if (pos.x < size.x / 3) { if (pos.y < size.y / 3) { bit = TileSet::BIND_TOPLEFT; @@ -884,7 +884,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { bit = TileSet::BIND_BOTTOMRIGHT; } } - } else if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_3X3) { + } else { if (pos.x < size.x / 3) { if (pos.y < size.y / 3) { bit = TileSet::BIND_TOPLEFT; @@ -1849,7 +1849,7 @@ void TileSetEditorHelper::_get_property_list(List<PropertyInfo> *p_list) const { if (selected_tile < 0 || tileset.is_null()) return; - p_list->push_back(PropertyInfo(Variant::INT, "bitmask_mode", PROPERTY_HINT_ENUM, "2x2,3x3")); + p_list->push_back(PropertyInfo(Variant::INT, "bitmask_mode", PROPERTY_HINT_ENUM, "2x2,3x3 (minimal),3x3")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "layout/tile_size")); p_list->push_back(PropertyInfo(Variant::INT, "layout/spacing", PROPERTY_HINT_RANGE, "0,256,1")); } 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/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp index 4737e14111..16e0386952 100644 --- a/scene/2d/navigation2d.cpp +++ b/scene/2d/navigation2d.cpp @@ -671,7 +671,7 @@ Object *Navigation2D::get_closest_point_owner(const Vector2 &p_point) { if (Geometry::is_point_in_triangle(p_point, _get_vertex(p.edges[0].point), _get_vertex(p.edges[i - 1].point), _get_vertex(p.edges[i].point))) { - E->get().owner; + return E->get().owner; } } } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 5294189c65..d88e148b2c 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -845,16 +845,37 @@ void TileMap::update_cell_bitmask(int p_x, int p_y) { if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) { mask |= TileSet::BIND_BOTTOMRIGHT; } - } else if (tile_set->autotile_get_bitmask_mode(id) == TileSet::BITMASK_3X3) { - if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1))) { - mask |= TileSet::BIND_TOPLEFT; + } else { + if (tile_set->autotile_get_bitmask_mode(id) == TileSet::BITMASK_3X3_MINIMAL) { + if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) { + mask |= TileSet::BIND_TOPLEFT; + } + if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) { + mask |= TileSet::BIND_TOPRIGHT; + } + if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) { + mask |= TileSet::BIND_BOTTOMLEFT; + } + if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) { + mask |= TileSet::BIND_BOTTOMRIGHT; + } + } else { + if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1))) { + mask |= TileSet::BIND_TOPLEFT; + } + if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y - 1))) { + mask |= TileSet::BIND_TOPRIGHT; + } + if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y + 1))) { + mask |= TileSet::BIND_BOTTOMLEFT; + } + if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1))) { + mask |= TileSet::BIND_BOTTOMRIGHT; + } } if (tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1))) { mask |= TileSet::BIND_TOP; } - if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y - 1))) { - mask |= TileSet::BIND_TOPRIGHT; - } if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) { mask |= TileSet::BIND_LEFT; } @@ -862,15 +883,9 @@ void TileMap::update_cell_bitmask(int p_x, int p_y) { if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) { mask |= TileSet::BIND_RIGHT; } - if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y + 1))) { - mask |= TileSet::BIND_BOTTOMLEFT; - } if (tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1))) { mask |= TileSet::BIND_BOTTOM; } - if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1))) { - mask |= TileSet::BIND_BOTTOMRIGHT; - } } Vector2 coord = tile_set->autotile_get_subtile_for_bitmask(id, mask, this, Vector2(p_x, p_y)); E->get().autotile_coord_x = (int)coord.x; 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<Control>(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<InputEvent> &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<Texture> &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<Texture> &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<Texture> &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<Texture> &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<Texture> &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<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_ID, bool p_global) { @@ -608,6 +615,7 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut item.shortcut_is_global = p_global; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bool p_global) { @@ -622,6 +630,7 @@ void PopupMenu::add_shortcut(const Ref<ShortCut> &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<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_ID, bool p_global) { @@ -638,6 +647,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<Sh item.shortcut_is_global = p_global; items.push_back(item); update(); + minimum_size_changed(); } void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bool p_global) { @@ -653,6 +663,7 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &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<ShortCut> &p_shortcut, int p_ID, bool p_global) { @@ -660,6 +671,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &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<Texture> &p_icon) { @@ -689,6 +703,7 @@ void PopupMenu::set_item_icon(int p_idx, const Ref<Texture> &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<Texture> 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 { diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 42d64376f5..58057cda0c 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -264,7 +264,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region")); p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE")); if (tile_get_tile_mode(id) == AUTO_TILE) { - p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3 (minimal),3X3", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/icon_coordinate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/tile_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); @@ -960,6 +960,7 @@ void TileSet::_bind_methods() { BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_forward_subtile_selection", PropertyInfo(Variant::INT, "autotile_id"), PropertyInfo(Variant::INT, "bitmask"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location"))); BIND_ENUM_CONSTANT(BITMASK_2X2); + BIND_ENUM_CONSTANT(BITMASK_3X3_MINIMAL); BIND_ENUM_CONSTANT(BITMASK_3X3); BIND_ENUM_CONSTANT(BIND_TOPLEFT); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index d5704ac9a0..ec635ee5cc 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -56,6 +56,7 @@ public: enum BitmaskMode { BITMASK_2X2, + BITMASK_3X3_MINIMAL, BITMASK_3X3 }; |