ソースを参照

Reorganize Theme resource code for better maintainability

Yuri Sizov 3 年 前
コミット
cd45a70f2d
2 ファイル変更429 行追加409 行削除
  1. 424 408
      scene/resources/theme.cpp
  2. 5 1
      scene/resources/theme.h

+ 424 - 408
scene/resources/theme.cpp

@@ -29,221 +29,18 @@
 /*************************************************************************/
 
 #include "theme.h"
-#include "core/os/file_access.h"
 #include "core/print_string.h"
 
-void Theme::_emit_theme_changed() {
-	if (no_change_propagation) {
-		return;
-	}
-
-	_change_notify();
-	emit_changed();
-}
-
-PoolVector<String> Theme::_get_icon_list(const String &p_node_type) const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_icon_list(p_node_type, &il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_icon_types() const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_icon_types(&il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_stylebox_list(const String &p_node_type) const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_stylebox_list(p_node_type, &il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_stylebox_types() const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_stylebox_types(&il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_font_list(const String &p_node_type) const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_font_list(p_node_type, &il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_font_types() const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_font_types(&il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_color_list(const String &p_node_type) const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_color_list(p_node_type, &il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_color_types() const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_color_types(&il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_constant_list(const String &p_node_type) const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_constant_list(p_node_type, &il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_constant_types() const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_constant_types(&il);
-	ilret.resize(il.size());
-
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
-
-PoolVector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_node_type) const {
-	switch (p_data_type) {
-		case DATA_TYPE_COLOR:
-			return _get_color_list(p_node_type);
-		case DATA_TYPE_CONSTANT:
-			return _get_constant_list(p_node_type);
-		case DATA_TYPE_FONT:
-			return _get_font_list(p_node_type);
-		case DATA_TYPE_ICON:
-			return _get_icon_list(p_node_type);
-		case DATA_TYPE_STYLEBOX:
-			return _get_stylebox_list(p_node_type);
-		case DATA_TYPE_MAX:
-			break; // Can't happen, but silences warning.
-	}
-
-	return PoolVector<String>();
-}
-
-PoolVector<String> Theme::_get_theme_item_types(DataType p_data_type) const {
-	switch (p_data_type) {
-		case DATA_TYPE_COLOR:
-			return _get_color_types();
-		case DATA_TYPE_CONSTANT:
-			return _get_constant_types();
-		case DATA_TYPE_FONT:
-			return _get_font_types();
-		case DATA_TYPE_ICON:
-			return _get_icon_types();
-		case DATA_TYPE_STYLEBOX:
-			return _get_stylebox_types();
-		case DATA_TYPE_MAX:
-			break; // Can't happen, but silences warning.
-	}
-
-	return PoolVector<String>();
-}
-
-PoolVector<String> Theme::_get_type_list(const String &p_node_type) const {
-	PoolVector<String> ilret;
-	List<StringName> il;
-
-	get_type_list(&il);
-	ilret.resize(il.size());
+// Universal Theme resources used when no other theme has the item.
+Ref<Theme> Theme::default_theme;
+Ref<Theme> Theme::project_default_theme;
 
-	int i = 0;
-	PoolVector<String>::Write w = ilret.write();
-	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
-		w[i] = E->get();
-	}
-	return ilret;
-}
+// Universal default values, final fallback for every theme.
+Ref<Texture> Theme::default_icon;
+Ref<StyleBox> Theme::default_style;
+Ref<Font> Theme::default_font;
 
+// Dynamic properties.
 bool Theme::_set(const StringName &p_name, const Variant &p_value) {
 	String sname = p_name;
 
@@ -371,34 +168,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
 	}
 }
 
-void Theme::set_default_theme_font(const Ref<Font> &p_default_font) {
-	if (default_theme_font == p_default_font) {
-		return;
-	}
-
-	if (default_theme_font.is_valid()) {
-		default_theme_font->disconnect("changed", this, "_emit_theme_changed");
-	}
-
-	default_theme_font = p_default_font;
-
-	if (default_theme_font.is_valid()) {
-		default_theme_font->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
-	}
-
-	_emit_theme_changed();
-}
-
-Ref<Font> Theme::get_default_theme_font() const {
-	return default_theme_font;
-}
-
-Ref<Theme> Theme::project_default_theme;
-Ref<Theme> Theme::default_theme;
-Ref<Texture> Theme::default_icon;
-Ref<StyleBox> Theme::default_style;
-Ref<Font> Theme::default_font;
-
+// Universal fallback Theme resources.
 Ref<Theme> Theme::get_default() {
 	return default_theme;
 }
@@ -415,6 +185,7 @@ void Theme::set_project_default(const Ref<Theme> &p_project_default) {
 	project_default_theme = p_project_default;
 }
 
+// Universal fallback values for theme item types.
 void Theme::set_default_icon(const Ref<Texture> &p_icon) {
 	default_icon = p_icon;
 }
@@ -427,18 +198,42 @@ void Theme::set_default_font(const Ref<Font> &p_font) {
 	default_font = p_font;
 }
 
-void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture> &p_icon) {
-	if (icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) {
-		icon_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
+// Fallback values for theme item types, configurable per theme.
+void Theme::set_default_theme_font(const Ref<Font> &p_default_font) {
+	if (default_theme_font == p_default_font) {
+		return;
 	}
 
-	icon_map[p_node_type][p_name] = p_icon;
-
-	if (p_icon.is_valid()) {
-		icon_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
+	if (default_theme_font.is_valid()) {
+		default_theme_font->disconnect("changed", this, "_emit_theme_changed");
 	}
 
-	_emit_theme_changed();
+	default_theme_font = p_default_font;
+
+	if (default_theme_font.is_valid()) {
+		default_theme_font->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
+	}
+
+	_emit_theme_changed();
+}
+
+Ref<Font> Theme::get_default_theme_font() const {
+	return default_theme_font;
+}
+
+// Icons.
+void Theme::set_icon(const StringName &p_name, const StringName &p_node_type, const Ref<Texture> &p_icon) {
+	if (icon_map[p_node_type].has(p_name) && icon_map[p_node_type][p_name].is_valid()) {
+		icon_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
+	}
+
+	icon_map[p_node_type][p_name] = p_icon;
+
+	if (p_icon.is_valid()) {
+		icon_map[p_node_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED);
+	}
+
+	_emit_theme_changed();
 }
 
 Ref<Texture> Theme::get_icon(const StringName &p_name, const StringName &p_node_type) const {
@@ -511,6 +306,7 @@ void Theme::get_icon_types(List<StringName> *p_list) const {
 	}
 }
 
+// Shaders.
 void Theme::set_shader(const StringName &p_name, const StringName &p_node_type, const Ref<Shader> &p_shader) {
 	shader_map[p_node_type][p_name] = p_shader;
 
@@ -552,6 +348,7 @@ void Theme::get_shader_list(const StringName &p_node_type, List<StringName> *p_l
 	}
 }
 
+// Styleboxes.
 void Theme::set_stylebox(const StringName &p_name, const StringName &p_node_type, const Ref<StyleBox> &p_style) {
 	if (style_map[p_node_type].has(p_name) && style_map[p_node_type][p_name].is_valid()) {
 		style_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
@@ -636,6 +433,7 @@ void Theme::get_stylebox_types(List<StringName> *p_list) const {
 	}
 }
 
+// Fonts.
 void Theme::set_font(const StringName &p_name, const StringName &p_node_type, const Ref<Font> &p_font) {
 	if (font_map[p_node_type][p_name].is_valid()) {
 		font_map[p_node_type][p_name]->disconnect("changed", this, "_emit_theme_changed");
@@ -722,6 +520,7 @@ void Theme::get_font_types(List<StringName> *p_list) const {
 	}
 }
 
+// Colors.
 void Theme::set_color(const StringName &p_name, const StringName &p_node_type, const Color &p_color) {
 	color_map[p_node_type][p_name] = p_color;
 
@@ -794,6 +593,7 @@ void Theme::get_color_types(List<StringName> *p_list) const {
 	}
 }
 
+// Theme constants.
 void Theme::set_constant(const StringName &p_name, const StringName &p_node_type, int p_constant) {
 	constant_map[p_node_type][p_name] = p_constant;
 
@@ -866,6 +666,7 @@ void Theme::get_constant_types(List<StringName> *p_list) const {
 	}
 }
 
+// Generic methods for managing theme items.
 void Theme::set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type, const Variant &p_value) {
 	switch (p_data_type) {
 		case DATA_TYPE_COLOR: {
@@ -957,117 +758,371 @@ bool Theme::has_theme_item_nocheck(DataType p_data_type, const StringName &p_nam
 			break; // Can't happen, but silences warning.
 	}
 
-	return false;
+	return false;
+}
+
+void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
+	switch (p_data_type) {
+		case DATA_TYPE_COLOR:
+			rename_color(p_old_name, p_name, p_node_type);
+			break;
+		case DATA_TYPE_CONSTANT:
+			rename_constant(p_old_name, p_name, p_node_type);
+			break;
+		case DATA_TYPE_FONT:
+			rename_font(p_old_name, p_name, p_node_type);
+			break;
+		case DATA_TYPE_ICON:
+			rename_icon(p_old_name, p_name, p_node_type);
+			break;
+		case DATA_TYPE_STYLEBOX:
+			rename_stylebox(p_old_name, p_name, p_node_type);
+			break;
+		case DATA_TYPE_MAX:
+			break; // Can't happen, but silences warning.
+	}
+}
+
+void Theme::clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) {
+	switch (p_data_type) {
+		case DATA_TYPE_COLOR:
+			clear_color(p_name, p_node_type);
+			break;
+		case DATA_TYPE_CONSTANT:
+			clear_constant(p_name, p_node_type);
+			break;
+		case DATA_TYPE_FONT:
+			clear_font(p_name, p_node_type);
+			break;
+		case DATA_TYPE_ICON:
+			clear_icon(p_name, p_node_type);
+			break;
+		case DATA_TYPE_STYLEBOX:
+			clear_stylebox(p_name, p_node_type);
+			break;
+		case DATA_TYPE_MAX:
+			break; // Can't happen, but silences warning.
+	}
+}
+
+void Theme::get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const {
+	switch (p_data_type) {
+		case DATA_TYPE_COLOR:
+			get_color_list(p_node_type, p_list);
+			break;
+		case DATA_TYPE_CONSTANT:
+			get_constant_list(p_node_type, p_list);
+			break;
+		case DATA_TYPE_FONT:
+			get_font_list(p_node_type, p_list);
+			break;
+		case DATA_TYPE_ICON:
+			get_icon_list(p_node_type, p_list);
+			break;
+		case DATA_TYPE_STYLEBOX:
+			get_stylebox_list(p_node_type, p_list);
+			break;
+		case DATA_TYPE_MAX:
+			break; // Can't happen, but silences warning.
+	}
+}
+
+void Theme::add_theme_item_type(DataType p_data_type, const StringName &p_node_type) {
+	switch (p_data_type) {
+		case DATA_TYPE_COLOR:
+			add_color_type(p_node_type);
+			break;
+		case DATA_TYPE_CONSTANT:
+			add_constant_type(p_node_type);
+			break;
+		case DATA_TYPE_FONT:
+			add_font_type(p_node_type);
+			break;
+		case DATA_TYPE_ICON:
+			add_icon_type(p_node_type);
+			break;
+		case DATA_TYPE_STYLEBOX:
+			add_stylebox_type(p_node_type);
+			break;
+		case DATA_TYPE_MAX:
+			break; // Can't happen, but silences warning.
+	}
+}
+
+void Theme::get_theme_item_types(DataType p_data_type, List<StringName> *p_list) const {
+	switch (p_data_type) {
+		case DATA_TYPE_COLOR:
+			get_color_types(p_list);
+			break;
+		case DATA_TYPE_CONSTANT:
+			get_constant_types(p_list);
+			break;
+		case DATA_TYPE_FONT:
+			get_font_types(p_list);
+			break;
+		case DATA_TYPE_ICON:
+			get_icon_types(p_list);
+			break;
+		case DATA_TYPE_STYLEBOX:
+			get_stylebox_types(p_list);
+			break;
+		case DATA_TYPE_MAX:
+			break; // Can't happen, but silences warning.
+	}
+}
+
+// Theme types.
+void Theme::get_type_list(List<StringName> *p_list) const {
+	ERR_FAIL_NULL(p_list);
+
+	Set<StringName> types;
+	const StringName *key = nullptr;
+
+	while ((key = icon_map.next(key))) {
+		types.insert(*key);
+	}
+
+	key = nullptr;
+
+	while ((key = style_map.next(key))) {
+		types.insert(*key);
+	}
+
+	key = nullptr;
+
+	while ((key = font_map.next(key))) {
+		types.insert(*key);
+	}
+
+	key = nullptr;
+
+	while ((key = color_map.next(key))) {
+		types.insert(*key);
+	}
+
+	key = nullptr;
+
+	while ((key = constant_map.next(key))) {
+		types.insert(*key);
+	}
+
+	for (Set<StringName>::Element *E = types.front(); E; E = E->next()) {
+		p_list->push_back(E->get());
+	}
+}
+
+// Internal methods for getting lists as a Vector of String (compatible with public API).
+PoolVector<String> Theme::_get_icon_list(const String &p_node_type) const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_icon_list(p_node_type, &il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
+}
+
+PoolVector<String> Theme::_get_icon_types() const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_icon_types(&il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
+}
+
+PoolVector<String> Theme::_get_stylebox_list(const String &p_node_type) const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_stylebox_list(p_node_type, &il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
+}
+
+PoolVector<String> Theme::_get_stylebox_types() const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_stylebox_types(&il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
+}
+
+PoolVector<String> Theme::_get_font_list(const String &p_node_type) const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_font_list(p_node_type, &il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
+}
+
+PoolVector<String> Theme::_get_font_types() const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_font_types(&il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
+}
+
+PoolVector<String> Theme::_get_color_list(const String &p_node_type) const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_color_list(p_node_type, &il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
+}
+
+PoolVector<String> Theme::_get_color_types() const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_color_types(&il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
+}
+
+PoolVector<String> Theme::_get_constant_list(const String &p_node_type) const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_constant_list(p_node_type, &il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
+	}
+	return ilret;
 }
 
-void Theme::rename_theme_item(DataType p_data_type, const StringName &p_old_name, const StringName &p_name, const StringName &p_node_type) {
-	switch (p_data_type) {
-		case DATA_TYPE_COLOR:
-			rename_color(p_old_name, p_name, p_node_type);
-			break;
-		case DATA_TYPE_CONSTANT:
-			rename_constant(p_old_name, p_name, p_node_type);
-			break;
-		case DATA_TYPE_FONT:
-			rename_font(p_old_name, p_name, p_node_type);
-			break;
-		case DATA_TYPE_ICON:
-			rename_icon(p_old_name, p_name, p_node_type);
-			break;
-		case DATA_TYPE_STYLEBOX:
-			rename_stylebox(p_old_name, p_name, p_node_type);
-			break;
-		case DATA_TYPE_MAX:
-			break; // Can't happen, but silences warning.
+PoolVector<String> Theme::_get_constant_types() const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_constant_types(&il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
 	}
+	return ilret;
 }
 
-void Theme::clear_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_node_type) {
+PoolVector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_node_type) const {
 	switch (p_data_type) {
 		case DATA_TYPE_COLOR:
-			clear_color(p_name, p_node_type);
-			break;
+			return _get_color_list(p_node_type);
 		case DATA_TYPE_CONSTANT:
-			clear_constant(p_name, p_node_type);
-			break;
+			return _get_constant_list(p_node_type);
 		case DATA_TYPE_FONT:
-			clear_font(p_name, p_node_type);
-			break;
+			return _get_font_list(p_node_type);
 		case DATA_TYPE_ICON:
-			clear_icon(p_name, p_node_type);
-			break;
+			return _get_icon_list(p_node_type);
 		case DATA_TYPE_STYLEBOX:
-			clear_stylebox(p_name, p_node_type);
-			break;
+			return _get_stylebox_list(p_node_type);
 		case DATA_TYPE_MAX:
 			break; // Can't happen, but silences warning.
 	}
+
+	return PoolVector<String>();
 }
 
-void Theme::get_theme_item_list(DataType p_data_type, StringName p_node_type, List<StringName> *p_list) const {
+PoolVector<String> Theme::_get_theme_item_types(DataType p_data_type) const {
 	switch (p_data_type) {
 		case DATA_TYPE_COLOR:
-			get_color_list(p_node_type, p_list);
-			break;
+			return _get_color_types();
 		case DATA_TYPE_CONSTANT:
-			get_constant_list(p_node_type, p_list);
-			break;
+			return _get_constant_types();
 		case DATA_TYPE_FONT:
-			get_font_list(p_node_type, p_list);
-			break;
+			return _get_font_types();
 		case DATA_TYPE_ICON:
-			get_icon_list(p_node_type, p_list);
-			break;
+			return _get_icon_types();
 		case DATA_TYPE_STYLEBOX:
-			get_stylebox_list(p_node_type, p_list);
-			break;
+			return _get_stylebox_types();
 		case DATA_TYPE_MAX:
 			break; // Can't happen, but silences warning.
 	}
+
+	return PoolVector<String>();
 }
 
-void Theme::add_theme_item_type(DataType p_data_type, const StringName &p_node_type) {
-	switch (p_data_type) {
-		case DATA_TYPE_COLOR:
-			add_color_type(p_node_type);
-			break;
-		case DATA_TYPE_CONSTANT:
-			add_constant_type(p_node_type);
-			break;
-		case DATA_TYPE_FONT:
-			add_font_type(p_node_type);
-			break;
-		case DATA_TYPE_ICON:
-			add_icon_type(p_node_type);
-			break;
-		case DATA_TYPE_STYLEBOX:
-			add_stylebox_type(p_node_type);
-			break;
-		case DATA_TYPE_MAX:
-			break; // Can't happen, but silences warning.
+PoolVector<String> Theme::_get_type_list(const String &p_node_type) const {
+	PoolVector<String> ilret;
+	List<StringName> il;
+
+	get_type_list(&il);
+	ilret.resize(il.size());
+
+	int i = 0;
+	PoolVector<String>::Write w = ilret.write();
+	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) {
+		w[i] = E->get();
 	}
+	return ilret;
 }
 
-void Theme::get_theme_item_types(DataType p_data_type, List<StringName> *p_list) const {
-	switch (p_data_type) {
-		case DATA_TYPE_COLOR:
-			get_color_types(p_list);
-			break;
-		case DATA_TYPE_CONSTANT:
-			get_constant_types(p_list);
-			break;
-		case DATA_TYPE_FONT:
-			get_font_types(p_list);
-			break;
-		case DATA_TYPE_ICON:
-			get_icon_types(p_list);
-			break;
-		case DATA_TYPE_STYLEBOX:
-			get_stylebox_types(p_list);
-			break;
-		case DATA_TYPE_MAX:
-			break; // Can't happen, but silences warning.
+// Theme bulk manipulations.
+void Theme::_emit_theme_changed() {
+	if (no_change_propagation) {
+		return;
 	}
+
+	_change_notify();
+	emit_changed();
 }
 
 void Theme::_freeze_change_propagation() {
@@ -1079,57 +1134,6 @@ void Theme::_unfreeze_and_propagate_changes() {
 	_emit_theme_changed();
 }
 
-void Theme::clear() {
-	//these need disconnecting
-	{
-		const StringName *K = nullptr;
-		while ((K = icon_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = icon_map[*K].next(L))) {
-				Ref<Texture> icon = icon_map[*K][*L];
-				if (icon.is_valid()) {
-					icon->disconnect("changed", this, "_emit_theme_changed");
-				}
-			}
-		}
-	}
-
-	{
-		const StringName *K = nullptr;
-		while ((K = style_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = style_map[*K].next(L))) {
-				Ref<StyleBox> style = style_map[*K][*L];
-				if (style.is_valid()) {
-					style->disconnect("changed", this, "_emit_theme_changed");
-				}
-			}
-		}
-	}
-
-	{
-		const StringName *K = nullptr;
-		while ((K = font_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = font_map[*K].next(L))) {
-				Ref<Font> font = font_map[*K][*L];
-				if (font.is_valid()) {
-					font->disconnect("changed", this, "_emit_theme_changed");
-				}
-			}
-		}
-	}
-
-	icon_map.clear();
-	style_map.clear();
-	font_map.clear();
-	shader_map.clear();
-	color_map.clear();
-	constant_map.clear();
-
-	_emit_theme_changed();
-}
-
 void Theme::copy_default_theme() {
 	Ref<Theme> default_theme2 = get_default();
 	copy_theme(default_theme2);
@@ -1258,43 +1262,55 @@ void Theme::merge_with(const Ref<Theme> &p_other) {
 	_unfreeze_and_propagate_changes();
 }
 
-void Theme::get_type_list(List<StringName> *p_list) const {
-	ERR_FAIL_NULL(p_list);
-
-	Set<StringName> types;
-	const StringName *key = nullptr;
-
-	while ((key = icon_map.next(key))) {
-		types.insert(*key);
-	}
-
-	key = nullptr;
-
-	while ((key = style_map.next(key))) {
-		types.insert(*key);
+void Theme::clear() {
+	//these need disconnecting
+	{
+		const StringName *K = nullptr;
+		while ((K = icon_map.next(K))) {
+			const StringName *L = nullptr;
+			while ((L = icon_map[*K].next(L))) {
+				Ref<Texture> icon = icon_map[*K][*L];
+				if (icon.is_valid()) {
+					icon->disconnect("changed", this, "_emit_theme_changed");
+				}
+			}
+		}
 	}
 
-	key = nullptr;
-
-	while ((key = font_map.next(key))) {
-		types.insert(*key);
+	{
+		const StringName *K = nullptr;
+		while ((K = style_map.next(K))) {
+			const StringName *L = nullptr;
+			while ((L = style_map[*K].next(L))) {
+				Ref<StyleBox> style = style_map[*K][*L];
+				if (style.is_valid()) {
+					style->disconnect("changed", this, "_emit_theme_changed");
+				}
+			}
+		}
 	}
 
-	key = nullptr;
-
-	while ((key = color_map.next(key))) {
-		types.insert(*key);
+	{
+		const StringName *K = nullptr;
+		while ((K = font_map.next(K))) {
+			const StringName *L = nullptr;
+			while ((L = font_map[*K].next(L))) {
+				Ref<Font> font = font_map[*K][*L];
+				if (font.is_valid()) {
+					font->disconnect("changed", this, "_emit_theme_changed");
+				}
+			}
+		}
 	}
 
-	key = nullptr;
-
-	while ((key = constant_map.next(key))) {
-		types.insert(*key);
-	}
+	icon_map.clear();
+	style_map.clear();
+	font_map.clear();
+	shader_map.clear();
+	color_map.clear();
+	constant_map.clear();
 
-	for (Set<StringName>::Element *E = types.front(); E; E = E->next()) {
-		p_list->push_back(E->get());
-	}
+	_emit_theme_changed();
 }
 
 void Theme::_bind_methods() {

+ 5 - 1
scene/resources/theme.h

@@ -90,12 +90,16 @@ protected:
 	bool _get(const StringName &p_name, Variant &r_ret) const;
 	void _get_property_list(List<PropertyInfo> *p_list) const;
 
-	static Ref<Theme> project_default_theme;
+	// Universal Theme resources used when no other theme has the item.
 	static Ref<Theme> default_theme;
+	static Ref<Theme> project_default_theme;
+
+	// Universal default values, final fallback for every theme.
 	static Ref<Texture> default_icon;
 	static Ref<StyleBox> default_style;
 	static Ref<Font> default_font;
 
+	// Default values configurable for each individual theme.
 	Ref<Font> default_theme_font;
 
 	static void _bind_methods();