1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-23 15:16:17 +00:00

Remove ItemList editor and replace it by a property array

This commit is contained in:
Gilles Roudière
2021-10-27 18:29:44 +02:00
parent 435d50bf0f
commit a51f92273a
7 changed files with 98 additions and 723 deletions

View File

@@ -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_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_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_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 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); static void set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default);

View File

@@ -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. 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.
</description> </description>
</method> </method>
<method name="get_item_count" qualifiers="const">
<return type="int" />
<description>
Returns the number of items currently in the list.
</description>
</method>
<method name="get_item_custom_bg_color" qualifiers="const"> <method name="get_item_custom_bg_color" qualifiers="const">
<return type="Color" /> <return type="Color" />
<argument index="0" name="idx" type="int" /> <argument index="0" name="idx" type="int" />
@@ -387,6 +381,9 @@
<member name="icon_scale" type="float" setter="set_icon_scale" getter="get_icon_scale" default="1.0"> <member name="icon_scale" type="float" setter="set_icon_scale" getter="get_icon_scale" default="1.0">
The scale of icon applied after [member fixed_icon_size] and transposing takes effect. The scale of icon applied after [member fixed_icon_size] and transposing takes effect.
</member> </member>
<member name="items_count" type="int" setter="set_item_count" getter="get_item_count" default="0">
The number of items currently in the list.
</member>
<member name="max_columns" type="int" setter="set_max_columns" getter="get_max_columns" default="1"> <member name="max_columns" type="int" setter="set_max_columns" getter="get_max_columns" default="1">
Maximum columns the list will have. Maximum columns the list will have.
If greater than zero, the content will be split among the specified columns. If greater than zero, the content will be split among the specified columns.

View File

@@ -144,7 +144,6 @@
#include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h" #include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h"
#include "editor/plugins/gradient_editor_plugin.h" #include "editor/plugins/gradient_editor_plugin.h"
#include "editor/plugins/input_event_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/light_occluder_2d_editor_plugin.h"
#include "editor/plugins/lightmap_gi_editor_plugin.h" #include "editor/plugins/lightmap_gi_editor_plugin.h"
#include "editor/plugins/line_2d_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(CPUParticles2DEditorPlugin(this)));
add_editor_plugin(memnew(CPUParticles3DEditorPlugin(this))); add_editor_plugin(memnew(CPUParticles3DEditorPlugin(this)));
add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this))); add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this)));
add_editor_plugin(memnew(ItemListEditorPlugin(this)));
add_editor_plugin(memnew(Polygon3DEditorPlugin(this))); add_editor_plugin(memnew(Polygon3DEditorPlugin(this)));
add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin(this))); add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin(this)));
add_editor_plugin(memnew(TilesEditorPlugin(this))); add_editor_plugin(memnew(TilesEditorPlugin(this)));

View File

@@ -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<PropertyInfo> *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<OptionButton>(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<MenuButton>(p_object)->get_popup();
} else {
pp = Object::cast_to<PopupMenu>(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<ItemList>(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<Node>(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() {
}

View File

@@ -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<PropertyInfo> *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<Texture2D> &p_tex) {}
virtual Ref<Texture2D> get_item_icon(int p_idx) const { return Ref<Texture2D>(); };
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<Texture2D> &p_tex) override { ob->set_item_icon(p_idx, p_tex); }
virtual Ref<Texture2D> 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<Texture2D> &p_tex) override { pp->set_item_icon(p_idx, p_tex); }
virtual Ref<Texture2D> 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<Texture2D> &p_tex) override { pp->set_item_icon(p_idx, p_tex); }
virtual Ref<Texture2D> 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<ItemListPlugin *> 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

View File

