Browse Source

Implement #32347 - RichTextLabel's Item and Item* structs should not inherit Object, it's too expensive

Relintai 5 years ago
parent
commit
25704e81fa

+ 4 - 0
scene/gui/rich_text_effect.cpp

@@ -120,3 +120,7 @@ CharFXTransform::CharFXTransform() {
 	color = Color();
 	color = Color();
 	character = 0;
 	character = 0;
 }
 }
+
+CharFXTransform::~CharFXTransform() {
+	environment.clear();
+}

+ 2 - 0
scene/gui/rich_text_effect.h

@@ -64,6 +64,8 @@ public:
 	Dictionary environment;
 	Dictionary environment;
 
 
 	CharFXTransform();
 	CharFXTransform();
+	~CharFXTransform();
+
 	uint64_t get_relative_index() { return relative_index; }
 	uint64_t get_relative_index() { return relative_index; }
 	void set_relative_index(uint64_t p_index) { relative_index = p_index; }
 	void set_relative_index(uint64_t p_index) { relative_index = p_index; }
 	uint64_t get_absolute_index() { return absolute_index; }
 	uint64_t get_absolute_index() { return absolute_index; }

+ 57 - 28
scene/gui/rich_text_label.cpp

@@ -348,6 +348,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 				int it_char_start = p_char_count;
 				int it_char_start = p_char_count;
 
 
 				Vector<ItemFX *> fx_stack = Vector<ItemFX *>();
 				Vector<ItemFX *> fx_stack = Vector<ItemFX *>();
+				_fetch_item_fx_stack(text, fx_stack);
 				bool custom_fx_ok = true;
 				bool custom_fx_ok = true;
 
 
 				if (p_mode == PROCESS_DRAW) {
 				if (p_mode == PROCESS_DRAW) {
@@ -359,8 +360,14 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 						strikethrough = true;
 						strikethrough = true;
 					}
 					}
 
 
-					fade = _fetch_by_type<ItemFade>(text, ITEM_FADE);
-					_fetch_item_stack<ItemFX>(text, fx_stack);
+					Item *fade_item = it;
+					while (fade_item) {
+						if (fade_item->type == ITEM_FADE) {
+							fade = static_cast<ItemFade *>(fade_item);
+							break;
+						}
+						fade_item = fade_item->parent;
+					}
 
 
 				} else if (p_mode == PROCESS_CACHE) {
 				} else if (p_mode == PROCESS_CACHE) {
 					l.char_count += text->text.length();
 					l.char_count += text->text.length();
@@ -467,18 +474,16 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 																				 faded_visibility > 0.0f);
 																				 faded_visibility > 0.0f);
 
 
 								for (int j = 0; j < fx_stack.size(); j++) {
 								for (int j = 0; j < fx_stack.size(); j++) {
-									ItemCustomFX *item_custom = Object::cast_to<ItemCustomFX>(fx_stack[j]);
-									ItemShake *item_shake = Object::cast_to<ItemShake>(fx_stack[j]);
-									ItemWave *item_wave = Object::cast_to<ItemWave>(fx_stack[j]);
-									ItemTornado *item_tornado = Object::cast_to<ItemTornado>(fx_stack[j]);
-									ItemRainbow *item_rainbow = Object::cast_to<ItemRainbow>(fx_stack[j]);
-
-									if (item_custom && custom_fx_ok) {
-										Ref<CharFXTransform> charfx = Ref<CharFXTransform>(memnew(CharFXTransform));
-										Ref<RichTextEffect> custom_effect = _get_custom_effect_by_code(item_custom->identifier);
+									ItemFX *item_fx = fx_stack[j];
+
+									if (item_fx->type == ITEM_CUSTOMFX && custom_fx_ok) {
+										ItemCustomFX *item_custom = static_cast<ItemCustomFX *>(item_fx);
+
+										Ref<CharFXTransform> charfx = item_custom->char_fx_transform;
+										Ref<RichTextEffect> custom_effect = item_custom->custom_effect;
+
 										if (!custom_effect.is_null()) {
 										if (!custom_effect.is_null()) {
 											charfx->elapsed_time = item_custom->elapsed_time;
 											charfx->elapsed_time = item_custom->elapsed_time;
-											charfx->environment = item_custom->environment;
 											charfx->relative_index = c_item_offset;
 											charfx->relative_index = c_item_offset;
 											charfx->absolute_index = p_char_count;
 											charfx->absolute_index = p_char_count;
 											charfx->visibility = visible;
 											charfx->visibility = visible;
@@ -494,7 +499,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 											visible &= charfx->visibility;
 											visible &= charfx->visibility;
 											fx_char = charfx->character;
 											fx_char = charfx->character;
 										}
 										}
-									} else if (item_shake) {
+									} else if (item_fx->type == ITEM_SHAKE) {
+										ItemShake *item_shake = static_cast<ItemShake *>(item_fx);
+
 										uint64_t char_current_rand = item_shake->offset_random(c_item_offset);
 										uint64_t char_current_rand = item_shake->offset_random(c_item_offset);
 										uint64_t char_previous_rand = item_shake->offset_previous_random(c_item_offset);
 										uint64_t char_previous_rand = item_shake->offset_previous_random(c_item_offset);
 										uint64_t max_rand = 2147483647;
 										uint64_t max_rand = 2147483647;
@@ -509,14 +516,20 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 																	 Math::cos(current_offset),
 																	 Math::cos(current_offset),
 																	 n_time)) *
 																	 n_time)) *
 													 (float)item_shake->strength / 10.0f;
 													 (float)item_shake->strength / 10.0f;
