Просмотр исходного кода

Fetch override list from ThemeDB

kobewi 1 год назад
Родитель
Сommit
7d6ded2027
4 измененных файлов с 78 добавлено и 75 удалено
  1. 1 1
      editor/doc_tools.cpp
  2. 45 65
      scene/gui/control.cpp
  3. 22 8
      scene/theme/theme_db.cpp
  4. 10 1
      scene/theme/theme_db.h

+ 1 - 1
editor/doc_tools.cpp

@@ -632,7 +632,7 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 			// Theme items.
 			{
 				List<ThemeDB::ThemeItemBind> theme_items;
-				ThemeDB::get_singleton()->get_class_own_items(cname, &theme_items);
+				ThemeDB::get_singleton()->get_class_items(cname, &theme_items);
 				Ref<Theme> default_theme = ThemeDB::get_singleton()->get_default_theme();
 
 				for (const ThemeDB::ThemeItemBind &theme_item : theme_items) {

+ 45 - 65
scene/gui/control.cpp

@@ -370,80 +370,60 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const {
 
 void Control::_get_property_list(List<PropertyInfo> *p_list) const {
 	ERR_MAIN_THREAD_GUARD;
-	Ref<Theme> default_theme = ThemeDB::get_singleton()->get_default_theme();
+	List<ThemeDB::ThemeItemBind> theme_items;
+	ThemeDB::get_singleton()->get_class_items(get_class_name(), &theme_items, true);
 
 	p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Theme Overrides", "theme_override_"), PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP));
 
-	{
-		List<StringName> names;
-		default_theme->get_color_list(get_class_name(), &names);
-		for (const StringName &E : names) {
-			uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
-			if (data.theme_color_override.has(E)) {
-				usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
-			}
+	for (const ThemeDB::ThemeItemBind &E : theme_items) {
+		uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
 
-			p_list->push_back(PropertyInfo(Variant::COLOR, PNAME("theme_override_colors") + String("/") + E, PROPERTY_HINT_NONE, "", usage));
-		}
-	}
-	{
-		List<StringName> names;
-		default_theme->get_constant_list(get_class_name(), &names);
-		for (const StringName &E : names) {
-			uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
-			if (data.theme_constant_override.has(E)) {
-				usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
-			}
+		switch (E.data_type) {
+			case Theme::DATA_TYPE_COLOR: {
+				if (data.theme_color_override.has(E.item_name)) {
+					usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+				}
+				p_list->push_back(PropertyInfo(Variant::COLOR, PNAME("theme_override_colors") + String("/") + E.item_name, PROPERTY_HINT_NONE, "", usage));
+			} break;
 
-			p_list->push_back(PropertyInfo(Variant::INT, PNAME("theme_override_constants") + String("/") + E, PROPERTY_HINT_RANGE, "-16384,16384", usage));
-		}
-	}
-	{
-		List<StringName> names;
-		default_theme->get_font_list(get_class_name(), &names);
-		for (const StringName &E : names) {
-			uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
-			if (data.theme_font_override.has(E)) {
-				usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
-			}
+			case Theme::DATA_TYPE_CONSTANT: {
+				if (data.theme_constant_override.has(E.item_name)) {
+					usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+				}
+				p_list->push_back(PropertyInfo(Variant::INT, PNAME("theme_override_constants") + String("/") + E.item_name, PROPERTY_HINT_RANGE, "-16384,16384", usage));
+			} break;
 
-			p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("theme_override_fonts") + String("/") + E, PROPERTY_HINT_RESOURCE_TYPE, "Font", usage));
-		}
-	}
-	{
-		List<StringName> names;
-		default_theme->get_font_size_list(get_class_name(), &names);
-		for (const StringName &E : names) {
-			uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
-			if (data.theme_font_size_override.has(E)) {
-				usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
-			}
+			case Theme::DATA_TYPE_FONT: {
+				if (data.theme_font_override.has(E.item_name)) {
+					usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+				}
+				p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("theme_override_fonts") + String("/") + E.item_name, PROPERTY_HINT_RESOURCE_TYPE, "Font", usage));
+			} break;
 
-			p_list->push_back(PropertyInfo(Variant::INT, PNAME("theme_override_font_sizes") + String("/") + E, PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px", usage));
-		}
-	}
-	{
-		List<StringName> names;
-		default_theme->get_icon_list(get_class_name(), &names);
-		for (const StringName &E : names) {
-			uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
-			if (data.theme_icon_override.has(E)) {
-				usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
-			}
+			case Theme::DATA_TYPE_FONT_SIZE: {
+				if (data.theme_font_size_override.has(E.item_name)) {
+					usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+				}
+				p_list->push_back(PropertyInfo(Variant::INT, PNAME("theme_override_font_sizes") + String("/") + E.item_name, PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px", usage));
+			} break;
 
-			p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("theme_override_icons") + String("/") + E, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", usage));
-		}
-	}
-	{
-		List<StringName> names;
-		default_theme->get_stylebox_list(get_class_name(), &names);
-		for (const StringName &E : names) {
-			uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
-			if (data.theme_style_override.has(E)) {
-				usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
-			}
+			case Theme::DATA_TYPE_ICON: {
+				if (data.theme_icon_override.has(E.item_name)) {
+					usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+				}
+				p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("theme_override_icons") + String("/") + E.item_name, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", usage));
+			} break;
+
+			case Theme::DATA_TYPE_STYLEBOX: {
+				if (data.theme_style_override.has(E.item_name)) {
+					usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
+				}
+				p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("theme_override_styles") + String("/") + E.item_name, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", usage));
+			} break;
 
-			p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("theme_override_styles") + String("/") + E, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", usage));
+			default: {
+				// Silences warning.
+			} break;
 		}
 	}
 }

+ 22 - 8
scene/theme/theme_db.cpp

@@ -337,6 +337,7 @@ void ThemeDB::bind_class_item(Theme::DataType p_data_type, const StringName &p_c
 	bind.setter = p_setter;
 
 	theme_item_binds[p_class_name][p_prop_name] = bind;
+	theme_item_binds_list[p_class_name].push_back(bind);
 }
 
 void ThemeDB::bind_class_external_item(Theme::DataType p_data_type, const StringName &p_class_name, const StringName &p_prop_name, const StringName &p_item_name, const StringName &p_type_name, ThemeItemSetter p_setter) {
@@ -351,6 +352,7 @@ void ThemeDB::bind_class_external_item(Theme::DataType p_data_type, const String
 	bind.setter = p_setter;
 
 	theme_item_binds[p_class_name][p_prop_name] = bind;
+	theme_item_binds_list[p_class_name].push_back(bind);
 }
 
 void ThemeDB::update_class_instance_items(Node *p_instance) {
@@ -371,7 +373,7 @@ void ThemeDB::update_class_instance_items(Node *p_instance) {
 	}
 }
 
-void ThemeDB::get_class_own_items(const StringName &p_class_name, List<ThemeItemBind> *r_list) {
+void ThemeDB::get_class_items(const StringName &p_class_name, List<ThemeItemBind> *r_list, bool p_include_inherited) {
 	List<StringName> class_hierarchy;
 	StringName class_name = p_class_name;
 	while (class_name != StringName()) {
@@ -381,23 +383,32 @@ void ThemeDB::get_class_own_items(const StringName &p_class_name, List<ThemeItem
 
 	HashSet<StringName> inherited_props;
 	for (const StringName &theme_type : class_hierarchy) {
-		HashMap<StringName, HashMap<StringName, ThemeItemBind>>::Iterator E = theme_item_binds.find(theme_type);
+		HashMap<StringName, List<ThemeItemBind>>::Iterator E = theme_item_binds_list.find(theme_type);
 		if (E) {
-			for (const KeyValue<StringName, ThemeItemBind> &F : E->value) {
-				if (inherited_props.has(F.value.item_name)) {
+			for (const ThemeItemBind &F : E->value) {
+				if (inherited_props.has(F.item_name)) {
 					continue; // Skip inherited properties.
 				}
-				if (F.value.external || F.value.class_name != p_class_name) {
-					inherited_props.insert(F.value.item_name);
-					continue; // Track properties defined in parent classes, and skip them.
+				if (F.external || F.class_name != p_class_name) {
+					inherited_props.insert(F.item_name);
+
+					if (!p_include_inherited) {
+						continue; // Track properties defined in parent classes, and skip them.
+					}
 				}
 
-				r_list->push_back(F.value);
+				r_list->push_back(F);
 			}
 		}
 	}
 }
 
+void ThemeDB::_sort_theme_items() {
+	for (KeyValue<StringName, List<ThemeDB::ThemeItemBind>> &E : theme_item_binds_list) {
+		E.value.sort_custom<ThemeItemBind::SortByType>();
+	}
+}
+
 // Object methods.
 
 void ThemeDB::_bind_methods() {
@@ -435,6 +446,9 @@ ThemeDB *ThemeDB::get_singleton() {
 
 ThemeDB::ThemeDB() {
 	singleton = this;
+	if (MessageQueue::get_singleton()) { // May not exist in tests etc.
+		callable_mp(this, &ThemeDB::_sort_theme_items).call_deferred();
+	}
 }
 
 ThemeDB::~ThemeDB() {

+ 10 - 1
scene/theme/theme_db.h

@@ -107,10 +107,19 @@ public:
 		bool external = false;
 
 		ThemeItemSetter setter;
+
+		struct SortByType {
+			_FORCE_INLINE_ bool operator()(const ThemeItemBind &l, const ThemeItemBind &r) const {
+				return l.data_type < r.data_type;
+			}
+		};
 	};
 
 private:
 	HashMap<StringName, HashMap<StringName, ThemeItemBind>> theme_item_binds;
+	HashMap<StringName, List<ThemeItemBind>> theme_item_binds_list; // Used for listing purposes.
+
+	void _sort_theme_items();
 
 protected:
 	static void _bind_methods();
@@ -162,7 +171,7 @@ public:
 	void bind_class_external_item(Theme::DataType p_data_type, const StringName &p_class_name, const StringName &p_prop_name, const StringName &p_item_name, const StringName &p_type_name, ThemeItemSetter p_setter);
 	void update_class_instance_items(Node *p_instance);
 
-	void get_class_own_items(const StringName &p_class_name, List<ThemeItemBind> *r_list);
+	void get_class_items(const StringName &p_class_name, List<ThemeItemBind> *r_list, bool p_include_inherited = false);
 
 	// Memory management, reference, and initialization.