@@ -55,16 +55,8 @@ void ItemList::_shape(int p_idx) {
int ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bool p_selectable) { int ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bool p_selectable) {
Item item; Item item;
item.icon = p_texture; 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 = p_item;
item.text_buf.instantiate();
item.selectable = p_selectable; 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); items.push_back(item);
int item_id = items.size() - 1; int item_id = items.size() - 1;
@@ -72,27 +64,20 @@ int ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bo
update(); update();
shape_changed = true; shape_changed = true;
notify_property_list_changed();
return item_id; return item_id;
} }
int ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) { int ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) {
Item item; Item item;
item.icon = p_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.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); items.push_back(item);
int item_id = items.size() - 1; int item_id = items.size() - 1;
update(); update();
shape_changed = true; shape_changed = true;
notify_property_list_changed();
return item_id; return item_id;
} }
@@ -400,6 +385,15 @@ void ItemList::move_item(int p_from_idx, int p_to_idx) {
update(); update();
shape_changed = true; 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 { int ItemList::get_item_count() const {
@@ -416,6 +410,7 @@ void ItemList::remove_item(int p_idx) {
update(); update();
shape_changed = true; shape_changed = true;
defer_select_single = -1; defer_select_single = -1;
notify_property_list_changed();
} }
void ItemList::clear() { void ItemList::clear() {
@@ -425,6 +420,7 @@ void ItemList::clear() {
update(); update();
shape_changed = true; shape_changed = true;
defer_select_single = -1; defer_select_single = -1;
notify_property_list_changed();
} }
void ItemList::set_fixed_column_width(int p_size) { void ItemList::set_fixed_column_width(int p_size) {
@@ -1446,32 +1442,6 @@ bool ItemList::is_anything_selected() {
return false; 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<Texture2D> 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 { Size2 ItemList::get_minimum_size() const {
if (auto_height) { if (auto_height) {
return Size2(0, auto_height_value); return Size2(0, auto_height_value);
@@ -1508,6 +1478,74 @@ TextParagraph::OverrunBehavior ItemList::get_text_overrun_behavior() const {
return text_overrun_behavior; return text_overrun_behavior;
} }
bool ItemList::_set(const StringName &p_name, const Variant &p_value) {
Vector<String> 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<Texture2D> 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<String> 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<PropertyInfo> *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() { 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_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)); 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("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("get_item_count"), &ItemList::get_item_count);
ClassDB::bind_method(D_METHOD("remove_item", "idx"), &ItemList::remove_item); 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("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("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); 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::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_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::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::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::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_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_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::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"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "same_column_width"), "set_same_column_width", "is_same_column_width");

View File

@@ -54,7 +54,7 @@ private:
Ref<Texture2D> icon; Ref<Texture2D> icon;
bool icon_transposed = false; bool icon_transposed = false;
Rect2i icon_region; Rect2i icon_region;
Color icon_modulate; Color icon_modulate = Color(1, 1, 1, 1);
Ref<Texture2D> tag_icon; Ref<Texture2D> tag_icon;
String text; String text;
Ref<TextParagraph> text_buf; Ref<TextParagraph> text_buf;
@@ -65,11 +65,11 @@ private:
bool selectable = false; bool selectable = false;
bool selected = false; bool selected = false;
bool disabled = false; bool disabled = false;
bool tooltip_enabled = false; bool tooltip_enabled = true;
Variant metadata; Variant metadata;
String tooltip; String tooltip;
Color custom_fg; Color custom_fg;
Color custom_bg; Color custom_bg = Color(0.0, 0.0, 0.0, 0.0);
Rect2 rect_cache; Rect2 rect_cache;
Rect2 min_rect_cache; Rect2 min_rect_cache;
@@ -77,6 +77,10 @@ private:
Size2 get_icon_size() const; Size2 get_icon_size() const;
bool operator<(const Item &p_another) const { return text < p_another.text; } bool operator<(const Item &p_another) const { return text < p_another.text; }
Item() {
text_buf.instantiate();
}
}; };
int current = -1; int current = -1;
@@ -119,14 +123,14 @@ private:
bool do_autoscroll_to_bottom = false; bool do_autoscroll_to_bottom = false;
Array _get_items() const;
void _set_items(const Array &p_items);
void _scroll_changed(double); void _scroll_changed(double);
void _shape(int p_idx); void _shape(int p_idx);
protected: protected:
void _notification(int p_what); 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<PropertyInfo> *p_list) const;
static void _bind_methods(); static void _bind_methods();
public: public:
@@ -199,6 +203,7 @@ public:
void move_item(int p_from_idx, int p_to_idx); void move_item(int p_from_idx, int p_to_idx);
void set_item_count(int p_count);
int get_item_count() const; int get_item_count() const;
void remove_item(int p_idx); void remove_item(int p_idx);