-									} else if (item_wave) {
+									} else if (item_fx->type == ITEM_WAVE) {
+										ItemWave *item_wave = static_cast<ItemWave *>(item_fx);
+
 										double value = Math::sin(item_wave->frequency * item_wave->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_wave->amplitude / 10.0f);
 										double value = Math::sin(item_wave->frequency * item_wave->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_wave->amplitude / 10.0f);
 										fx_offset += Point2(0, 1) * value;
 										fx_offset += Point2(0, 1) * value;
-									} else if (item_tornado) {
+									} else if (item_fx->type == ITEM_TORNADO) {
+										ItemTornado *item_tornado = static_cast<ItemTornado *>(item_fx);
+
 										double torn_x = Math::sin(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_tornado->radius);
 										double torn_x = Math::sin(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_tornado->radius);
 										double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_tornado->radius);
 										double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + pofs) / 50)) * (item_tornado->radius);
 										fx_offset += Point2(torn_x, torn_y);
 										fx_offset += Point2(torn_x, torn_y);
-									} else if (item_rainbow) {
+									} else if (item_fx->type == ITEM_RAINBOW) {
+										ItemRainbow *item_rainbow = static_cast<ItemRainbow *>(item_fx);
+
 										fx_color = fx_color.from_hsv(item_rainbow->frequency * (item_rainbow->elapsed_time + ((p_ofs.x + pofs) / 50)),
 										fx_color = fx_color.from_hsv(item_rainbow->frequency * (item_rainbow->elapsed_time + ((p_ofs.x + pofs) / 50)),
 												item_rainbow->saturation,
 												item_rainbow->saturation,
 												item_rainbow->value,
 												item_rainbow->value,
@@ -884,7 +897,11 @@ void RichTextLabel::_update_scroll() {
 void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, float p_delta_time) {
 void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, float p_delta_time) {
 	Item *it = p_frame;
 	Item *it = p_frame;
 	while (it) {
 	while (it) {
-		ItemFX *ifx = Object::cast_to<ItemFX>(it);
+		ItemFX *ifx = NULL;
+
+		if (it->type == ITEM_CUSTOMFX || it->type == ITEM_SHAKE || it->type == ITEM_WAVE || it->type == ITEM_TORNADO || it->type == ITEM_RAINBOW) {
+			ifx = static_cast<ItemFX *>(it);
+		}
 
 
 		if (!ifx) {
 		if (!ifx) {
 			it = _get_next_item(it, true);
 			it = _get_next_item(it, true);
@@ -893,7 +910,12 @@ void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, float p_delta_
 
 
 		ifx->elapsed_time += p_delta_time;
 		ifx->elapsed_time += p_delta_time;
 
 
-		ItemShake *shake = Object::cast_to<ItemShake>(it);
+		ItemShake *shake = NULL;
+
+		if (it->type == ITEM_SHAKE) {
+			shake = static_cast<ItemShake *>(it);
+		}
+
 		if (shake) {
 		if (shake) {
 			bool cycle = (shake->elapsed_time > (1.0f / shake->rate));
 			bool cycle = (shake->elapsed_time > (1.0f / shake->rate));
 			if (cycle) {
 			if (cycle) {
@@ -983,9 +1005,6 @@ void RichTextLabel::_notification(int p_what) {
 		case NOTIFICATION_INTERNAL_PROCESS: {
 		case NOTIFICATION_INTERNAL_PROCESS: {
 			float dt = get_process_delta_time();
 			float dt = get_process_delta_time();
 
 
-			for (int i = 0; i < custom_effects.size(); i++) {
-			}
-
 			_update_fx(main, dt);
 			_update_fx(main, dt);
 			update();
 			update();
 		}
 		}
@@ -1408,6 +1427,17 @@ bool RichTextLabel::_find_by_type(Item *p_item, ItemType p_type) {
 	return false;
 	return false;
 }
 }
 
 
+void RichTextLabel::_fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack) {
+	Item *item = p_item;
+	while (item) {
+		if (item->type == ITEM_CUSTOMFX || item->type == ITEM_SHAKE || item->type == ITEM_WAVE || item->type == ITEM_TORNADO || item->type == ITEM_RAINBOW) {
+			r_stack.push_back(static_cast<ItemFX *>(item));
+		}
+
+		item = item->parent;
+	}
+}
+
 bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item) {
 bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item) {
 	Item *item = p_item;
 	Item *item = p_item;
 
 
@@ -1776,10 +1806,10 @@ void RichTextLabel::push_rainbow(float p_saturation, float p_value, float p_freq
 	_add_item(item, true);
 	_add_item(item, true);
 }
 }
 
 
-void RichTextLabel::push_customfx(String p_identifier, Dictionary p_environment) {
+void RichTextLabel::push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionary p_environment) {
 	ItemCustomFX *item = memnew(ItemCustomFX);
 	ItemCustomFX *item = memnew(ItemCustomFX);
-	item->identifier = p_identifier;
-	item->environment = p_environment;
+	item->custom_effect = p_custom_effect;
+	item->char_fx_transform->environment = p_environment;
 	_add_item(item, true);
 	_add_item(item, true);
 }
 }
 
 
@@ -2287,7 +2317,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 				Ref<RichTextEffect> effect = _get_custom_effect_by_code(identifier);
 				Ref<RichTextEffect> effect = _get_custom_effect_by_code(identifier);
 
 
 				if (!effect.is_null()) {
 				if (!effect.is_null()) {
-					push_customfx(identifier, properties);
+					push_customfx(effect, properties);
 					pos = brk_end + 1;
 					pos = brk_end + 1;
 					tag_stack.push_front(identifier);
 					tag_stack.push_front(identifier);
 					set_process_internal(true);
 					set_process_internal(true);
@@ -2700,17 +2730,16 @@ Size2 RichTextLabel::get_minimum_size() const {
 }
 }
 
 
 Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_identifier) {
 Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_identifier) {
-	Ref<RichTextEffect> r;
 	for (int i = 0; i < custom_effects.size(); i++) {
 	for (int i = 0; i < custom_effects.size(); i++) {
 		if (!custom_effects[i].is_valid())
 		if (!custom_effects[i].is_valid())
 			continue;
 			continue;
 
 
 		if (custom_effects[i]->get_bbcode() == p_bbcode_identifier) {
 		if (custom_effects[i]->get_bbcode() == p_bbcode_identifier) {
-			r = custom_effects[i];
+			return custom_effects[i];
 		}
 		}
 	}
 	}
 
 
-	return r;
+	return Ref<RichTextEffect>();
 }
 }
 
 
 Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressions) {
 Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressions) {

+ 31 - 117
scene/gui/rich_text_label.h

@@ -81,7 +81,7 @@ protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 private:
 private:
-	class Item;
+	struct Item;
 
 
 	struct Line {
 	struct Line {
 
 
@@ -103,10 +103,7 @@ private:
 		}
 		}
 	};
 	};
 
 
-	class Item : public Object {
-		GDCLASS(Item, Object);
-
-	public:
+	struct Item {
 		int index;
 		int index;
 		Item *parent;
 		Item *parent;
 		ItemType type;
 		ItemType type;
@@ -129,10 +126,7 @@ private:
 		virtual ~Item() { _clear_children(); }
 		virtual ~Item() { _clear_children(); }
 	};
 	};
 
 
-	class ItemFrame : public Item {
-		GDCLASS(ItemFrame, Item);
-
-	public:
+	struct ItemFrame : public Item {
 		int parent_line;
 		int parent_line;
 		bool cell;
 		bool cell;
 		Vector<Line> lines;
 		Vector<Line> lines;
@@ -147,95 +141,59 @@ private:
 		}
 		}
 	};
 	};
 
 
-	class ItemText : public Item {
-		GDCLASS(ItemText, Item);
-
-	public:
+	struct ItemText : public Item {
 		String text;
 		String text;
 		ItemText() { type = ITEM_TEXT; }
 		ItemText() { type = ITEM_TEXT; }
 	};
 	};
 
 
-	class ItemImage : public Item {
-		GDCLASS(ItemImage, Item);
-
-	public:
+	struct ItemImage : public Item {
 		Ref<Texture> image;
 		Ref<Texture> image;
 		ItemImage() { type = ITEM_IMAGE; }
 		ItemImage() { type = ITEM_IMAGE; }
 	};
 	};
 
 
-	class ItemFont : public Item {
-		GDCLASS(ItemFont, Item);
-
-	public:
+	struct ItemFont : public Item {
 		Ref<Font> font;
 		Ref<Font> font;
 		ItemFont() { type = ITEM_FONT; }
 		ItemFont() { type = ITEM_FONT; }
 	};
 	};
 
 
-	class ItemColor : public Item {
-		GDCLASS(ItemColor, Item);
-
-	public:
+	struct ItemColor : public Item {
 		Color color;
 		Color color;
 		ItemColor() { type = ITEM_COLOR; }
 		ItemColor() { type = ITEM_COLOR; }
 	};
 	};
 
 
-	class ItemUnderline : public Item {
-		GDCLASS(ItemUnderline, Item);
-
-	public:
+	struct ItemUnderline : public Item {
 		ItemUnderline() { type = ITEM_UNDERLINE; }
 		ItemUnderline() { type = ITEM_UNDERLINE; }
 	};
 	};
 
 
-	class ItemStrikethrough : public Item {
-		GDCLASS(ItemStrikethrough, Item);
-
-	public:
+	struct ItemStrikethrough : public Item {
 		ItemStrikethrough() { type = ITEM_STRIKETHROUGH; }
 		ItemStrikethrough() { type = ITEM_STRIKETHROUGH; }
 	};
 	};
 
 
-	class ItemMeta : public Item {
-		GDCLASS(ItemMeta, Item);
-
-	public:
+	struct ItemMeta : public Item {
 		Variant meta;
 		Variant meta;
 		ItemMeta() { type = ITEM_META; }
 		ItemMeta() { type = ITEM_META; }
 	};
 	};
 
 
-	class ItemAlign : public Item {
-		GDCLASS(ItemAlign, Item);
-
-	public:
+	struct ItemAlign : public Item {
 		Align align;
 		Align align;
 		ItemAlign() { type = ITEM_ALIGN; }
 		ItemAlign() { type = ITEM_ALIGN; }
 	};
 	};
 
 
-	class ItemIndent : public Item {
-		GDCLASS(ItemIndent, Item);
-
-	public:
+	struct ItemIndent : public Item {
 		int level;
 		int level;
 		ItemIndent() { type = ITEM_INDENT; }
 		ItemIndent() { type = ITEM_INDENT; }
 	};
 	};
 
 
-	class ItemList : public Item {
-		GDCLASS(ItemList, Item);
-
-	public:
+	struct ItemList : public Item {
 		ListType list_type;
 		ListType list_type;
 		ItemList() { type = ITEM_LIST; }
 		ItemList() { type = ITEM_LIST; }
 	};
 	};
 
 
-	class ItemNewline : public Item {
-		GDCLASS(ItemNewline, Item);
-
-	public:
+	struct ItemNewline : public Item {
 		ItemNewline() { type = ITEM_NEWLINE; }
 		ItemNewline() { type = ITEM_NEWLINE; }
 	};
 	};
 
 
-	class ItemTable : public Item {
-		GDCLASS(ItemTable, Item);
-
-	public:
+	struct ItemTable : public Item {
 		struct Column {
 		struct Column {
 			bool expand;
 			bool expand;
 			int expand_ratio;
 			int expand_ratio;
@@ -249,20 +207,14 @@ private:
 		ItemTable() { type = ITEM_TABLE; }
 		ItemTable() { type = ITEM_TABLE; }
 	};
 	};
 
 
-	class ItemFade : public Item {
-		GDCLASS(ItemFade, Item);
-
-	public:
+	struct ItemFade : public Item {
 		int starting_index;
 		int starting_index;
 		int length;
 		int length;
 
 
 		ItemFade() { type = ITEM_FADE; }
 		ItemFade() { type = ITEM_FADE; }
 	};
 	};
 
 
-	class ItemFX : public Item {
-		GDCLASS(ItemFX, Item);
-
-	public:
+	struct ItemFX : public Item {
 		float elapsed_time;
 		float elapsed_time;
 
 
 		ItemFX() {
 		ItemFX() {
@@ -270,10 +222,7 @@ private:
 		}
 		}
 	};
 	};
 
 
-	class ItemShake : public ItemFX {
-		GDCLASS(ItemShake, ItemFX);
-
-	public:
+	struct ItemShake : public ItemFX {
 		int strength;
 		int strength;
 		float rate;
 		float rate;
 		uint64_t _current_rng;
 		uint64_t _current_rng;
@@ -302,10 +251,7 @@ private:
 		}
 		}
 	};
 	};
 
 
-	class ItemWave : public ItemFX {
-		GDCLASS(ItemWave, ItemFX);
-
-	public:
+	struct ItemWave : public ItemFX {
 		float frequency;
 		float frequency;
 		float amplitude;
 		float amplitude;
 
 
@@ -316,10 +262,7 @@ private:
 		}
 		}
 	};
 	};
 
 
-	class ItemTornado : public ItemFX {
-		GDCLASS(ItemTornado, ItemFX);
-
-	public:
+	struct ItemTornado : public ItemFX {
 		float radius;
 		float radius;
 		float frequency;
 		float frequency;
 
 
@@ -330,10 +273,7 @@ private:
 		}
 		}
 	};
 	};
 
 
