Răsfoiți Sursa

Implement property array for OptionButton

kobewi 3 ani în urmă
părinte
comite
c68e93ad52
3 a modificat fișierele cu 74 adăugiri și 47 ștergeri
  1. 3 6
      doc/classes/OptionButton.xml
  2. 67 38
      scene/gui/option_button.cpp
  3. 4 3
      scene/gui/option_button.h

+ 3 - 6
doc/classes/OptionButton.xml

@@ -39,12 +39,6 @@
 				Clears all the items in the [OptionButton].
 			</description>
 		</method>
-		<method name="get_item_count" qualifiers="const">
-			<return type="int" />
-			<description>
-				Returns the amount of items in the OptionButton, including separators.
-			</description>
-		</method>
 		<method name="get_item_icon" qualifiers="const">
 			<return type="Texture2D" />
 			<argument index="0" name="idx" type="int" />
@@ -165,6 +159,9 @@
 	<members>
 		<member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" overrides="BaseButton" enum="BaseButton.ActionMode" default="0" />
 		<member name="alignment" type="int" setter="set_text_alignment" getter="get_text_alignment" overrides="Button" enum="HorizontalAlignment" default="0" />
+		<member name="item_count" type="int" setter="set_item_count" getter="get_item_count" default="0">
+			The number of items to select from.
+		</member>
 		<member name="selected" type="int" setter="_select_int" getter="get_selected" default="-1">
 			The index of the currently selected item, or [code]-1[/code] if no item is selected.
 		</member>

+ 67 - 38
scene/gui/option_button.cpp

@@ -110,6 +110,63 @@ void OptionButton::_notification(int p_what) {
 	}
 }
 
+bool OptionButton::_set(const StringName &p_name, const Variant &p_value) {
+	Vector<String> components = String(p_name).split("/", true, 2);
+	if (components.size() >= 2 && components[0] == "popup") {
+		bool valid;
+		popup->set(String(p_name).trim_prefix("popup/"), p_value, &valid);
+
+		int idx = components[1].get_slice("_", 1).to_int();
+		if (idx == current) {
+			// Force refreshing currently displayed item.
+			current = -1;
+			_select(idx, false);
+		}
+
+		return valid;
+	}
+	return false;
+}
+
+bool OptionButton::_get(const StringName &p_name, Variant &r_ret) const {
+	Vector<String> components = String(p_name).split("/", true, 2);
+	if (components.size() >= 2 && components[0] == "popup") {
+		bool valid;
+		r_ret = popup->get(String(p_name).trim_prefix("popup/"), &valid);
+		return valid;
+	}
+	return false;
+}
+
+void OptionButton::_get_property_list(List<PropertyInfo> *p_list) const {
+	for (int i = 0; i < popup->get_item_count(); i++) {
+		p_list->push_back(PropertyInfo(Variant::STRING, vformat("popup/item_%d/text", i)));
+
+		PropertyInfo pi = PropertyInfo(Variant::OBJECT, vformat("popup/item_%d/icon", i), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D");
+		pi.usage &= ~(popup->get_item_icon(i).is_null() ? PROPERTY_USAGE_STORAGE : 0);
+		p_list->push_back(pi);
+
+		pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/checkable", i), PROPERTY_HINT_ENUM, "No,As checkbox,As radio button");
+		pi.usage &= ~(!popup->is_item_checkable(i) ? PROPERTY_USAGE_STORAGE : 0);
+		p_list->push_back(pi);
+
+		pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/checked", i));
+		pi.usage &= ~(!popup->is_item_checked(i) ? PROPERTY_USAGE_STORAGE : 0);
+		p_list->push_back(pi);
+
+		pi = PropertyInfo(Variant::INT, vformat("popup/item_%d/id", i), PROPERTY_HINT_RANGE, "1,10,1,or_greater");
+		p_list->push_back(pi);
+
+		pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/disabled", i));
+		pi.usage &= ~(!popup->is_item_disabled(i) ? PROPERTY_USAGE_STORAGE : 0);
+		p_list->push_back(pi);
+
+		pi = PropertyInfo(Variant::BOOL, vformat("popup/item_%d/separator", i));
+		pi.usage &= ~(!popup->is_item_separator(i) ? PROPERTY_USAGE_STORAGE : 0);
+		p_list->push_back(pi);
+	}
+}
+
 void OptionButton::_focused(int p_which) {
 	emit_signal(SNAME("item_focused"), p_which);
 }
@@ -191,6 +248,12 @@ bool OptionButton::is_item_disabled(int p_idx) const {
 	return popup->is_item_disabled(p_idx);
 }
 
+void OptionButton::set_item_count(int p_count) {
+	ERR_FAIL_COND(p_count < 0);
+	popup->set_item_count(p_count);
+	notify_property_list_changed();
+}
+
 int OptionButton::get_item_count() const {
 	return popup->get_item_count();
 }
@@ -267,38 +330,6 @@ PopupMenu *OptionButton::get_popup() const {
 	return popup;
 }
 
-Array OptionButton::_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));
-		items.push_back(get_item_id(i));
-		items.push_back(get_item_metadata(i));
-	}
-
-	return items;
-}
-
-void OptionButton::_set_items(const Array &p_items) {
-	ERR_FAIL_COND(p_items.size() % 5);
-	clear();
-
-	for (int i = 0; i < p_items.size(); i += 5) {
-		String text = p_items[i + 0];
-		Ref<Texture2D> icon = p_items[i + 1];
-		bool disabled = p_items[i + 2];
-		int id = p_items[i + 3];
-		Variant meta = p_items[i + 4];
-
-		int idx = get_item_count();
-		add_item(text, id);
-		set_item_icon(idx, icon);
-		set_item_disabled(idx, disabled);
-		set_item_metadata(idx, meta);
-	}
-}
-
 void OptionButton::get_translatable_strings(List<String> *p_strings) const {
 	popup->get_translatable_strings(p_strings);
 }
