Presort text draw calls.
This commit is contained in:
@@ -457,6 +457,13 @@
|
||||
[b]Note:[/b] The equivalent node is [CanvasItem].
|
||||
</description>
|
||||
</method>
|
||||
<method name="canvas_item_flush_presort">
|
||||
<return type="void" />
|
||||
<param index="0" name="item" type="RID" />
|
||||
<description>
|
||||
Ends draw call pre-sorting. See [method canvas_item_set_presort_level].
|
||||
</description>
|
||||
</method>
|
||||
<method name="canvas_item_get_instance_shader_parameter" qualifiers="const">
|
||||
<return type="Variant" />
|
||||
<param index="0" name="instance" type="RID" />
|
||||
@@ -618,6 +625,14 @@
|
||||
Sets a parent [CanvasItem] to the [CanvasItem]. The item will inherit transform, modulation and visibility from its parent, like [CanvasItem] nodes in the scene tree.
|
||||
</description>
|
||||
</method>
|
||||
<method name="canvas_item_set_presort_level">
|
||||
<return type="void" />
|
||||
<param index="0" name="item" type="RID" />
|
||||
<param index="1" name="order" type="int" />
|
||||
<description>
|
||||
Starts draw call pre-sorting or changes the pre-sorting level. All subsequent draw calls until [method canvas_item_flush_presort] is called are sorted according to the [param order] (in ascending order) and texture usage, to ensure draw call batching. The original call order is not preserved, except [method canvas_item_add_set_transform], [method canvas_item_add_clip_ignore], and [method canvas_item_add_animation_slice] effects. Draw calls made before the first [method canvas_item_set_presort_level] call or after [method canvas_item_flush_presort] is called are also not affected. [param order] should be greater or equal to zero.
|
||||
</description>
|
||||
</method>
|
||||
<method name="canvas_item_set_self_modulate">
|
||||
<return type="void" />
|
||||
<param index="0" name="item" type="RID" />
|
||||
|
||||
@@ -446,7 +446,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
||||
}
|
||||
|
||||
if (ci->skeleton.is_valid()) {
|
||||
const Item::Command *c = ci->commands;
|
||||
const Item::Command *c = ci->first_command;
|
||||
|
||||
while (c) {
|
||||
if (c->type == Item::Command::TYPE_MESH) {
|
||||
@@ -876,7 +876,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
|
||||
}
|
||||
|
||||
const RSE::CanvasItemTextureRepeat base_texture_repeat = p_item->texture_repeat == RSE::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? state.default_repeat : p_item->texture_repeat;
|
||||
const Item::Command *c = p_item->commands;
|
||||
const Item::Command *c = p_item->first_command;
|
||||
while (c) {
|
||||
if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) {
|
||||
c = c->next;
|
||||
|
||||
@@ -581,14 +581,18 @@ Array ScriptTextEditor::_inline_object_parse(const String &p_text) {
|
||||
}
|
||||
|
||||
void ScriptTextEditor::_inline_object_draw(const Dictionary &p_info, const Rect2 &p_rect) {
|
||||
// Note: this method uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order. See TextEdit::DrawStep.
|
||||
if (_is_valid_color_info(p_info)) {
|
||||
Rect2 col_rect = p_rect.grow(-4);
|
||||
if (color_alpha_texture.is_null()) {
|
||||
color_alpha_texture = inline_color_picker->get_theme_icon("sample_bg", "ColorPicker");
|
||||
}
|
||||
RID text_ci = code_editor->get_text_editor()->get_text_canvas_item();
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, TextEdit::DrawStep::DRAW_STEP_TEXT_OUTLINE);
|
||||
RS::get_singleton()->canvas_item_add_rect(text_ci, p_rect.grow(-3), Color(1, 1, 1));
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, TextEdit::DrawStep::DRAW_STEP_TEXT);
|
||||
color_alpha_texture->draw_rect(text_ci, col_rect);
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, TextEdit::DrawStep::DRAW_STEP_TEXT_OVERLAY);
|
||||
RS::get_singleton()->canvas_item_add_rect(text_ci, col_rect, Color(p_info["color"]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1525,6 +1525,7 @@ bool CodeEdit::is_drawing_executing_lines_gutter() const {
|
||||
}
|
||||
|
||||
void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) {
|
||||
// Note: this method uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order. See TextEdit::DrawStep.
|
||||
bool hovering = get_hovered_gutter() == Vector2i(main_gutter, p_line);
|
||||
RID ci = get_text_canvas_item();
|
||||
if (draw_breakpoints && theme_cache.breakpoint_icon.is_valid()) {
|
||||
@@ -1715,6 +1716,7 @@ int CodeEdit::get_line_numbers_min_digits() const {
|
||||
}
|
||||
|
||||
void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) {
|
||||
// Note: this method uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order. See TextEdit::DrawStep.
|
||||
if (!Rect2(Vector2(0, 0), get_size()).intersects(p_region)) {
|
||||
return;
|
||||
}
|
||||
@@ -1777,6 +1779,7 @@ bool CodeEdit::is_drawing_fold_gutter() const {
|
||||
}
|
||||
|
||||
void CodeEdit::_fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_region) {
|
||||
// Note: this method uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order. See TextEdit::DrawStep.
|
||||
if (!can_fold_line(p_line) && !is_line_folded(p_line)) {
|
||||
set_line_gutter_clickable(p_line, fold_gutter, false);
|
||||
return;
|
||||
|
||||
+17
-1
@@ -804,6 +804,7 @@ void Label::_notification(int p_what) {
|
||||
int visible_glyphs = total_glyphs * visible_ratio;
|
||||
|
||||
int line_index = 0;
|
||||
// Note: part of this method between this comment and `canvas_item_flush_presort` call uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order.
|
||||
for (int p = 0; p < paragraphs.size(); p++) {
|
||||
const Paragraph ¶ = paragraphs[p];
|
||||
if (line_index + para.lines_rid.size() <= lines_skipped) {
|
||||
@@ -843,12 +844,17 @@ void Label::_notification(int p_what) {
|
||||
int processed_glyphs_step = 0;
|
||||
|
||||
// Draw shadow outline.
|
||||
int draw_step = 0;
|
||||
if (font_shadow_color.a != 0 && shadow_outline_size > 0) {
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, draw_step);
|
||||
draw_step++;
|
||||
draw_text(rtl, ellipsis_pos, ellipsis_gl_size, ellipsis_glyphs, trim_chars, para.start, visible_chars, trim_glyphs_ltr, processed_glyphs_step, processed_glyphs, visible_glyphs, trim_glyphs_rtl, total_glyphs, ci, ofs, gl_size, trim_pos, glyphs, font_shadow_color, draw_glyph_shadow_outline, shadow_outline_size, shadow_ofs);
|
||||
}
|
||||
|
||||
// Draw shadow.
|
||||
if (font_shadow_color.a > 0) {
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, draw_step);
|
||||
draw_step++;
|
||||
draw_text(rtl, ellipsis_pos, ellipsis_gl_size, ellipsis_glyphs, trim_chars, para.start, visible_chars, trim_glyphs_ltr, processed_glyphs_step, processed_glyphs, visible_glyphs, trim_glyphs_rtl, total_glyphs, ci, ofs, gl_size, trim_pos, glyphs, font_shadow_color, draw_glyph_shadow, shadow_ofs);
|
||||
}
|
||||
|
||||
@@ -859,9 +865,12 @@ void Label::_notification(int p_what) {
|
||||
for (int draw_iteration_index = draw_iterations - 1; draw_iteration_index >= 0; --draw_iteration_index) {
|
||||
LabelSettings::StackedShadowData stacked_shadow_data = stacked_shadow_datas[draw_iteration_index];
|
||||
if (stacked_shadow_data.outline_size > 0) {
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, draw_step);
|
||||
draw_step++;
|
||||
draw_text(rtl, ellipsis_pos, ellipsis_gl_size, ellipsis_glyphs, trim_chars, para.start, visible_chars, trim_glyphs_ltr, processed_glyphs_step, processed_glyphs, visible_glyphs, trim_glyphs_rtl, total_glyphs, ci, ofs, gl_size, trim_pos, glyphs, stacked_shadow_data.color, draw_glyph_shadow_outline, stacked_shadow_data.outline_size, stacked_shadow_data.offset);
|
||||
}
|
||||
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, draw_step);
|
||||
draw_step++;
|
||||
draw_text(rtl, ellipsis_pos, ellipsis_gl_size, ellipsis_glyphs, trim_chars, para.start, visible_chars, trim_glyphs_ltr, processed_glyphs_step, processed_glyphs, visible_glyphs, trim_glyphs_rtl, total_glyphs, ci, ofs, gl_size, trim_pos, glyphs, stacked_shadow_data.color, draw_glyph_shadow, stacked_shadow_data.offset);
|
||||
}
|
||||
}
|
||||
@@ -885,6 +894,8 @@ void Label::_notification(int p_what) {
|
||||
if (stacked_outline_data.size <= 0) {
|
||||
continue;
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, draw_step);
|
||||
draw_step++;
|
||||
draw_text(rtl, ellipsis_pos, ellipsis_gl_size, ellipsis_glyphs, trim_chars, para.start, visible_chars, trim_glyphs_ltr, processed_glyphs_step, processed_glyphs, visible_glyphs, trim_glyphs_rtl, total_glyphs, ci, ofs, gl_size, trim_pos, glyphs, stacked_outline_data.color, draw_glyph_outline, stacked_outline_draw_size);
|
||||
stacked_outline_draw_size -= stacked_outline_data.size;
|
||||
}
|
||||
@@ -892,11 +903,15 @@ void Label::_notification(int p_what) {
|
||||
|
||||
// Draw outline.
|
||||
if (outline_size > 0 && font_outline_color.a != 0) {
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, draw_step);
|
||||
draw_step++;
|
||||
draw_text(rtl, ellipsis_pos, ellipsis_gl_size, ellipsis_glyphs, trim_chars, para.start, visible_chars, trim_glyphs_ltr, processed_glyphs_step, processed_glyphs, visible_glyphs, trim_glyphs_rtl, total_glyphs, ci, ofs, gl_size, trim_pos, glyphs, font_outline_color, draw_glyph_outline, outline_size);
|
||||
}
|
||||
|
||||
// Draw text.
|
||||
{
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, draw_step);
|
||||
draw_step++;
|
||||
draw_text(rtl, ellipsis_pos, ellipsis_gl_size, ellipsis_glyphs, trim_chars, para.start, visible_chars, trim_glyphs_ltr, processed_glyphs_step, processed_glyphs, visible_glyphs, trim_glyphs_rtl, total_glyphs, ci, ofs, gl_size, trim_pos, glyphs, font_color, draw_glyph);
|
||||
}
|
||||
|
||||
@@ -907,6 +922,7 @@ void Label::_notification(int p_what) {
|
||||
line_index += para.lines_rid.size();
|
||||
}
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_flush_presort(ci);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
|
||||
@@ -1519,11 +1519,13 @@ void LineEdit::_notification(int p_what) {
|
||||
int gl_size = TS->shaped_text_get_glyph_count(text_rid);
|
||||
|
||||
// Draw text.
|
||||
// Note: part of this method between this comment and `canvas_item_flush_presort` call uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order.
|
||||
ofs.y += TS->shaped_text_get_ascent(text_rid);
|
||||
Color font_outline_color = theme_cache.font_outline_color;
|
||||
int outline_size = theme_cache.font_outline_size;
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
Vector2 oofs = ofs;
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, DRAW_STEP_OUTLINE);
|
||||
for (int i = 0; i < gl_size; i++) {
|
||||
for (int j = 0; j < glyphs[i].repeat; j++) {
|
||||
if (std::ceil(oofs.x) >= x_ofs && (oofs.x + glyphs[i].advance) <= ofs_max) {
|
||||
@@ -1538,6 +1540,7 @@ void LineEdit::_notification(int p_what) {
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, DRAW_STEP_TEXT);
|
||||
for (int i = 0; i < gl_size; i++) {
|
||||
bool selected = selection.enabled && glyphs[i].start >= selection.begin && glyphs[i].end <= selection.end;
|
||||
for (int j = 0; j < glyphs[i].repeat; j++) {
|
||||
@@ -1554,6 +1557,7 @@ void LineEdit::_notification(int p_what) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_flush_presort(ci);
|
||||
|
||||
// Draw carets.
|
||||
ofs.x = x_ofs + scroll_offset;
|
||||
|
||||
@@ -91,6 +91,11 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
enum LEDrawStep {
|
||||
DRAW_STEP_OUTLINE,
|
||||
DRAW_STEP_TEXT,
|
||||
};
|
||||
|
||||
HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;
|
||||
|
||||
bool editing = false;
|
||||
|
||||
@@ -1053,7 +1053,8 @@ void RichTextLabel::_update_table_size(ItemTable *p_table) {
|
||||
}
|
||||
}
|
||||
|
||||
int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, float p_vsep, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs) {
|
||||
int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, float p_vsep, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs, int p_draw_step) {
|
||||
// Note: this method uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order.
|
||||
ERR_FAIL_NULL_V(p_frame, 0);
|
||||
ERR_FAIL_COND_V(p_line < 0 || p_line >= (int)p_frame->lines.size(), 0);
|
||||
|
||||
@@ -1084,8 +1085,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||
bool skip_dc = (trim_chars && l.char_offset > visible_characters) || (trim_glyphs_ltr && (r_processed_glyphs >= visible_glyphs)) || (trim_glyphs_rtl && (r_processed_glyphs < total_glyphs - visible_glyphs));
|
||||
if (!skip_dc) {
|
||||
if (l.dc_ol_size > 0) {
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_OUTLINE);
|
||||
l.text_buf->draw_dropcap_outline(ci, p_ofs + ((rtl) ? Vector2() : Vector2(l.offset.x, 0)), l.dc_ol_size, l.dc_ol_color);
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_TEXT);
|
||||
l.text_buf->draw_dropcap(ci, p_ofs + ((rtl) ? Vector2() : Vector2(l.offset.x, 0)), l.dc_color);
|
||||
}
|
||||
|
||||
@@ -1153,20 +1156,24 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||
Color font_outline_color = l.prefix_outline_color == Color(0, 0, 0, 0) ? _find_outline_color(l.from, p_base_color) : l.prefix_outline_color;
|
||||
Color font_shadow_color = p_font_shadow_color * Color(1, 1, 1, font_color.a);
|
||||
if (rtl) {
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_OUTLINE);
|
||||
if (p_shadow_outline_size > 0 && font_shadow_color.a != 0.0) {
|
||||
l.text_prefix->draw_outline(ci, p_ofs + Vector2(off.x + length, 0) + p_shadow_ofs, p_shadow_outline_size, font_shadow_color);
|
||||
}
|
||||
if (outline_size > 0 && font_outline_color.a != 0.0) {
|
||||
l.text_prefix->draw_outline(ci, p_ofs + Vector2(off.x + length, 0), outline_size, font_outline_color);
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_TEXT);
|
||||
l.text_prefix->draw(ci, p_ofs + Vector2(off.x + length, 0), font_color);
|
||||
} else {
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_OUTLINE);
|
||||
if (p_shadow_outline_size > 0 && font_shadow_color.a != 0.0) {
|
||||
l.text_prefix->draw_outline(ci, p_ofs + Vector2(off.x - l.text_prefix->get_size().x, 0) + p_shadow_ofs, p_shadow_outline_size, font_shadow_color);
|
||||
}
|
||||
if (outline_size > 0 && font_outline_color.a != 0.0) {
|
||||
l.text_prefix->draw_outline(ci, p_ofs + Vector2(off.x - l.text_prefix->get_size().x, 0), outline_size, font_outline_color);
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_TEXT);
|
||||
l.text_prefix->draw(ci, p_ofs + Vector2(off.x - l.text_prefix->get_size().x, 0), font_color);
|
||||
}
|
||||
}
|
||||
@@ -1200,7 +1207,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||
}
|
||||
|
||||
int processed_glyphs_step = 0;
|
||||
for (int step = DRAW_STEP_BACKGROUND; step < DRAW_STEP_MAX; step++) {
|
||||
for (int step = DRAW_STEP_BACKGROUND; step < DRAW_STEP_TEXT_MAX; step++) {
|
||||
if (step == DRAW_STEP_TEXT) {
|
||||
// Draw inlined objects.
|
||||
Array objects = TS->shaped_text_get_objects(rid);
|
||||
@@ -1221,6 +1228,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||
switch (it->type) {
|
||||
case ITEM_IMAGE: {
|
||||
ItemImage *img = static_cast<ItemImage *>(it);
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_TEXT);
|
||||
if (img->pad) {
|
||||
Size2 pad_size = rect.size.min(img->image->get_size());
|
||||
Vector2 pad_off = (rect.size - pad_size) / 2;
|
||||
@@ -1249,7 +1257,6 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||
table_ofs -= Vector2(h_separation * 0.5, v_separation * 0.5).floor();
|
||||
}
|
||||
|
||||
bool right_has_border = false;
|
||||
int idx = 0;
|
||||
for (Item *E : table->subitems) {
|
||||
ItemFrame *frame = static_cast<ItemFrame *>(E);
|
||||
@@ -1276,29 +1283,19 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||
row_bg = frame->even_row_bg != Color(0, 0, 0, 0) ? frame->even_row_bg : even_row_bg;
|
||||
}
|
||||
if (row_bg.a > 0.0) {
|
||||
if (right_has_border) {
|
||||
// To prevent the border of the right cell from being covered.
|
||||
cell_rect.size.x -= 1;
|
||||
draw_rect(cell_rect, row_bg, true);
|
||||
cell_rect.size.x += 1;
|
||||
} else {
|
||||
draw_rect(cell_rect, row_bg, true);
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_CELL_BACKGROUND);
|
||||
draw_rect(cell_rect, row_bg, true);
|
||||
}
|
||||
|
||||
right_has_border = false;
|
||||
|
||||
Color bc = frame->border != Color(0, 0, 0, 0) ? frame->border : border;
|
||||
if (bc.a > 0.0) {
|
||||
if (rtl && col < col_count - 1) {
|
||||
right_has_border = true;
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + DRAW_STEP_CELL_BORDER);
|
||||
draw_rect(cell_rect, bc, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < (int)frame->lines.size(); j++) {
|
||||
_draw_line(frame, j, p_ofs + rect.position + off + Vector2(0, frame->lines[j].offset.y), rect.size.x, 0, p_base_color, p_outline_size, p_outline_color, p_font_shadow_color, p_shadow_outline_size, p_shadow_ofs, r_processed_glyphs);
|
||||
_draw_line(frame, j, p_ofs + rect.position + off + Vector2(0, frame->lines[j].offset.y), rect.size.x, 0, p_base_color, p_outline_size, p_outline_color, p_font_shadow_color, p_shadow_outline_size, p_shadow_ofs, r_processed_glyphs, p_draw_step + DRAW_STEP_MAX);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
@@ -1309,6 +1306,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(ci, p_draw_step + step);
|
||||
Vector2 off_step = off;
|
||||
processed_glyphs_step = r_processed_glyphs;
|
||||
|
||||
@@ -2802,10 +2800,11 @@ void RichTextLabel::_notification(int p_what) {
|
||||
// New cache draw.
|
||||
Point2 ofs = text_rect.get_position() + Vector2(0, vbegin + main->lines[from_line].offset.y - vofs);
|
||||
int processed_glyphs = 0;
|
||||
// Note: this loop uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order.
|
||||
while (ofs.y < size.height - v_limit && from_line < to_line) {
|
||||
MutexLock lock(main->lines[from_line].text_buf->get_mutex());
|
||||
|
||||
int drawn_lines = _draw_line(main, from_line, ofs, text_rect.size.x, vsep, theme_cache.default_color, theme_cache.outline_size, theme_cache.font_outline_color, theme_cache.font_shadow_color, theme_cache.shadow_outline_size, shadow_ofs, processed_glyphs);
|
||||
int drawn_lines = _draw_line(main, from_line, ofs, text_rect.size.x, vsep, theme_cache.default_color, theme_cache.outline_size, theme_cache.font_outline_color, theme_cache.font_shadow_color, theme_cache.shadow_outline_size, shadow_ofs, processed_glyphs, 0);
|
||||
visible_line_count += drawn_lines;
|
||||
if (drawn_lines > 0) {
|
||||
visible_paragraph_count++;
|
||||
@@ -2813,6 +2812,7 @@ void RichTextLabel::_notification(int p_what) {
|
||||
ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * (theme_cache.line_separation + vsep) + (theme_cache.paragraph_separation);
|
||||
from_line++;
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_flush_presort(ci);
|
||||
if (scroll_follow_visible_characters && scroll_active) {
|
||||
scroll_visible = follow_vc_pos > 0;
|
||||
if (scroll_visible) {
|
||||
|
||||
@@ -57,6 +57,9 @@ class RichTextLabel : public Control {
|
||||
DRAW_STEP_OUTLINE,
|
||||
DRAW_STEP_TEXT,
|
||||
DRAW_STEP_FOREGROUND,
|
||||
DRAW_STEP_TEXT_MAX,
|
||||
DRAW_STEP_CELL_BACKGROUND = DRAW_STEP_TEXT_MAX,
|
||||
DRAW_STEP_CELL_BORDER,
|
||||
DRAW_STEP_MAX,
|
||||
};
|
||||
|
||||
@@ -667,7 +670,7 @@ private:
|
||||
void _update_table_size(ItemTable *p_table);
|
||||
|
||||
void _update_line_font(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size);
|
||||
int _draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, float p_vsep, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs);
|
||||
int _draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, float p_vsep, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs, int p_draw_step);
|
||||
float _find_click_in_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, float p_vsep, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr, bool p_table = false, bool p_meta = false);
|
||||
void _accessibility_update_line(RID p_id, ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, float p_vsep);
|
||||
|
||||
|
||||
+13
-1
@@ -1336,6 +1336,7 @@ void TextEdit::_notification(int p_what) {
|
||||
_draw_guidelines();
|
||||
|
||||
// Draw main text.
|
||||
// Note: part of this method between this comment and `canvas_item_flush_presort` call uses pre-sorted draw, draw call order is ignored, use `canvas_item_set_presort_level` to specify draw order.
|
||||
line_drawing_cache.clear();
|
||||
int row_height = draw_placeholder ? placeholder_line_height + theme_cache.line_spacing : get_line_height();
|
||||
int line = first_vis_line;
|
||||
@@ -1408,6 +1409,7 @@ void TextEdit::_notification(int p_what) {
|
||||
break;
|
||||
}
|
||||
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_LINE_BACKGROUND);
|
||||
if (text.get_line_background_color(line).a > 0.0) {
|
||||
if (rtl) {
|
||||
RS::get_singleton()->canvas_item_add_rect(text_ci, Rect2(size.width - xmargin_end, ofs_y, xmargin_end - xmargin_beg, row_height), text.get_line_background_color(line));
|
||||
@@ -1417,6 +1419,7 @@ void TextEdit::_notification(int p_what) {
|
||||
}
|
||||
|
||||
// Draw current line highlight.
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_LINE_HIGHLIGHT);
|
||||
if (highlight_current_line && highlighted_lines.has(Pair<int, int>(line, line_wrap_index))) {
|
||||
if (rtl) {
|
||||
RS::get_singleton()->canvas_item_add_rect(text_ci, Rect2(size.width - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color);
|
||||
@@ -1451,8 +1454,10 @@ void TextEdit::_notification(int p_what) {
|
||||
|
||||
int yofs = ofs_y + (row_height - tl->get_size().y) / 2;
|
||||
if (theme_cache.outline_size > 0 && theme_cache.outline_color.a > 0) {
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_TEXT_OUTLINE);
|
||||
tl->draw_outline(text_ci, Point2(gutter_offset, yofs), theme_cache.outline_size, theme_cache.outline_color);
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_TEXT);
|
||||
tl->draw(text_ci, Point2(gutter_offset, yofs), get_line_gutter_item_color(line, g));
|
||||
} break;
|
||||
case GUTTER_TYPE_ICON: {
|
||||
@@ -1484,7 +1489,7 @@ void TextEdit::_notification(int p_what) {
|
||||
if (rtl) {
|
||||
gutter_rect.position.x = size.width - gutter_rect.position.x - gutter_rect.size.x;
|
||||
}
|
||||
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_TEXT);
|
||||
icon->draw_rect(text_ci, gutter_rect, false, get_line_gutter_item_color(line, g));
|
||||
} break;
|
||||
case GUTTER_TYPE_CUSTOM: {
|
||||
@@ -1493,6 +1498,7 @@ void TextEdit::_notification(int p_what) {
|
||||
if (rtl) {
|
||||
gutter_rect.position.x = size.width - gutter_rect.position.x - gutter_rect.size.x;
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_TEXT);
|
||||
gutter.custom_draw_callback.call(line, g, Rect2(gutter_rect));
|
||||
}
|
||||
} break;
|
||||
@@ -1526,6 +1532,7 @@ void TextEdit::_notification(int p_what) {
|
||||
|
||||
// Draw selections.
|
||||
float char_w = theme_cache.font->get_char_size(' ', theme_cache.font_size).width;
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_TEXT_SELECTION);
|
||||
for (int c = 0; c < get_caret_count(); c++) {
|
||||
if (!clipped && has_selection(c) && line >= get_selection_from_line(c) && line <= get_selection_to_line(c)) {
|
||||
int sel_from = (line > get_selection_from_line(c)) ? TS->shaped_text_get_range(rid).x : get_selection_from_column(c);
|
||||
@@ -1568,6 +1575,7 @@ void TextEdit::_notification(int p_what) {
|
||||
}
|
||||
|
||||
int start = TS->shaped_text_get_range(rid).x;
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_SEARCH_HIGHLIGHT);
|
||||
if (!clipped && !search_text.is_empty()) { // Search highlight
|
||||
int search_text_col = _get_column_pos_of_word(search_text, str, search_flags, 0);
|
||||
int search_text_len = search_text.length();
|
||||
@@ -1654,6 +1662,7 @@ void TextEdit::_notification(int p_what) {
|
||||
int last_visible_char = TS->shaped_text_get_range(rid).x;
|
||||
|
||||
float char_ofs = 0;
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_TEXT_OUTLINE);
|
||||
if (theme_cache.outline_size > 0 && theme_cache.outline_color.a > 0) {
|
||||
for (int j = 0; j < gl_size; j++) {
|
||||
for (int k = 0; k < glyphs[j].repeat; k++) {
|
||||
@@ -1680,6 +1689,7 @@ void TextEdit::_notification(int p_what) {
|
||||
}
|
||||
}
|
||||
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_TEXT);
|
||||
for (int j = 0; j < gl_size; j++) {
|
||||
for (const Pair<int64_t, Color> &color_data : color_map) {
|
||||
if (color_data.first <= glyphs[j].start) {
|
||||
@@ -1770,6 +1780,7 @@ void TextEdit::_notification(int p_what) {
|
||||
cache_entry.first_visible_chars.push_back(first_visible_char);
|
||||
cache_entry.last_visible_chars.push_back(last_visible_char);
|
||||
|
||||
RenderingServer::get_singleton()->canvas_item_set_presort_level(text_ci, DRAW_STEP_TEXT_OVERLAY);
|
||||
// is_line_folded
|
||||
if (line_wrap_index == line_wrap_amount && line < text.size() - 1 && _is_line_hidden(line + 1)) {
|
||||
int xofs = char_ofs + char_margin + (_get_folded_eol_icon()->get_width() / 2);
|
||||
@@ -1954,6 +1965,7 @@ void TextEdit::_notification(int p_what) {
|
||||
line_drawing_cache[line] = cache_entry;
|
||||
}
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_flush_presort(text_ci);
|
||||
|
||||
if (has_focus()) {
|
||||
_update_ime_window_position();
|
||||
|
||||
@@ -121,6 +121,16 @@ public:
|
||||
SEARCH_BACKWARDS = 4
|
||||
};
|
||||
|
||||
enum DrawStep {
|
||||
DRAW_STEP_LINE_BACKGROUND,
|
||||
DRAW_STEP_LINE_HIGHLIGHT,
|
||||
DRAW_STEP_TEXT_SELECTION,
|
||||
DRAW_STEP_SEARCH_HIGHLIGHT,
|
||||
DRAW_STEP_TEXT_OUTLINE,
|
||||
DRAW_STEP_TEXT,
|
||||
DRAW_STEP_TEXT_OVERLAY,
|
||||
};
|
||||
|
||||
private:
|
||||
struct GutterInfo {
|
||||
GutterType type = GutterType::GUTTER_TYPE_STRING;
|
||||
|
||||
@@ -222,7 +222,7 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
|
||||
|
||||
// We have two choices now, if user has drawn something, we must assume users wants to draw the "mask", so compute the size based on this.
|
||||
// If nothing has been drawn, we just take it over and draw it ourselves.
|
||||
if (ci->canvas_group->fit_empty && (ci->commands == nullptr || (ci->commands->next == nullptr && ci->commands->type == RendererCanvasCull::Item::Command::TYPE_RECT && (static_cast<RendererCanvasCull::Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
|
||||
if (ci->canvas_group->fit_empty && (ci->first_command == nullptr || (ci->first_command->next == nullptr && ci->first_command->type == RendererCanvasCull::Item::Command::TYPE_RECT && (static_cast<RendererCanvasCull::Item::CommandRect *>(ci->first_command)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
|
||||
// No commands, or sole command is the one used to draw, so we (re)create the draw command.
|
||||
ci->clear();
|
||||
|
||||
@@ -257,14 +257,14 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
|
||||
}
|
||||
}
|
||||
|
||||
if (((ci->commands != nullptr || ci->visibility_notifier) && p_clip_rect.intersects(p_global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {
|
||||
if (((ci->first_command != nullptr || ci->visibility_notifier) && p_clip_rect.intersects(p_global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {
|
||||
// Something to draw?
|
||||
|
||||
if (ci->update_when_visible) {
|
||||
RenderingServerDefault::redraw_request();
|
||||
}
|
||||
|
||||
if (ci->commands != nullptr || ci->copy_back_buffer) {
|
||||
if (ci->first_command != nullptr || ci->copy_back_buffer) {
|
||||
ci->final_transform = !ci->use_identity_transform ? p_transform : _current_camera_transform;
|
||||
ci->final_modulate = p_modulate * ci->self_modulate;
|
||||
ci->global_rect_cache = p_global_rect;
|
||||
@@ -330,6 +330,12 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!ci->presort_commands.is_empty()) {
|
||||
WARN_PRINT(vformat("Presort list for canvas item %x was not flushed!", ci->self.get_id()));
|
||||
}
|
||||
#endif
|
||||
|
||||
Rect2 rect = ci->get_rect();
|
||||
|
||||
if (ci->visibility_notifier) {
|
||||
@@ -460,7 +466,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
|
||||
}
|
||||
} else {
|
||||
RendererCanvasRender::Item *canvas_group_from = nullptr;
|
||||
bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
|
||||
bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->first_command != nullptr);
|
||||
if (use_canvas_group) {
|
||||
int zidx = p_z - RSE::CANVAS_ITEM_Z_MIN;
|
||||
canvas_group_from = r_z_last_list[zidx];
|
||||
@@ -470,7 +476,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
|
||||
}
|
||||
} else {
|
||||
RendererCanvasRender::Item *canvas_group_from = nullptr;
|
||||
bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
|
||||
bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->first_command != nullptr);
|
||||
if (use_canvas_group) {
|
||||
int zidx = p_z - RSE::CANVAS_ITEM_Z_MIN;
|
||||
canvas_group_from = r_z_last_list[zidx];
|
||||
@@ -744,12 +750,89 @@ float RendererCanvasCull::canvas_item_get_compensated_antialiasing_width(float p
|
||||
return p_width;
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_set_presort_level(RID p_item, int64_t p_order) {
|
||||
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||
ERR_FAIL_NULL(canvas_item);
|
||||
ERR_FAIL_COND(p_order < 0);
|
||||
|
||||
if (canvas_item->presort_level == -1) {
|
||||
canvas_item->presort_prev_command = canvas_item->last_command;
|
||||
if (!canvas_item->presort_prev_state.is_base_state()) {
|
||||
canvas_item->presort_states.push_back(canvas_item->presort_prev_state);
|
||||
canvas_item->presort_state = 0;
|
||||
}
|
||||
}
|
||||
canvas_item->presort_level = p_order;
|
||||
}
|
||||
|
||||
void RendererCanvasCull::_update_presort_state(Item *p_canvas_item, int32_t p_old_state, int32_t p_new_state, Item::Command **r_prev_command) {
|
||||
const Item::PresortState &old_state = (p_old_state >= 0) ? p_canvas_item->presort_states[p_old_state] : Item::PresortState();
|
||||
const Item::PresortState &new_state = (p_new_state >= 0) ? p_canvas_item->presort_states[p_new_state] : Item::PresortState();
|
||||
if (old_state.transform != new_state.transform) {
|
||||
Item::CommandTransform *tr = p_canvas_item->alloc_command<Item::CommandTransform>(false);
|
||||
if (tr) {
|
||||
tr->xform = new_state.transform;
|
||||
_insert_command(p_canvas_item, r_prev_command, tr);
|
||||
}
|
||||
}
|
||||
if (old_state.clip_ignore != new_state.clip_ignore) {
|
||||
Item::CommandClipIgnore *ci = p_canvas_item->alloc_command<Item::CommandClipIgnore>(false);
|
||||
if (ci) {
|
||||
ci->ignore = new_state.clip_ignore;
|
||||
_insert_command(p_canvas_item, r_prev_command, ci);
|
||||
}
|
||||
}
|
||||
if (old_state.animation_length != new_state.animation_length || old_state.slice_begin != new_state.slice_begin || old_state.slice_end != new_state.slice_end || old_state.offset != new_state.offset) {
|
||||
Item::CommandAnimationSlice *as = p_canvas_item->alloc_command<Item::CommandAnimationSlice>(false);
|
||||
if (as) {
|
||||
as->animation_length = new_state.animation_length;
|
||||
as->slice_begin = new_state.slice_begin;
|
||||
as->slice_end = new_state.slice_end;
|
||||
as->offset = new_state.offset;
|
||||
_insert_command(p_canvas_item, r_prev_command, as);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_flush_presort(RID p_item) {
|
||||
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||
ERR_FAIL_NULL(canvas_item);
|
||||
|
||||
canvas_item->presort_commands.sort_custom<Item::PresortDataCompare>();
|
||||
if (!canvas_item->presort_commands.is_empty()) {
|
||||
Item::Command *prev_command = canvas_item->presort_prev_command;
|
||||
int32_t start_presort_state = canvas_item->presort_prev_state.is_base_state() ? -1 : 0;
|
||||
int32_t prev_presort_state = start_presort_state;
|
||||
for (Item::PresortData &pd : canvas_item->presort_commands) {
|
||||
if (prev_presort_state != pd.state) {
|
||||
_update_presort_state(canvas_item, prev_presort_state, pd.state, &prev_command);
|
||||
prev_presort_state = pd.state;
|
||||
}
|
||||
_insert_command(canvas_item, &prev_command, pd.command);
|
||||
}
|
||||
if (start_presort_state != prev_presort_state) {
|
||||
_update_presort_state(canvas_item, prev_presort_state, start_presort_state, &prev_command);
|
||||
}
|
||||
prev_command->next = nullptr;
|
||||
canvas_item->last_command = prev_command;
|
||||
}
|
||||
canvas_item->presort_commands.clear();
|
||||
canvas_item->presort_states.clear();
|
||||
canvas_item->presort_prev_command = nullptr;
|
||||
canvas_item->presort_level = -1;
|
||||
canvas_item->presort_state = -1;
|
||||
canvas_item->presort_prev_state = Item::PresortState();
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width, bool p_antialiased) {
|
||||
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||
ERR_FAIL_NULL(canvas_item);
|
||||
|
||||
Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(line);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ line, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
Vector2 diff = (p_from - p_to);
|
||||
Vector2 dir = diff.orthogonal().normalized();
|
||||
@@ -806,6 +889,9 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
|
||||
{
|
||||
Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(left_border);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ left_border, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
left_border->points[0] = begin_left;
|
||||
left_border->points[1] = begin_left + border;
|
||||
@@ -822,6 +908,9 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
|
||||
{
|
||||
Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(right_border);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ right_border, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
right_border->points[0] = begin_right;
|
||||
right_border->points[1] = begin_right - border;
|
||||
@@ -838,6 +927,9 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
|
||||
{
|
||||
Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(top_border);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ top_border, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
top_border->points[0] = begin_left;
|
||||
top_border->points[1] = begin_left + border2;
|
||||
@@ -854,6 +946,9 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
|
||||
{
|
||||
Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(bottom_border);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ bottom_border, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
bottom_border->points[0] = end_left;
|
||||
bottom_border->points[1] = end_left - border2;
|
||||
@@ -870,6 +965,9 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
|
||||
{
|
||||
Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(top_left_corner);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ top_left_corner, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
top_left_corner->points[0] = begin_left;
|
||||
top_left_corner->points[1] = begin_left + border2;
|
||||
@@ -886,6 +984,9 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
|
||||
{
|
||||
Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(top_right_corner);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ top_right_corner, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
top_right_corner->points[0] = begin_right;
|
||||
top_right_corner->points[1] = begin_right + border2;
|
||||
@@ -902,6 +1003,9 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
|
||||
{
|
||||
Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(bottom_left_corner);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ bottom_left_corner, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
bottom_left_corner->points[0] = end_left;
|
||||
bottom_left_corner->points[1] = end_left - border2;
|
||||
@@ -918,6 +1022,9 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
|
||||
{
|
||||
Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(bottom_right_corner);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ bottom_right_corner, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
bottom_right_corner->points[0] = end_right;
|
||||
bottom_right_corner->points[1] = end_right - border2;
|
||||
@@ -989,6 +1096,9 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
|
||||
|
||||
Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();
|
||||
ERR_FAIL_NULL(pline);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ pline, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
if (p_antialiased) {
|
||||
p_width = canvas_item_get_compensated_antialiasing_width(p_width);
|
||||
@@ -1065,9 +1175,15 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
|
||||
|
||||
Item::CommandPolygon *pline_left = canvas_item->alloc_command<Item::CommandPolygon>();
|
||||
ERR_FAIL_NULL(pline_left);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ pline_left, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
Item::CommandPolygon *pline_right = canvas_item->alloc_command<Item::CommandPolygon>();
|
||||
ERR_FAIL_NULL(pline_right);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ pline_right, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
PackedColorArray colors_left;
|
||||
PackedVector2Array points_left;
|
||||
@@ -1274,6 +1390,10 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
|
||||
|
||||
Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();
|
||||
ERR_FAIL_NULL(pline);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ pline, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
pline->primitive = RSE::PRIMITIVE_LINES;
|
||||
pline->polygon.create(Vector<int>(), p_points, colors);
|
||||
} else {
|
||||
@@ -1306,6 +1426,10 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
|
||||
Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
|
||||
ERR_FAIL_NULL(rect);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ rect, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
rect->modulate = p_color;
|
||||
rect->rect = rect_adjusted;
|
||||
|
||||
@@ -1336,6 +1460,9 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
{
|
||||
Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(left_border);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ left_border, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
left_border->points[0] = begin_left;
|
||||
left_border->points[1] = begin_left + border;
|
||||
@@ -1352,6 +1479,9 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
{
|
||||
Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(right_border);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ right_border, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
right_border->points[0] = begin_right;
|
||||
right_border->points[1] = begin_right - border;
|
||||
@@ -1368,6 +1498,9 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
{
|
||||
Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(top_border);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ top_border, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
top_border->points[0] = begin_left;
|
||||
top_border->points[1] = begin_left + border2;
|
||||
@@ -1384,6 +1517,9 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
{
|
||||
Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(bottom_border);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ bottom_border, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
bottom_border->points[0] = end_left;
|
||||
bottom_border->points[1] = end_left - border2;
|
||||
@@ -1400,6 +1536,9 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
{
|
||||
Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(top_left_corner);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ top_left_corner, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
top_left_corner->points[0] = begin_left;
|
||||
top_left_corner->points[1] = begin_left + border2;
|
||||
@@ -1416,6 +1555,9 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
{
|
||||
Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(top_right_corner);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ top_right_corner, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
top_right_corner->points[0] = begin_right;
|
||||
top_right_corner->points[1] = begin_right + border2;
|
||||
@@ -1432,6 +1574,9 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
{
|
||||
Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(bottom_left_corner);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ bottom_left_corner, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
bottom_left_corner->points[0] = end_left;
|
||||
bottom_left_corner->points[1] = end_left - border2;
|
||||
@@ -1448,6 +1593,9 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
|
||||
{
|
||||
Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(bottom_right_corner);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ bottom_right_corner, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
bottom_right_corner->points[0] = end_right;
|
||||
bottom_right_corner->points[1] = end_right - border2;
|
||||
@@ -1481,6 +1629,9 @@ void RendererCanvasCull::canvas_item_add_ellipse(RID p_item, const Point2 &p_pos
|
||||
{
|
||||
Item::CommandPolygon *ellipse = canvas_item->alloc_command<Item::CommandPolygon>();
|
||||
ERR_FAIL_NULL(ellipse);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ ellipse, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
ellipse->primitive = RSE::PRIMITIVE_TRIANGLES;
|
||||
|
||||
@@ -1526,6 +1677,10 @@ void RendererCanvasCull::canvas_item_add_ellipse(RID p_item, const Point2 &p_pos
|
||||
|
||||
Item::CommandPolygon *feather = canvas_item->alloc_command<Item::CommandPolygon>();
|
||||
ERR_FAIL_NULL(feather);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ feather, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
feather->primitive = RSE::PRIMITIVE_TRIANGLE_STRIP;
|
||||
|
||||
Color transparent = Color(p_color, 0.0);
|
||||
@@ -1573,6 +1728,10 @@ void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
|
||||
|
||||
Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
|
||||
ERR_FAIL_NULL(rect);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ rect, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
rect->modulate = p_modulate;
|
||||
rect->rect = p_rect;
|
||||
rect->flags = 0;
|
||||
@@ -1604,6 +1763,10 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co
|
||||
|
||||
Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
|
||||
ERR_FAIL_NULL(rect);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ rect, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
rect->modulate = p_modulate;
|
||||
rect->rect = p_rect;
|
||||
|
||||
@@ -1638,6 +1801,10 @@ void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, con
|
||||
|
||||
Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
|
||||
ERR_FAIL_NULL(rect);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ rect, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
rect->modulate = p_modulate;
|
||||
rect->rect = p_rect;
|
||||
|
||||
@@ -1670,6 +1837,10 @@ void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const R
|
||||
|
||||
Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
|
||||
ERR_FAIL_NULL(rect);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ rect, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
rect->modulate = p_modulate;
|
||||
rect->rect = p_rect;
|
||||
|
||||
@@ -1711,6 +1882,9 @@ void RendererCanvasCull::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_r
|
||||
|
||||
Item::CommandNinePatch *style = canvas_item->alloc_command<Item::CommandNinePatch>();
|
||||
ERR_FAIL_NULL(style);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ style, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
style->texture = p_texture;
|
||||
|
||||
@@ -1735,6 +1909,9 @@ void RendererCanvasCull::canvas_item_add_primitive(RID p_item, const Vector<Poin
|
||||
|
||||
Item::CommandPrimitive *prim = canvas_item->alloc_command<Item::CommandPrimitive>();
|
||||
ERR_FAIL_NULL(prim);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ prim, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
for (int i = 0; i < p_points.size(); i++) {
|
||||
prim->points[i] = p_points[i];
|
||||
@@ -1771,7 +1948,12 @@ void RendererCanvasCull::canvas_item_add_polygon(RID p_item, const Vector<Point2
|
||||
|
||||
Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>();
|
||||
ERR_FAIL_NULL(polygon);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ polygon, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
polygon->primitive = RSE::PRIMITIVE_TRIANGLES;
|
||||
|
||||
polygon->texture = p_texture;
|
||||
polygon->polygon.create(indices, p_points, p_colors, p_uvs);
|
||||
}
|
||||
@@ -1789,6 +1971,9 @@ void RendererCanvasCull::canvas_item_add_triangle_array(RID p_item, const Vector
|
||||
|
||||
Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>();
|
||||
ERR_FAIL_NULL(polygon);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ polygon, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
polygon->texture = p_texture;
|
||||
|
||||
@@ -1800,10 +1985,28 @@ void RendererCanvasCull::canvas_item_add_triangle_array(RID p_item, const Vector
|
||||
void RendererCanvasCull::canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) {
|
||||
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||
ERR_FAIL_NULL(canvas_item);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
Item::PresortState st;
|
||||
if (canvas_item->presort_state >= 0) {
|
||||
st = canvas_item->presort_states[canvas_item->presort_state];
|
||||
}
|
||||
if (st.transform == p_transform) {
|
||||
return;
|
||||
}
|
||||
st.transform = p_transform;
|
||||
if (st.is_base_state()) {
|
||||
canvas_item->presort_state = -1;
|
||||
} else {
|
||||
canvas_item->presort_states.push_back(st);
|
||||
canvas_item->presort_state = canvas_item->presort_states.size() - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Item::CommandTransform *tr = canvas_item->alloc_command<Item::CommandTransform>();
|
||||
ERR_FAIL_NULL(tr);
|
||||
tr->xform = p_transform;
|
||||
canvas_item->presort_prev_state.transform = p_transform;
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture) {
|
||||
@@ -1813,6 +2016,10 @@ void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, con
|
||||
|
||||
Item::CommandMesh *m = canvas_item->alloc_command<Item::CommandMesh>();
|
||||
ERR_FAIL_NULL(m);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ m, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
m->mesh = p_mesh;
|
||||
if (canvas_item->skeleton.is_valid()) {
|
||||
m->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_mesh);
|
||||
@@ -1831,6 +2038,10 @@ void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles,
|
||||
|
||||
Item::CommandParticles *part = canvas_item->alloc_command<Item::CommandParticles>();
|
||||
ERR_FAIL_NULL(part);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ part, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
part->particles = p_particles;
|
||||
|
||||
part->texture = p_texture;
|
||||
@@ -1845,6 +2056,10 @@ void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p
|
||||
|
||||
Item::CommandMultiMesh *mm = canvas_item->alloc_command<Item::CommandMultiMesh>();
|
||||
ERR_FAIL_NULL(mm);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
canvas_item->presort_commands.push_back({ mm, canvas_item->presort_level, canvas_item->presort_state });
|
||||
}
|
||||
|
||||
mm->multimesh = p_mesh;
|
||||
|
||||
mm->texture = p_texture;
|
||||
@@ -1853,15 +2068,53 @@ void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p
|
||||
void RendererCanvasCull::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
|
||||
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||
ERR_FAIL_NULL(canvas_item);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
Item::PresortState st;
|
||||
if (canvas_item->presort_state >= 0) {
|
||||
st = canvas_item->presort_states[canvas_item->presort_state];
|
||||
}
|
||||
if (st.clip_ignore == p_ignore) {
|
||||
return;
|
||||
}
|
||||
st.clip_ignore = p_ignore;
|
||||
if (st.is_base_state()) {
|
||||
canvas_item->presort_state = -1;
|
||||
} else {
|
||||
canvas_item->presort_states.push_back(st);
|
||||
canvas_item->presort_state = canvas_item->presort_states.size() - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Item::CommandClipIgnore *ci = canvas_item->alloc_command<Item::CommandClipIgnore>();
|
||||
ERR_FAIL_NULL(ci);
|
||||
ci->ignore = p_ignore;
|
||||
canvas_item->presort_prev_state.clip_ignore = p_ignore;
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) {
|
||||
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||
ERR_FAIL_NULL(canvas_item);
|
||||
if (canvas_item->presort_level >= 0) {
|
||||
Item::PresortState st;
|
||||
if (canvas_item->presort_state >= 0) {
|
||||
st = canvas_item->presort_states[canvas_item->presort_state];
|
||||
}
|
||||
if (st.animation_length == p_animation_length && st.slice_begin == p_slice_begin && st.slice_end == p_slice_end && st.offset == p_offset) {
|
||||
return;
|
||||
}
|
||||
st.animation_length = p_animation_length;
|
||||
st.slice_begin = p_slice_begin;
|
||||
st.slice_end = p_slice_end;
|
||||
st.offset = p_offset;
|
||||
if (st.is_base_state()) {
|
||||
canvas_item->presort_state = -1;
|
||||
} else {
|
||||
canvas_item->presort_states.push_back(st);
|
||||
canvas_item->presort_state = canvas_item->presort_states.size() - 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Item::CommandAnimationSlice *as = canvas_item->alloc_command<Item::CommandAnimationSlice>();
|
||||
ERR_FAIL_NULL(as);
|
||||
@@ -1869,6 +2122,11 @@ void RendererCanvasCull::canvas_item_add_animation_slice(RID p_item, double p_an
|
||||
as->slice_begin = p_slice_begin;
|
||||
as->slice_end = p_slice_end;
|
||||
as->offset = p_offset;
|
||||
|
||||
canvas_item->presort_prev_state.animation_length = p_animation_length;
|
||||
canvas_item->presort_prev_state.slice_begin = p_slice_begin;
|
||||
canvas_item->presort_prev_state.slice_end = p_slice_end;
|
||||
canvas_item->presort_prev_state.offset = p_offset;
|
||||
}
|
||||
|
||||
void RendererCanvasCull::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
|
||||
@@ -1904,7 +2162,7 @@ void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton)
|
||||
}
|
||||
canvas_item->skeleton = p_skeleton;
|
||||
|
||||
Item::Command *c = canvas_item->commands;
|
||||
Item::Command *c = canvas_item->first_command;
|
||||
|
||||
while (c) {
|
||||
if (c->type == Item::Command::TYPE_MESH) {
|
||||
@@ -1946,6 +2204,12 @@ void RendererCanvasCull::canvas_item_clear(RID p_item) {
|
||||
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||
ERR_FAIL_NULL(canvas_item);
|
||||
|
||||
canvas_item->presort_commands.clear();
|
||||
canvas_item->presort_states.clear();
|
||||
canvas_item->presort_prev_command = nullptr;
|
||||
canvas_item->presort_level = -1;
|
||||
canvas_item->presort_state = -1;
|
||||
canvas_item->presort_prev_state = Item::PresortState();
|
||||
canvas_item->clear();
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
@@ -63,6 +63,95 @@ public:
|
||||
|
||||
Vector<Item *> child_items;
|
||||
|
||||
struct PresortData {
|
||||
Item::Command *command = nullptr;
|
||||
int32_t level = 0;
|
||||
int32_t state = -1;
|
||||
};
|
||||
struct PresortDataCompare {
|
||||
_FORCE_INLINE_ bool operator()(const PresortData &l, const PresortData &r) const {
|
||||
if (l.level == r.level) {
|
||||
uint64_t l_rid = 0;
|
||||
uint64_t r_rid = 0;
|
||||
switch (l.command->type) {
|
||||
case Item::Command::Type::TYPE_RECT: {
|
||||
l_rid = static_cast<CommandRect *>(l.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_NINEPATCH: {
|
||||
l_rid = static_cast<CommandNinePatch *>(l.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_POLYGON: {
|
||||
l_rid = static_cast<CommandPolygon *>(l.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_PRIMITIVE: {
|
||||
l_rid = static_cast<CommandPrimitive *>(l.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_MESH: {
|
||||
l_rid = static_cast<CommandMesh *>(l.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_MULTIMESH: {
|
||||
l_rid = static_cast<CommandMultiMesh *>(l.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_PARTICLES: {
|
||||
l_rid = static_cast<CommandParticles *>(l.command)->texture.get_id();
|
||||
} break;
|
||||
default: {
|
||||
l_rid = 0;
|
||||
} break;
|
||||
}
|
||||
switch (r.command->type) {
|
||||
case Item::Command::Type::TYPE_RECT: {
|
||||
r_rid = static_cast<CommandRect *>(r.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_NINEPATCH: {
|
||||
r_rid = static_cast<CommandNinePatch *>(r.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_POLYGON: {
|
||||
r_rid = static_cast<CommandPolygon *>(r.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_PRIMITIVE: {
|
||||
r_rid = static_cast<CommandPrimitive *>(r.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_MESH: {
|
||||
r_rid = static_cast<CommandMesh *>(r.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_MULTIMESH: {
|
||||
r_rid = static_cast<CommandMultiMesh *>(r.command)->texture.get_id();
|
||||
} break;
|
||||
case Item::Command::Type::TYPE_PARTICLES: {
|
||||
r_rid = static_cast<CommandParticles *>(r.command)->texture.get_id();
|
||||
} break;
|
||||
default: {
|
||||
r_rid = 0;
|
||||
} break;
|
||||
}
|
||||
return l_rid < r_rid;
|
||||
} else {
|
||||
return l.level < r.level;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct PresortState {
|
||||
Transform2D transform;
|
||||
bool clip_ignore = false;
|
||||
double animation_length = 0.0;
|
||||
double slice_begin = 0.0;
|
||||
double slice_end = 0.0;
|
||||
double offset = 0.0;
|
||||
|
||||
_FORCE_INLINE_ bool is_base_state() const {
|
||||
return transform == Transform2D() && !clip_ignore && animation_length == 0.0 && slice_begin == 0.0 && slice_end == 0.0 && offset == 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
int32_t presort_level = -1;
|
||||
int32_t presort_state = -1;
|
||||
Item::Command *presort_prev_command = nullptr;
|
||||
Item::PresortState presort_prev_state;
|
||||
LocalVector<PresortData> presort_commands;
|
||||
LocalVector<PresortState> presort_states;
|
||||
|
||||
struct VisibilityNotifierData {
|
||||
Rect2 area;
|
||||
Callable enter_callable;
|
||||
@@ -105,6 +194,16 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ void _insert_command(Item *p_canvas_item, Item::Command **r_prev_command, Item::Command *p_command) const {
|
||||
if (*r_prev_command) {
|
||||
(*r_prev_command)->next = p_command;
|
||||
} else {
|
||||
p_canvas_item->first_command = p_command;
|
||||
}
|
||||
*r_prev_command = p_command;
|
||||
}
|
||||
void _update_presort_state(Item *p_canvas_item, int32_t p_old_state, int32_t p_new_state, Item::Command **r_prev_command);
|
||||
|
||||
void _item_queue_update(Item *p_item, bool p_update_dependencies);
|
||||
SelfList<Item>::List _item_update_list;
|
||||
|
||||
@@ -280,6 +379,9 @@ public:
|
||||
void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
|
||||
void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset);
|
||||
|
||||
void canvas_item_set_presort_level(RID p_item, int64_t p_order);
|
||||
void canvas_item_flush_presort(RID p_item);
|
||||
|
||||
void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
|
||||
void canvas_item_set_z_index(RID p_item, int p_z);
|
||||
void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
|
||||
|
||||
@@ -41,7 +41,7 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const {
|
||||
|
||||
//must update rect
|
||||
|
||||
if (commands == nullptr) {
|
||||
if (first_command == nullptr) {
|
||||
rect = Rect2();
|
||||
rect_dirty = false;
|
||||
return rect;
|
||||
@@ -51,7 +51,7 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const {
|
||||
bool found_xform = false;
|
||||
bool first = true;
|
||||
|
||||
const Item::Command *c = commands;
|
||||
const Item::Command *c = first_command;
|
||||
|
||||
while (c) {
|
||||
Rect2 r;
|
||||
|
||||
@@ -374,7 +374,8 @@ public:
|
||||
|
||||
const Rect2 &get_rect() const;
|
||||
|
||||
Command *commands = nullptr;
|
||||
Command *heap_command = nullptr;
|
||||
Command *first_command = nullptr;
|
||||
Command *last_command = nullptr;
|
||||
Vector<CommandBlock> blocks;
|
||||
uint32_t current_block;
|
||||
@@ -383,15 +384,16 @@ public:
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
T *alloc_command() {
|
||||
T *alloc_command(bool p_set_next = true) {
|
||||
T *command = nullptr;
|
||||
if (commands == nullptr) {
|
||||
if (heap_command == nullptr) {
|
||||
// As the most common use case of canvas items is to
|
||||
// use only one command, the first is done with it's
|
||||
// own allocation. The rest of them use blocks.
|
||||
command = memnew(T);
|
||||
command->next = nullptr;
|
||||
commands = command;
|
||||
heap_command = command;
|
||||
first_command = command;
|
||||
last_command = command;
|
||||
} else {
|
||||
//Subsequent commands go into a block.
|
||||
@@ -418,7 +420,9 @@ public:
|
||||
void *memory = c->memory + c->usage;
|
||||
command = memnew_placement(memory, T);
|
||||
command->next = nullptr;
|
||||
last_command->next = command;
|
||||
if (p_set_next) {
|
||||
last_command->next = command;
|
||||
}
|
||||
last_command = command;
|
||||
c->usage += sizeof(T);
|
||||
break;
|
||||
@@ -430,14 +434,14 @@ public:
|
||||
}
|
||||
|
||||
void clear() {
|
||||
// The first one is always allocated on heap
|
||||
// The `heap_command` is always allocated on heap
|
||||
// the rest go in the blocks
|
||||
Command *c = commands;
|
||||
Command *c = first_command;
|
||||
while (c) {
|
||||
Command *n = c->next;
|
||||
if (c == commands) {
|
||||
memdelete(commands);
|
||||
commands = nullptr;
|
||||
if (c == heap_command) {
|
||||
memdelete(heap_command);
|
||||
heap_command = nullptr;
|
||||
} else {
|
||||
c->~Command();
|
||||
}
|
||||
@@ -451,8 +455,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
heap_command = nullptr;
|
||||
last_command = nullptr;
|
||||
commands = nullptr;
|
||||
first_command = nullptr;
|
||||
current_block = 0;
|
||||
clip = false;
|
||||
rect_dirty = true;
|
||||
@@ -465,8 +470,9 @@ public:
|
||||
RSE::CanvasItemTextureRepeat texture_repeat;
|
||||
|
||||
Item() {
|
||||
commands = nullptr;
|
||||
heap_command = nullptr;
|
||||
last_command = nullptr;
|
||||
first_command = nullptr;
|
||||
current_block = 0;
|
||||
light_mask = 1;
|
||||
vp_render = nullptr;
|
||||
|
||||
@@ -795,7 +795,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
|
||||
}
|
||||
|
||||
if (ci->skeleton.is_valid()) {
|
||||
const Item::Command *c = ci->commands;
|
||||
const Item::Command *c = ci->first_command;
|
||||
|
||||
while (c) {
|
||||
if (c->type == Item::Command::TYPE_MESH) {
|
||||
@@ -2397,7 +2397,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
|
||||
r_current_batch->use_lighting = use_lighting;
|
||||
}
|
||||
|
||||
const Item::Command *c = p_item->commands;
|
||||
const Item::Command *c = p_item->first_command;
|
||||
while (c) {
|
||||
if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) {
|
||||
c = c->next;
|
||||
|
||||
@@ -3358,6 +3358,9 @@ void RenderingServer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &RenderingServer::canvas_item_set_copy_to_backbuffer);
|
||||
ClassDB::bind_method(D_METHOD("canvas_item_attach_skeleton", "item", "skeleton"), &RenderingServer::canvas_item_attach_skeleton);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("canvas_item_set_presort_level", "item", "order"), &RenderingServer::canvas_item_set_presort_level);
|
||||
ClassDB::bind_method(D_METHOD("canvas_item_flush_presort", "item"), &RenderingServer::canvas_item_flush_presort);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &RenderingServer::canvas_item_clear);
|
||||
ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &RenderingServer::canvas_item_set_draw_index);
|
||||
ClassDB::bind_method(D_METHOD("canvas_item_set_material", "item", "material"), &RenderingServer::canvas_item_set_material);
|
||||
|
||||
@@ -839,6 +839,9 @@ public:
|
||||
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0;
|
||||
virtual void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) = 0;
|
||||
|
||||
virtual void canvas_item_set_presort_level(RID p_item, int64_t p_order) = 0;
|
||||
virtual void canvas_item_flush_presort(RID p_item) = 0;
|
||||
|
||||
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0;
|
||||
virtual void canvas_item_set_z_index(RID p_item, int p_z) = 0;
|
||||
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0;
|
||||
|
||||
@@ -1045,6 +1045,9 @@ public:
|
||||
FUNC2(canvas_item_add_clip_ignore, RID, bool)
|
||||
FUNC5(canvas_item_add_animation_slice, RID, double, double, double, double)
|
||||
|
||||
FUNC2(canvas_item_set_presort_level, RID, int64_t);
|
||||
FUNC1(canvas_item_flush_presort, RID);
|
||||
|
||||
FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
|
||||
FUNC2(canvas_item_set_z_index, RID, int)
|
||||
FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
|
||||
|
||||
Reference in New Issue
Block a user