-	class ItemRainbow : public ItemFX {
-		GDCLASS(ItemRainbow, ItemFX);
-
-	public:
+	struct ItemRainbow : public ItemFX {
 		float saturation;
 		float saturation;
 		float value;
 		float value;
 		float frequency;
 		float frequency;
@@ -346,22 +286,21 @@ private:
 		}
 		}
 	};
 	};
 
 
-	class ItemCustomFX : public ItemFX {
-		GDCLASS(ItemCustomFX, ItemFX);
-
-	public:
-		String identifier;
-		Dictionary environment;
+	struct ItemCustomFX : public ItemFX {
+		Ref<CharFXTransform> char_fx_transform;
+		Ref<RichTextEffect> custom_effect;
 
 
 		ItemCustomFX() {
 		ItemCustomFX() {
-			identifier = "";
-			environment = Dictionary();
 			type = ITEM_CUSTOMFX;
 			type = ITEM_CUSTOMFX;
+
+			char_fx_transform.instance();
 		}
 		}
 
 
 		virtual ~ItemCustomFX() {
 		virtual ~ItemCustomFX() {
 			_clear_children();
 			_clear_children();
-			environment.clear();
+
+			char_fx_transform.unref();
+			custom_effect.unref();
 		}
 		}
 	};
 	};
 
 
