diff --git a/core/object/class_db.h b/core/object/class_db.h index d9eec4e4a8..dae75ba564 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -331,7 +331,7 @@ public: static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix = ""); static void add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix = ""); - static void add_property_array_count(const StringName &p_class, const String &p_label, const StringName &p_count_property, const StringName &p_count_setter, const StringName &p_count_getter, const String &p_array_element_prefix, uint32_t p_count_usage = PROPERTY_USAGE_EDITOR); + static void add_property_array_count(const StringName &p_class, const String &p_label, const StringName &p_count_property, const StringName &p_count_setter, const StringName &p_count_getter, const String &p_array_element_prefix, uint32_t p_count_usage = PROPERTY_USAGE_DEFAULT); static void add_property_array(const StringName &p_class, const StringName &p_path, const String &p_array_element_prefix); static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1); static void set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default); diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index 0a995c770b..baa0faaae9 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -71,12 +71,6 @@ When there is no item at that point, -1 will be returned if [code]exact[/code] is [code]true[/code], and the closest item index will be returned otherwise. - - - - Returns the number of items currently in the list. - - @@ -387,6 +381,9 @@ The scale of icon applied after [member fixed_icon_size] and transposing takes effect. + + The number of items currently in the list. + Maximum columns the list will have. If greater than zero, the content will be split among the specified columns. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index b4980fe074..1904ac58b0 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -144,7 +144,6 @@ #include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h" #include "editor/plugins/gradient_editor_plugin.h" #include "editor/plugins/input_event_editor_plugin.h" -#include "editor/plugins/item_list_editor_plugin.h" #include "editor/plugins/light_occluder_2d_editor_plugin.h" #include "editor/plugins/lightmap_gi_editor_plugin.h" #include "editor/plugins/line_2d_editor_plugin.h" @@ -6960,7 +6959,6 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(CPUParticles2DEditorPlugin(this))); add_editor_plugin(memnew(CPUParticles3DEditorPlugin(this))); add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this))); - add_editor_plugin(memnew(ItemListEditorPlugin(this))); add_editor_plugin(memnew(Polygon3DEditorPlugin(this))); add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin(this))); add_editor_plugin(memnew(TilesEditorPlugin(this))); diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp deleted file mode 100644 index 16cafda899..0000000000 --- a/editor/plugins/item_list_editor_plugin.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/*************************************************************************/ -/* item_list_editor_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "item_list_editor_plugin.h" - -#include "core/io/resource_loader.h" -#include "editor/editor_scale.h" - -bool ItemListPlugin::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; - int idx = name.get_slice("/", 0).to_int(); - String what = name.get_slice("/", 1); - - if (what == "text") { - set_item_text(idx, p_value); - } else if (what == "icon") { - set_item_icon(idx, p_value); - } else if (what == "checkable") { - // This keeps compatibility to/from versions where this property was a boolean, before radio buttons - switch ((int)p_value) { - case 0: - case 1: - set_item_checkable(idx, p_value); - break; - case 2: - set_item_radio_checkable(idx, true); - break; - } - } else if (what == "checked") { - set_item_checked(idx, p_value); - } else if (what == "id") { - set_item_id(idx, p_value); - } else if (what == "enabled") { - set_item_enabled(idx, p_value); - } else if (what == "separator") { - set_item_separator(idx, p_value); - } else { - return false; - } - - return true; -} - -bool ItemListPlugin::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name; - int idx = name.get_slice("/", 0).to_int(); - String what = name.get_slice("/", 1); - - if (what == "text") { - r_ret = get_item_text(idx); - } else if (what == "icon") { - r_ret = get_item_icon(idx); - } else if (what == "checkable") { - // This keeps compatibility to/from versions where this property was a boolean, before radio buttons - if (!is_item_checkable(idx)) { - r_ret = 0; - } else { - r_ret = is_item_radio_checkable(idx) ? 2 : 1; - } - } else if (what == "checked") { - r_ret = is_item_checked(idx); - } else if (what == "id") { - r_ret = get_item_id(idx); - } else if (what == "enabled") { - r_ret = is_item_enabled(idx); - } else if (what == "separator") { - r_ret = is_item_separator(idx); - } else { - return false; - } - - return true; -} - -void ItemListPlugin::_get_property_list(List *p_list) const { - for (int i = 0; i < get_item_count(); i++) { - String base = itos(i) + "/"; - - p_list->push_back(PropertyInfo(Variant::STRING, base + "text")); - p_list->push_back(PropertyInfo(Variant::OBJECT, base + "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D")); - - int flags = get_flags(); - - if (flags & FLAG_CHECKABLE) { - p_list->push_back(PropertyInfo(Variant::INT, base + "checkable", PROPERTY_HINT_ENUM, "No,As checkbox,As radio button")); - p_list->push_back(PropertyInfo(Variant::BOOL, base + "checked")); - } - - if (flags & FLAG_ID) { - p_list->push_back(PropertyInfo(Variant::INT, base + "id", PROPERTY_HINT_RANGE, "-1,4096")); - } - - if (flags & FLAG_ENABLE) { - p_list->push_back(PropertyInfo(Variant::BOOL, base + "enabled")); - } - - if (flags & FLAG_SEPARATOR) { - p_list->push_back(PropertyInfo(Variant::BOOL, base + "separator")); - } - } -} - -/////////////////////////////////////////////////////////////// -///////////////////////// PLUGINS ///////////////////////////// -/////////////////////////////////////////////////////////////// - -void ItemListOptionButtonPlugin::set_object(Object *p_object) { - ob = Object::cast_to(p_object); -} - -bool ItemListOptionButtonPlugin::handles(Object *p_object) const { - return p_object->is_class("OptionButton"); -} - -int ItemListOptionButtonPlugin::get_flags() const { - return FLAG_ICON | FLAG_ID | FLAG_ENABLE; -} - -void ItemListOptionButtonPlugin::add_item() { - ob->add_item(vformat(TTR("Item %d"), ob->get_item_count())); - notify_property_list_changed(); -} - -int ItemListOptionButtonPlugin::get_item_count() const { - return ob->get_item_count(); -} - -void ItemListOptionButtonPlugin::erase(int p_idx) { - ob->remove_item(p_idx); - notify_property_list_changed(); -} - -ItemListOptionButtonPlugin::ItemListOptionButtonPlugin() { - ob = nullptr; -} - -/////////////////////////////////////////////////////////////// - -void ItemListPopupMenuPlugin::set_object(Object *p_object) { - if (p_object->is_class("MenuButton")) { - pp = Object::cast_to(p_object)->get_popup(); - } else { - pp = Object::cast_to(p_object); - } -} - -bool ItemListPopupMenuPlugin::handles(Object *p_object) const { - return p_object->is_class("PopupMenu") || p_object->is_class("MenuButton"); -} - -int ItemListPopupMenuPlugin::get_flags() const { - return FLAG_ICON | FLAG_CHECKABLE | FLAG_ID | FLAG_ENABLE | FLAG_SEPARATOR; -} - -void ItemListPopupMenuPlugin::add_item() { - pp->add_item(vformat(TTR("Item %d"), pp->get_item_count())); - notify_property_list_changed(); -} - -int ItemListPopupMenuPlugin::get_item_count() const { - return pp->get_item_count(); -} - -void ItemListPopupMenuPlugin::erase(int p_idx) { - pp->remove_item(p_idx); - notify_property_list_changed(); -} - -ItemListPopupMenuPlugin::ItemListPopupMenuPlugin() { - pp = nullptr; -} - -/////////////////////////////////////////////////////////////// - -void ItemListItemListPlugin::set_object(Object *p_object) { - pp = Object::cast_to(p_object); -} - -bool ItemListItemListPlugin::handles(Object *p_object) const { - return p_object->is_class("ItemList"); -} - -int ItemListItemListPlugin::get_flags() const { - return FLAG_ICON | FLAG_ENABLE; -} - -void ItemListItemListPlugin::add_item() { - pp->add_item(vformat(TTR("Item %d"), pp->get_item_count())); - notify_property_list_changed(); -} - -int ItemListItemListPlugin::get_item_count() const { - return pp->get_item_count(); -} - -void ItemListItemListPlugin::erase(int p_idx) { - pp->remove_item(p_idx); - notify_property_list_changed(); -} - -ItemListItemListPlugin::ItemListItemListPlugin() { - pp = nullptr; -} - -/////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////// - -void ItemListEditor::_node_removed(Node *p_node) { - if (p_node == item_list) { - item_list = nullptr; - hide(); - dialog->hide(); - } -} - -void ItemListEditor::_notification(int p_notification) { - if (p_notification == NOTIFICATION_ENTER_TREE || p_notification == NOTIFICATION_THEME_CHANGED) { - add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - clear_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - del_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - } else if (p_notification == NOTIFICATION_READY) { - get_tree()->connect("node_removed", callable_mp(this, &ItemListEditor::_node_removed)); - } -} - -void ItemListEditor::_add_pressed() { - if (selected_idx == -1) { - return; - } - - item_plugins[selected_idx]->add_item(); -} - -void ItemListEditor::_clear_pressed() { - for (int i = item_plugins[selected_idx]->get_item_count() - 1; i >= 0; i--) { - item_plugins[selected_idx]->erase(i); - } -} - -void ItemListEditor::_delete_pressed() { - if (selected_idx == -1) { - return; - } - - String current_selected = (String)property_editor->get_selected_path(); - - if (current_selected == "") { - return; - } - - // FIXME: Currently relying on selecting a *property* to derive what item to delete - // e.g. you select "1/enabled" to delete item 1. - // This should be fixed so that you can delete by selecting the item section header, - // or a delete button on that header. - - int idx = current_selected.get_slice("/", 0).to_int(); - - item_plugins[selected_idx]->erase(idx); -} - -void ItemListEditor::_edit_items() { - dialog->popup_centered_clamped(Vector2(425, 1200) * EDSCALE, 0.8); -} - -void ItemListEditor::edit(Node *p_item_list) { - item_list = p_item_list; - - if (!item_list) { - selected_idx = -1; - property_editor->edit(nullptr); - return; - } - - for (int i = 0; i < item_plugins.size(); i++) { - if (item_plugins[i]->handles(p_item_list)) { - item_plugins[i]->set_object(p_item_list); - property_editor->edit(item_plugins[i]); - - toolbar_button->set_icon(EditorNode::get_singleton()->get_object_icon(item_list, "")); - - selected_idx = i; - return; - } - } - - selected_idx = -1; - property_editor->edit(nullptr); -} - -bool ItemListEditor::handles(Object *p_object) const { - for (int i = 0; i < item_plugins.size(); i++) { - if (item_plugins[i]->handles(p_object)) { - return true; - } - } - - return false; -} - -void ItemListEditor::_bind_methods() { -} - -ItemListEditor::ItemListEditor() { - selected_idx = -1; - item_list = nullptr; - - toolbar_button = memnew(Button); - toolbar_button->set_flat(true); - toolbar_button->set_text(TTR("Items")); - add_child(toolbar_button); - toolbar_button->connect("pressed", callable_mp(this, &ItemListEditor::_edit_items)); - - dialog = memnew(AcceptDialog); - dialog->set_title(TTR("Item List Editor")); - add_child(dialog); - - VBoxContainer *vbc = memnew(VBoxContainer); - dialog->add_child(vbc); - //dialog->set_child_rect(vbc); - - HBoxContainer *hbc = memnew(HBoxContainer); - hbc->set_h_size_flags(SIZE_EXPAND_FILL); - vbc->add_child(hbc); - - add_button = memnew(Button); - add_button->set_text(TTR("Add")); - hbc->add_child(add_button); - add_button->connect("pressed", callable_mp(this, &ItemListEditor::_add_pressed)); - - hbc->add_spacer(); - - clear_button = memnew(Button); - clear_button->set_text(TTR("Delete All")); - hbc->add_child(clear_button); - clear_button->connect("pressed", callable_mp(this, &ItemListEditor::_clear_pressed)); - - del_button = memnew(Button); - del_button->set_text(TTR("Delete")); - hbc->add_child(del_button); - del_button->connect("pressed", callable_mp(this, &ItemListEditor::_delete_pressed)); - - property_editor = memnew(EditorInspector); - vbc->add_child(property_editor); - property_editor->set_v_size_flags(SIZE_EXPAND_FILL); -} - -ItemListEditor::~ItemListEditor() { - for (int i = 0; i < item_plugins.size(); i++) { - memdelete(item_plugins[i]); - } -} - -void ItemListEditorPlugin::edit(Object *p_object) { - item_list_editor->edit(Object::cast_to(p_object)); -} - -bool ItemListEditorPlugin::handles(Object *p_object) const { - return item_list_editor->handles(p_object); -} - -void ItemListEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - item_list_editor->show(); - } else { - item_list_editor->hide(); - item_list_editor->edit(nullptr); - } -} - -ItemListEditorPlugin::ItemListEditorPlugin(EditorNode *p_node) { - editor = p_node; - item_list_editor = memnew(ItemListEditor); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(item_list_editor); - - item_list_editor->hide(); - item_list_editor->add_plugin(memnew(ItemListOptionButtonPlugin)); - item_list_editor->add_plugin(memnew(ItemListPopupMenuPlugin)); - item_list_editor->add_plugin(memnew(ItemListItemListPlugin)); -} - -ItemListEditorPlugin::~ItemListEditorPlugin() { -} diff --git a/editor/plugins/item_list_editor_plugin.h b/editor/plugins/item_list_editor_plugin.h deleted file mode 100644 index 8f61aef083..0000000000 --- a/editor/plugins/item_list_editor_plugin.h +++ /dev/null @@ -1,250 +0,0 @@ -/*************************************************************************/ -/* item_list_editor_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 ITEM_LIST_EDITOR_PLUGIN_H -#define ITEM_LIST_EDITOR_PLUGIN_H - -#include "canvas_item_editor_plugin.h" -#include "editor/editor_inspector.h" -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "scene/gui/menu_button.h" -#include "scene/gui/option_button.h" -#include "scene/gui/popup_menu.h" - -class ItemListPlugin : public Object { - GDCLASS(ItemListPlugin, Object); - -protected: - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List *p_list) const; - -public: - enum Flags { - FLAG_ICON = 1, - FLAG_CHECKABLE = 2, - FLAG_ID = 4, - FLAG_ENABLE = 8, - FLAG_SEPARATOR = 16 - }; - - virtual void set_object(Object *p_object) = 0; - virtual bool handles(Object *p_object) const = 0; - - virtual int get_flags() const = 0; - - virtual void set_item_text(int p_idx, const String &p_text) {} - virtual String get_item_text(int p_idx) const { return ""; }; - - virtual void set_item_icon(int p_idx, const Ref &p_tex) {} - virtual Ref get_item_icon(int p_idx) const { return Ref(); }; - - virtual void set_item_checkable(int p_idx, bool p_check) {} - virtual void set_item_radio_checkable(int p_idx, bool p_check) {} - virtual bool is_item_checkable(int p_idx) const { return false; }; - virtual bool is_item_radio_checkable(int p_idx) const { return false; }; - - virtual void set_item_checked(int p_idx, bool p_checked) {} - virtual bool is_item_checked(int p_idx) const { return false; }; - - virtual void set_item_enabled(int p_idx, int p_enabled) {} - virtual bool is_item_enabled(int p_idx) const { return false; }; - - virtual void set_item_id(int p_idx, int p_id) {} - virtual int get_item_id(int p_idx) const { return -1; }; - - virtual void set_item_separator(int p_idx, bool p_separator) {} - virtual bool is_item_separator(int p_idx) const { return false; }; - - virtual void add_item() = 0; - virtual int get_item_count() const = 0; - virtual void erase(int p_idx) = 0; - - ItemListPlugin() {} -}; - -/////////////////////////////////////////////////////////////// - -class ItemListOptionButtonPlugin : public ItemListPlugin { - GDCLASS(ItemListOptionButtonPlugin, ItemListPlugin); - - OptionButton *ob; - -public: - virtual void set_object(Object *p_object) override; - virtual bool handles(Object *p_object) const override; - virtual int get_flags() const override; - - virtual void set_item_text(int p_idx, const String &p_text) override { ob->set_item_text(p_idx, p_text); } - virtual String get_item_text(int p_idx) const override { return ob->get_item_text(p_idx); } - - virtual void set_item_icon(int p_idx, const Ref &p_tex) override { ob->set_item_icon(p_idx, p_tex); } - virtual Ref get_item_icon(int p_idx) const override { return ob->get_item_icon(p_idx); } - - virtual void set_item_enabled(int p_idx, int p_enabled) override { ob->set_item_disabled(p_idx, !p_enabled); } - virtual bool is_item_enabled(int p_idx) const override { return !ob->is_item_disabled(p_idx); } - - virtual void set_item_id(int p_idx, int p_id) override { ob->set_item_id(p_idx, p_id); } - virtual int get_item_id(int p_idx) const override { return ob->get_item_id(p_idx); } - - virtual void add_item() override; - virtual int get_item_count() const override; - virtual void erase(int p_idx) override; - - ItemListOptionButtonPlugin(); -}; - -class ItemListPopupMenuPlugin : public ItemListPlugin { - GDCLASS(ItemListPopupMenuPlugin, ItemListPlugin); - - PopupMenu *pp; - -public: - virtual void set_object(Object *p_object) override; - virtual bool handles(Object *p_object) const override; - virtual int get_flags() const override; - - virtual void set_item_text(int p_idx, const String &p_text) override { pp->set_item_text(p_idx, p_text); } - virtual String get_item_text(int p_idx) const override { return pp->get_item_text(p_idx); } - - virtual void set_item_icon(int p_idx, const Ref &p_tex) override { pp->set_item_icon(p_idx, p_tex); } - virtual Ref get_item_icon(int p_idx) const override { return pp->get_item_icon(p_idx); } - - virtual void set_item_checkable(int p_idx, bool p_check) override { pp->set_item_as_checkable(p_idx, p_check); } - virtual void set_item_radio_checkable(int p_idx, bool p_check) override { pp->set_item_as_radio_checkable(p_idx, p_check); } - virtual bool is_item_checkable(int p_idx) const override { return pp->is_item_checkable(p_idx); } - virtual bool is_item_radio_checkable(int p_idx) const override { return pp->is_item_radio_checkable(p_idx); } - - virtual void set_item_checked(int p_idx, bool p_checked) override { pp->set_item_checked(p_idx, p_checked); } - virtual bool is_item_checked(int p_idx) const override { return pp->is_item_checked(p_idx); } - - virtual void set_item_enabled(int p_idx, int p_enabled) override { pp->set_item_disabled(p_idx, !p_enabled); } - virtual bool is_item_enabled(int p_idx) const override { return !pp->is_item_disabled(p_idx); } - - virtual void set_item_id(int p_idx, int p_id) override { pp->set_item_id(p_idx, p_id); } - virtual int get_item_id(int p_idx) const override { return pp->get_item_id(p_idx); } - - virtual void set_item_separator(int p_idx, bool p_separator) override { pp->set_item_as_separator(p_idx, p_separator); } - virtual bool is_item_separator(int p_idx) const override { return pp->is_item_separator(p_idx); } - - virtual void add_item() override; - virtual int get_item_count() const override; - virtual void erase(int p_idx) override; - - ItemListPopupMenuPlugin(); -}; - -/////////////////////////////////////////////////////////////// - -class ItemListItemListPlugin : public ItemListPlugin { - GDCLASS(ItemListItemListPlugin, ItemListPlugin); - - ItemList *pp; - -public: - virtual void set_object(Object *p_object) override; - virtual bool handles(Object *p_object) const override; - virtual int get_flags() const override; - - virtual void set_item_text(int p_idx, const String &p_text) override { pp->set_item_text(p_idx, p_text); } - virtual String get_item_text(int p_idx) const override { return pp->get_item_text(p_idx); } - - virtual void set_item_icon(int p_idx, const Ref &p_tex) override { pp->set_item_icon(p_idx, p_tex); } - virtual Ref get_item_icon(int p_idx) const override { return pp->get_item_icon(p_idx); } - - virtual void set_item_enabled(int p_idx, int p_enabled) override { pp->set_item_disabled(p_idx, !p_enabled); } - virtual bool is_item_enabled(int p_idx) const override { return !pp->is_item_disabled(p_idx); } - - virtual void add_item() override; - virtual int get_item_count() const override; - virtual void erase(int p_idx) override; - - ItemListItemListPlugin(); -}; - -/////////////////////////////////////////////////////////////// - -class ItemListEditor : public HBoxContainer { - GDCLASS(ItemListEditor, HBoxContainer); - - Node *item_list; - - Button *toolbar_button; - - AcceptDialog *dialog; - EditorInspector *property_editor; - Tree *tree; - Button *add_button; - Button *del_button; - Button *clear_button; - - int selected_idx; - - Vector item_plugins; - - void _edit_items(); - - void _add_pressed(); - void _delete_pressed(); - void _clear_pressed(); - - void _node_removed(Node *p_node); - -protected: - void _notification(int p_notification); - static void _bind_methods(); - -public: - void edit(Node *p_item_list); - bool handles(Object *p_object) const; - void add_plugin(ItemListPlugin *p_plugin) { item_plugins.push_back(p_plugin); } - ItemListEditor(); - ~ItemListEditor(); -}; - -class ItemListEditorPlugin : public EditorPlugin { - GDCLASS(ItemListEditorPlugin, EditorPlugin); - - ItemListEditor *item_list_editor; - EditorNode *editor; - -public: - virtual String get_name() const override { return "ItemList"; } - bool has_main_screen() const override { return false; } - virtual void edit(Object *p_object) override; - virtual bool handles(Object *p_object) const override; - virtual void make_visible(bool p_visible) override; - - ItemListEditorPlugin(EditorNode *p_node); - ~ItemListEditorPlugin(); -}; - -#endif // ITEM_LIST_EDITOR_PLUGIN_H diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index d10ad90c1f..4215c9aff4 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -55,16 +55,8 @@ void ItemList::_shape(int p_idx) { int ItemList::add_item(const String &p_item, const Ref &p_texture, bool p_selectable) { Item item; item.icon = p_texture; - item.icon_transposed = false; - item.icon_region = Rect2i(); - item.icon_modulate = Color(1, 1, 1, 1); item.text = p_item; - item.text_buf.instantiate(); item.selectable = p_selectable; - item.selected = false; - item.disabled = false; - item.tooltip_enabled = true; - item.custom_bg = Color(0, 0, 0, 0); items.push_back(item); int item_id = items.size() - 1; @@ -72,27 +64,20 @@ int ItemList::add_item(const String &p_item, const Ref &p_texture, bo update(); shape_changed = true; + notify_property_list_changed(); return item_id; } int ItemList::add_icon_item(const Ref &p_item, bool p_selectable) { Item item; item.icon = p_item; - item.icon_transposed = false; - item.icon_region = Rect2i(); - item.icon_modulate = Color(1, 1, 1, 1); - //item.text=p_item; - item.text_buf.instantiate(); item.selectable = p_selectable; - item.selected = false; - item.disabled = false; - item.tooltip_enabled = true; - item.custom_bg = Color(0, 0, 0, 0); items.push_back(item); int item_id = items.size() - 1; update(); shape_changed = true; + notify_property_list_changed(); return item_id; } @@ -400,6 +385,15 @@ void ItemList::move_item(int p_from_idx, int p_to_idx) { update(); shape_changed = true; + notify_property_list_changed(); +} + +void ItemList::set_item_count(int p_count) { + ERR_FAIL_COND(p_count < 0); + items.resize(p_count); + update(); + shape_changed = true; + notify_property_list_changed(); } int ItemList::get_item_count() const { @@ -416,6 +410,7 @@ void ItemList::remove_item(int p_idx) { update(); shape_changed = true; defer_select_single = -1; + notify_property_list_changed(); } void ItemList::clear() { @@ -425,6 +420,7 @@ void ItemList::clear() { update(); shape_changed = true; defer_select_single = -1; + notify_property_list_changed(); } void ItemList::set_fixed_column_width(int p_size) { @@ -1446,32 +1442,6 @@ bool ItemList::is_anything_selected() { return false; } -void ItemList::_set_items(const Array &p_items) { - ERR_FAIL_COND(p_items.size() % 3); - clear(); - - for (int i = 0; i < p_items.size(); i += 3) { - String text = p_items[i + 0]; - Ref icon = p_items[i + 1]; - bool disabled = p_items[i + 2]; - - int idx = get_item_count(); - add_item(text, icon); - set_item_disabled(idx, disabled); - } -} - -Array ItemList::_get_items() const { - Array items; - for (int i = 0; i < get_item_count(); i++) { - items.push_back(get_item_text(i)); - items.push_back(get_item_icon(i)); - items.push_back(is_item_disabled(i)); - } - - return items; -} - Size2 ItemList::get_minimum_size() const { if (auto_height) { return Size2(0, auto_height_value); @@ -1508,6 +1478,74 @@ TextParagraph::OverrunBehavior ItemList::get_text_overrun_behavior() const { return text_overrun_behavior; } +bool ItemList::_set(const StringName &p_name, const Variant &p_value) { + Vector components = String(p_name).split("/", true, 2); + if (components.size() >= 2 && components[0].begins_with("item_") && components[0].trim_prefix("item_").is_valid_int()) { + int item_index = components[0].trim_prefix("item_").to_int(); + if (components[1] == "text") { + set_item_text(item_index, p_value); + return true; + } else if (components[1] == "icon") { + set_item_icon(item_index, p_value); + return true; + } else if (components[1] == "disabled") { + set_item_disabled(item_index, p_value); + return true; + } + } +#ifndef DISABLE_DEPRECATED + // Compatibility. + if (p_name == "items") { + Array arr = p_value; + ERR_FAIL_COND_V(arr.size() % 3, false); + clear(); + + for (int i = 0; i < arr.size(); i += 3) { + String text = arr[i + 0]; + Ref icon = arr[i + 1]; + bool disabled = arr[i + 2]; + + int idx = get_item_count(); + add_item(text, icon); + set_item_disabled(idx, disabled); + } + } +#endif + return false; +} + +bool ItemList::_get(const StringName &p_name, Variant &r_ret) const { + Vector components = String(p_name).split("/", true, 2); + if (components.size() >= 2 && components[0].begins_with("item_") && components[0].trim_prefix("item_").is_valid_int()) { + int item_index = components[0].trim_prefix("item_").to_int(); + if (components[1] == "text") { + r_ret = get_item_text(item_index); + return true; + } else if (components[1] == "icon") { + r_ret = get_item_icon(item_index); + return true; + } else if (components[1] == "disabled") { + r_ret = is_item_disabled(item_index); + return true; + } + } + return false; +} + +void ItemList::_get_property_list(List *p_list) const { + for (int i = 0; i < items.size(); i++) { + p_list->push_back(PropertyInfo(Variant::STRING, vformat("item_%d/text", i))); + + PropertyInfo pi = PropertyInfo(Variant::OBJECT, vformat("item_%d/icon", i), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"); + pi.usage &= ~(get_item_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + + pi = PropertyInfo(Variant::BOOL, vformat("item_%d/disabled", i)); + pi.usage &= ~(!is_item_disabled(i) ? PROPERTY_USAGE_STORAGE : 0); + p_list->push_back(pi); + } +} + void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("add_item", "text", "icon", "selectable"), &ItemList::add_item, DEFVAL(Variant()), DEFVAL(true)); ClassDB::bind_method(D_METHOD("add_icon_item", "icon", "selectable"), &ItemList::add_icon_item, DEFVAL(true)); @@ -1567,6 +1605,7 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("move_item", "from_idx", "to_idx"), &ItemList::move_item); + ClassDB::bind_method(D_METHOD("set_item_count"), &ItemList::set_item_count); ClassDB::bind_method(D_METHOD("get_item_count"), &ItemList::get_item_count); ClassDB::bind_method(D_METHOD("remove_item", "idx"), &ItemList::remove_item); @@ -1614,20 +1653,16 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("get_v_scroll"), &ItemList::get_v_scroll); - ClassDB::bind_method(D_METHOD("_set_items"), &ItemList::_set_items); - ClassDB::bind_method(D_METHOD("_get_items"), &ItemList::_get_items); - ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &ItemList::set_text_overrun_behavior); ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &ItemList::get_text_overrun_behavior); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Multi"), "set_select_mode", "get_select_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_text_lines", PROPERTY_HINT_RANGE, "1,10,1,or_greater"), "set_max_text_lines", "get_max_text_lines"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior"); + ADD_ARRAY_COUNT("Items", "items_count", "set_item_count", "get_item_count", "item_"); ADD_GROUP("Columns", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), "set_max_columns", "get_max_columns"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width"); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 148fa7ba9f..e780179e7b 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -54,7 +54,7 @@ private: Ref icon; bool icon_transposed = false; Rect2i icon_region; - Color icon_modulate; + Color icon_modulate = Color(1, 1, 1, 1); Ref tag_icon; String text; Ref text_buf; @@ -65,11 +65,11 @@ private: bool selectable = false; bool selected = false; bool disabled = false; - bool tooltip_enabled = false; + bool tooltip_enabled = true; Variant metadata; String tooltip; Color custom_fg; - Color custom_bg; + Color custom_bg = Color(0.0, 0.0, 0.0, 0.0); Rect2 rect_cache; Rect2 min_rect_cache; @@ -77,6 +77,10 @@ private: Size2 get_icon_size() const; bool operator<(const Item &p_another) const { return text < p_another.text; } + + Item() { + text_buf.instantiate(); + } }; int current = -1; @@ -119,14 +123,14 @@ private: bool do_autoscroll_to_bottom = false; - Array _get_items() const; - void _set_items(const Array &p_items); - void _scroll_changed(double); void _shape(int p_idx); protected: void _notification(int p_what); + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List *p_list) const; static void _bind_methods(); public: @@ -199,6 +203,7 @@ public: void move_item(int p_from_idx, int p_to_idx); + void set_item_count(int p_count); int get_item_count() const; void remove_item(int p_idx);