@@ -317,7 +348,6 @@ void OptionButton::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_item_index", "id"), &OptionButton::get_item_index);
 	ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &OptionButton::get_item_metadata);
 	ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &OptionButton::is_item_disabled);
-	ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count);
 	ClassDB::bind_method(D_METHOD("add_separator"), &OptionButton::add_separator);
 	ClassDB::bind_method(D_METHOD("clear"), &OptionButton::clear);
 	ClassDB::bind_method(D_METHOD("select", "idx"), &OptionButton::select);
@@ -329,11 +359,10 @@ void OptionButton::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("get_popup"), &OptionButton::get_popup);
 
-	ClassDB::bind_method(D_METHOD("_set_items"), &OptionButton::_set_items);
-	ClassDB::bind_method(D_METHOD("_get_items"), &OptionButton::_get_items);
-
-	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items");
-	// "selected" property must come after "items", otherwise GH-10213 occurs.
+	ClassDB::bind_method(D_METHOD("set_item_count"), &OptionButton::set_item_count);
+	ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count);
+	// "selected" property must come after "item_count", otherwise GH-10213 occurs.
+	ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected");
 	ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index")));
 	ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "index")));

+ 4 - 3
scene/gui/option_button.h

@@ -45,14 +45,14 @@ class OptionButton : public Button {
 	void _select(int p_which, bool p_emit = false);
 	void _select_int(int p_which);
 
-	Array _get_items() const;
-	void _set_items(const Array &p_items);
-
 	virtual void pressed() override;
 
 protected:
 	Size2 get_minimum_size() const override;
 	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();
 
 public:
@@ -76,6 +76,7 @@ public:
 	Variant get_item_metadata(int p_idx) const;
 	bool is_item_disabled(int p_idx) const;
 
+	void set_item_count(int p_count);
 	int get_item_count() const;
 
 	void add_separator();