@@ -440,32 +379,7 @@ private:
 	bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = NULL);
 	bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = NULL);
 	bool _find_layout_subitem(Item *from, Item *to);
 	bool _find_layout_subitem(Item *from, Item *to);
 	bool _find_by_type(Item *p_item, ItemType p_type);
 	bool _find_by_type(Item *p_item, ItemType p_type);
-	template <typename T>
-	T *_fetch_by_type(Item *p_item, ItemType p_type) {
-		Item *item = p_item;
-		T *result = NULL;
-		while (item) {
-			if (item->type == p_type) {
-				result = Object::cast_to<T>(item);
-				if (result)
-					return result;
-			}
-			item = item->parent;
-		}
-
-		return result;
-	};
-	template <typename T>
-	void _fetch_item_stack(Item *p_item, Vector<T *> &r_stack) {
-		Item *item = p_item;
-		while (item) {
-			T *found = Object::cast_to<T>(item);
-			if (found) {
-				r_stack.push_back(found);
-			}
-			item = item->parent;
-		}
-	}
+	void _fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack);
 
 
 	void _update_scroll();
 	void _update_scroll();
 	void _update_fx(ItemFrame *p_frame, float p_delta_time);
 	void _update_fx(ItemFrame *p_frame, float p_delta_time);
@@ -509,7 +423,7 @@ public:
 	void push_wave(float p_frequency, float p_amplitude);
 	void push_wave(float p_frequency, float p_amplitude);
 	void push_tornado(float p_frequency, float p_radius);
 	void push_tornado(float p_frequency, float p_radius);
 	void push_rainbow(float p_saturation, float p_value, float p_frequency);
 	void push_rainbow(float p_saturation, float p_value, float p_frequency);
-	void push_customfx(String p_identifier, Dictionary p_environment);
+	void push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionary p_environment);
 	void set_table_column_expand(int p_column, bool p_expand, int p_ratio = 1);
 	void set_table_column_expand(int p_column, bool p_expand, int p_ratio = 1);
 	int get_current_table_column() const;
 	int get_current_table_column() const;
 	void push_cell();
 	void push_cell();