Browse Source

Merge pull request #79498 from lawnjelly/multirect_fix_flushing

[3.x] MultiRect - Fix flushing in TextEdit
Rémi Verschelde 2 years ago
parent
commit
078e1b9f45

+ 5 - 0
scene/gui/text_edit.cpp

@@ -1653,6 +1653,11 @@ void TextEdit::_notification(int p_what) {
 				line_drawing_cache[line] = cache_entry;
 			}
 
+			// Flush out any text in the drawer BEFORE
+			// drawing the completion box, as we want the completion
+			// box to overwrite the underlying text.
+			drawer.flush();
+
 			bool completion_below = false;
 			if (completion_active && is_cursor_visible && completion_options.size() > 0) {
 				// Completion panel

+ 6 - 3
scene/resources/font.cpp

@@ -542,15 +542,18 @@ FontDrawer::FontDrawer(const Ref<Font> &p_font, const Color &p_outline_color) :
 		font(p_font),
 		outline_color(p_outline_color) {
 	has_outline = p_font->has_outline();
-	multirect.begin();
 }
 
-FontDrawer::~FontDrawer() {
+void FontDrawer::flush() {
 	for (int i = 0; i < pending_draws.size(); ++i) {
 		const PendingDraw &draw = pending_draws[i];
 		font->draw_char_ex(draw.canvas_item, draw.pos, draw.chr, draw.next, draw.modulate, false, &multirect);
 	}
-	multirect.end();
+	multirect.flush();
+}
+
+FontDrawer::~FontDrawer() {
+	flush();
 }
 
 void BitmapFont::set_fallback(const Ref<BitmapFont> &p_fallback) {

+ 1 - 0
scene/resources/font.h

@@ -110,6 +110,7 @@ public:
 		return font->draw_char_ex(p_canvas_item, p_pos, p_char, p_next, has_outline ? outline_color : p_modulate, has_outline, &multirect);
 	}
 	MultiRect &get_multirect() { return multirect; }
+	void flush();
 
 	~FontDrawer();
 };

+ 11 - 19
servers/visual/visual_server_canvas_helper.cpp

@@ -38,22 +38,6 @@ Mutex VisualServerCanvasHelper::_tilemap_mutex;
 
 bool VisualServerCanvasHelper::_multirect_enabled = true;
 
-MultiRect::MultiRect() {
-	begin();
-}
-MultiRect::~MultiRect() {
-	end();
-}
-
-void MultiRect::begin() {
-	DEV_CHECK_ONCE(!rects.size());
-	rects.clear();
-	sources.clear();
-
-	state.flags = 0;
-	state_set = false;
-}
-
 void MultiRect::add_rect(RID p_canvas_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, RID p_normal_map, bool p_clip_uv) {
 	bool new_common_data = true;
 
@@ -101,7 +85,7 @@ void MultiRect::add_rect(RID p_canvas_item, const Rect2 &p_rect, RID p_texture,
 	if (!is_empty()) {
 		if ((state != s) ||
 				(rects.size() >= MAX_RECTS)) {
-			end();
+			flush();
 		} else {
 			new_common_data = false;
 		}
@@ -113,6 +97,11 @@ void MultiRect::add_rect(RID p_canvas_item, const Rect2 &p_rect, RID p_texture,
 
 	rects.push_back(rect);
 	sources.push_back(source);
+
+	// Legacy path
+	if (!VisualServerCanvasHelper::_multirect_enabled) {
+		flush();
+	}
 }
 
 void MultiRect::begin(const VisualServerCanvasHelper::State &p_state) {
@@ -184,7 +173,7 @@ bool MultiRect::add(const Rect2 &p_rect, const Rect2 &p_src_rect, bool p_commit_
 	return true;
 }
 
-void MultiRect::end() {
+void MultiRect::flush() {
 	if (!is_empty()) {
 		if (VisualServerCanvasHelper::_multirect_enabled) {
 			VisualServer::get_singleton()->canvas_item_add_texture_multirect_region(state.item, rects, state.texture, sources, state.modulate, state.flags, state.normal_map);
@@ -203,6 +192,9 @@ void MultiRect::end() {
 		sources.clear();
 	}
 	state_set = false;
+
+	// This may not be necessary (if needing to eek out maximum speed).
+	state.flags = 0;
 }
 
 void VisualServerCanvasHelper::tilemap_begin() {
@@ -272,7 +264,7 @@ void VisualServerCanvasHelper::tilemap_end() {
 	}
 
 	for (uint32_t n = 0; n < _tilemap_multirects.size(); n++) {
-		_tilemap_multirects[n].end();
+		_tilemap_multirects[n].flush();
 	}
 
 	_tilemap_multirects.clear();

+ 5 - 4
servers/visual/visual_server_canvas_helper.h

@@ -97,7 +97,6 @@ private:
 
 public:
 	// Simple API
-	void begin();
 	void add_rect(RID p_canvas_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), bool p_clip_uv = false);
 
 	// Efficient API
@@ -105,10 +104,12 @@ public:
 	bool add(const Rect2 &p_rect, const Rect2 &p_src_rect, bool p_commit_on_flip_change = true);
 	bool is_empty() const { return rects.is_empty(); }
 	bool is_full() const { return rects.is_full(); }
-	void end();
 
-	MultiRect();
-	~MultiRect();
+	// Always called in destructor, but can be used explicitly
+	// for multiple draws, or to time the flush.
+	void flush();
+
+	~MultiRect() { flush(); }
 };
 
 #endif // VISUAL_SERVER_CANVAS_HELPER_H