summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/math/quick_hull.cpp11
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp947
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.h46
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp5
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h4
-rw-r--r--drivers/gles2/shader_gles2.cpp14
-rw-r--r--drivers/gles2/shader_gles2.h1
-rw-r--r--drivers/gles2/shaders/canvas.glsl33
-rw-r--r--editor/editor_help.cpp8
-rw-r--r--editor/editor_settings.cpp1
-rw-r--r--editor/find_in_files.cpp257
-rw-r--r--editor/find_in_files.h24
-rw-r--r--modules/bullet/godot_result_callbacks.cpp4
-rw-r--r--modules/mono/config.py4
-rw-r--r--scene/resources/material.cpp2
15 files changed, 689 insertions, 672 deletions
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index cb923d264e..45c106102e 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -397,7 +397,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
Map<Edge, RetFaceConnect>::Element *F = ret_edges.find(e);
ERR_CONTINUE(!F);
-
List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left;
ERR_CONTINUE(O == E);
ERR_CONTINUE(O == NULL);
@@ -426,7 +425,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
Edge e2(idx, idxn);
Map<Edge, RetFaceConnect>::Element *F2 = ret_edges.find(e2);
-
ERR_CONTINUE(!F2);
//change faceconnect, point to this face instead
if (F2->get().left == O)
@@ -439,6 +437,15 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
}
}
+ // remove all edge connections to this face
+ for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) {
+ if (E->get().left == O)
+ E->get().left = NULL;
+
+ if (E->get().right == O)
+ E->get().right = NULL;
+ }
+
ret_edges.erase(F); //remove the edge
ret_faces.erase(O); //remove the face
}
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index f7b49c627d..d6fbf04353 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -64,13 +64,9 @@ void RasterizerCanvasGLES2::_set_uniforms() {
state.canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
}
-
- state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, state.uniforms.texpixel_size);
}
void RasterizerCanvasGLES2::canvas_begin() {
- data.primitive = GL_TRIANGLES;
- data.texture = GL_NONE;
state.canvas_shader.bind();
if (storage->frame.current_rt) {
@@ -99,7 +95,6 @@ void RasterizerCanvasGLES2::canvas_begin() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
- data.texture = storage->resources.white_tex;
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
glDisableVertexAttribArray(VS::ARRAY_COLOR);
@@ -130,7 +125,7 @@ void RasterizerCanvasGLES2::canvas_begin() {
state.uniforms.extra_matrix = Transform2D();
_set_uniforms();
- state.prev_uniforms = state.uniforms;
+ _bind_quad_buffer();
}
void RasterizerCanvasGLES2::canvas_end() {
@@ -148,7 +143,6 @@ void RasterizerCanvasGLES2::canvas_end() {
RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) {
RasterizerStorageGLES2::Texture *tex_return = NULL;
- GLuint newtexid;
if (p_texture.is_valid()) {
@@ -158,7 +152,8 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
state.current_tex = RID();
state.current_tex_ptr = NULL;
- newtexid = storage->resources.white_tex;
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
} else {
@@ -172,7 +167,8 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
texture->render_target->used_in_frame = true;
}
- newtexid = texture->tex_id;
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture->tex_id);
state.current_tex = p_texture;
state.current_tex_ptr = texture;
@@ -183,15 +179,8 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
state.current_tex = RID();
state.current_tex_ptr = NULL;
- newtexid = storage->resources.white_tex;
- }
-
- if (data.texture != newtexid) {
- _flush();
-
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, newtexid);
- data.texture = newtexid;
+ glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
}
return tex_return;
@@ -201,154 +190,217 @@ void RasterizerCanvasGLES2::_set_texture_rect_mode(bool p_enable, bool p_ninepat
}
void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) {
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
- bool single;
- Color color;
+ uint32_t buffer_ofs = 0;
+
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
+ buffer_ofs += sizeof(Vector2) * p_vertex_count;
if (p_singlecolor) {
- single = true;
- color = *p_colors;
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ Color m = *p_colors;
+ glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
} else if (!p_colors) {
- single = true;
- color = Color(1, 1, 1, 1);
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
+ } else {
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
+ glEnableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), ((uint8_t *)0) + buffer_ofs);
+ buffer_ofs += sizeof(Color) * p_vertex_count;
+ }
+
+ if (p_uvs) {
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs);
+ buffer_ofs += sizeof(Vector2) * p_vertex_count;
} else {
- single = false;
+ glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
}
- const bool use_single_color = single;
- const Color single_color = color;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices);
+
+ glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+}
- for (int i = 0; i < p_vertex_count; ++i) {
- v->v = p_vertices[i];
+void RasterizerCanvasGLES2::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
+ glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
- if (p_uvs)
- v->uv = p_uvs[i];
- else
- v->uv = Vector2();
+ uint32_t buffer_ofs = 0;
- ++v;
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), (uint8_t *)0);
+ buffer_ofs += sizeof(Vector2) * p_vertex_count;
+
+ if (p_singlecolor) {
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ Color m = *p_colors;
+ glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
+ } else if (!p_colors) {
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
+ } else {
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
+ glEnableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), ((uint8_t *)0) + buffer_ofs);
+ buffer_ofs += sizeof(Color) * p_vertex_count;
}
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, p_indices, p_index_count * sizeof(int));
+ if (p_uvs) {
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs);
+ } else {
+ glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
+ }
- _commit(p_vertex_count, p_index_count);
+ glDrawArrays(p_primitive, 0, p_vertex_count);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
-void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material) {
+void RasterizerCanvasGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) {
- int command_count = p_item->commands.size();
- Item::Command **commands = p_item->commands.ptrw();
+ static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN };
- for (int i = 0; i < command_count; i++) {
+ int color_offset = 0;
+ int uv_offset = 0;
+ int stride = 2;
- Item::Command *command = commands[i];
+ if (p_colors) {
+ color_offset = stride;
+ stride += 4;
+ }
- if (command->type != Item::Command::TYPE_RECT && state.tiled) {
- _flush();
- _untile();
- }
+ if (p_uvs) {
+ uv_offset = stride;
+ stride += 2;
+ }
- switch (command->type) {
+ float buffer_data[(2 + 2 + 4) * 4];
- case Item::Command::TYPE_LINE: {
- const Item::CommandLine *line = static_cast<Item::CommandLine *>(command);
+ for (int i = 0; i < p_points; i++) {
+ buffer_data[stride * i + 0] = p_vertices[i].x;
+ buffer_data[stride * i + 1] = p_vertices[i].y;
+ }
- if (line->width <= 1) {
- const int p_vertex_count = 2;
- const int p_index_count = 2;
+ if (p_colors) {
+ for (int i = 0; i < p_points; i++) {
+ buffer_data[stride * i + color_offset + 0] = p_colors[i].r;
+ buffer_data[stride * i + color_offset + 1] = p_colors[i].g;
+ buffer_data[stride * i + color_offset + 2] = p_colors[i].b;
+ buffer_data[stride * i + color_offset + 3] = p_colors[i].a;
+ }
+ }
- _begin(GL_LINES);
- _prepare(p_vertex_count, p_index_count);
+ if (p_uvs) {
+ for (int i = 0; i < p_points; i++) {
+ buffer_data[stride * i + uv_offset + 0] = p_uvs[i].x;
+ buffer_data[stride * i + uv_offset + 1] = p_uvs[i].y;
+ }
+ }
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), buffer_data);
- Vertex vertices[p_vertex_count];
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), NULL);
- vertices[0].v = Vector2(line->from.x, line->from.y);
- vertices[0].c = line->color;
- vertices[0].uv = Vector2();
+ if (p_colors) {
+ glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), (uint8_t *)0 + color_offset * sizeof(float));
+ glEnableVertexAttribArray(VS::ARRAY_COLOR);
+ }
- vertices[1].v = Vector2(line->to.x, line->to.y);
- vertices[1].c = line->color;
- vertices[1].uv = Vector2();
+ if (p_uvs) {
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), (uint8_t *)0 + uv_offset * sizeof(float));
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ }
- memcpy(data.mem_vertex_buffer + data.mem_vertex_buffer_offset, vertices, sizeof(vertices));
+ glDrawArrays(prim[p_points], 0, p_points);
- const int indices[p_index_count] = { 0, 1 };
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, indices, sizeof(indices));
+void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material) {
- _commit(p_vertex_count, p_index_count);
- } else {
- const int p_vertex_count = 4;
- const int p_index_count = 6;
+ int command_count = p_item->commands.size();
+ Item::Command **commands = p_item->commands.ptrw();
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
+ for (int i = 0; i < command_count; i++) {
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ Item::Command *command = commands[i];
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ switch (command->type) {
- Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5;
+ case Item::Command::TYPE_LINE: {
- v[0].v = line->from - t;
- v[0].c = line->color;
- v[0].uv = Vector2();
+ Item::CommandLine *line = static_cast<Item::CommandLine *>(command);
- v[1].v = line->from + t;
- v[1].c = line->color;
- v[1].uv = Vector2();
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
- v[2].v = line->to + t;
- v[2].c = line->color;
- v[2].uv = Vector2();
+ _bind_canvas_texture(RID(), RID());
+
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4fv(VS::ARRAY_COLOR, line->color.components);
- v[3].v = line->to - t;
- v[3].c = line->color;
- v[3].uv = Vector2();
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix);
- const int indices[p_index_count] = {
- 0, 1, 2,
- 2, 3, 0
+ if (line->width <= 1) {
+ Vector2 verts[2] = {
+ Vector2(line->from.x, line->from.y),
+ Vector2(line->to.x, line->to.y)
};
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, indices, sizeof(indices));
+ _draw_gui_primitive(2, verts, NULL, NULL);
+ } else {
+ Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5;
- _commit(p_vertex_count, p_index_count);
- }
+ Vector2 verts[4] = {
+ line->from - t,
+ line->from + t,
+ line->to + t,
+ line->to - t
+ };
+ _draw_gui_primitive(4, verts, NULL, NULL);
+ }
} break;
case Item::Command::TYPE_RECT: {
- const int p_vertex_count = 4;
- const int p_index_count = 6;
-
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
Item::CommandRect *r = static_cast<Item::CommandRect *>(command);
- _bind_shader(p_material);
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4fv(VS::ARRAY_COLOR, r->modulate.components);
- Rect2 src_rect;
- Rect2 dst_rect;
+ _bind_quad_buffer();
+
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map);
if (!tex) {
- dst_rect = Rect2(r->rect.position, r->rect.size);
+ Rect2 dst_rect = Rect2(r->rect.position, r->rect.size);
if (dst_rect.size.width < 0) {
dst_rect.position.x += dst_rect.size.width;
@@ -359,28 +411,24 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
dst_rect.size.height *= -1;
}
- src_rect = Rect2(0, 0, 1, 1);
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y));
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(0, 0, 1, 1));
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
} else {
- const bool tiled = r->flags & CANVAS_RECT_TILE && !(tex->flags & VS::TEXTURE_FLAG_REPEAT);
+ bool untile = false;
- if (tiled != state.tiled) {
- _flush();
-
- if (tiled) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- state.tiled = true;
- } else {
- _untile();
- }
+ if (r->flags & CANVAS_RECT_TILE && !(tex->flags & VS::TEXTURE_FLAG_REPEAT)) {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ untile = true;
}
Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height);
+ Rect2 src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1);
- src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1);
- dst_rect = Rect2(r->rect.position, r->rect.size);
+ Rect2 dst_rect = Rect2(r->rect.position, r->rect.size);
if (dst_rect.size.width < 0) {
dst_rect.position.x += dst_rect.size.width;
@@ -393,61 +441,48 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
if (r->flags & CANVAS_RECT_FLIP_H) {
src_rect.size.x *= -1;
- src_rect.position.x -= src_rect.size.width;
}
+
if (r->flags & CANVAS_RECT_FLIP_V) {
src_rect.size.y *= -1;
- src_rect.position.y -= src_rect.size.height;
}
+
if (r->flags & CANVAS_RECT_TRANSPOSE) {
dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform
}
- state.uniforms.texpixel_size = texpixel_size;
- }
-
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
-
- // 0,0
- v[0].v = dst_rect.position;
- v[0].c = r->modulate;
- v[0].uv = src_rect.position;
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
- // 0,1
- v[1].v = Vector2(dst_rect.position.x, dst_rect.position.y + dst_rect.size.y);
- v[1].c = r->modulate;
- v[1].uv = Vector2(src_rect.position.x, src_rect.position.y + src_rect.size.y);
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y));
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y));
- // 1,1
- v[2].v = Vector2(dst_rect.position.x + dst_rect.size.x, dst_rect.position.y + dst_rect.size.y);
- v[2].c = r->modulate;
- v[2].uv = Vector2(src_rect.position.x + src_rect.size.x, src_rect.position.y + src_rect.size.y);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- // 1,0
- v[3].v = Vector2(dst_rect.position.x + dst_rect.size.x, dst_rect.position.y);
- v[3].c = r->modulate;
- v[3].uv = Vector2(src_rect.position.x + src_rect.size.x, src_rect.position.y);
-
- const int indices[p_index_count] = {
- 0, 1, 2,
- 2, 3, 0
- };
+ if (untile) {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ }
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, indices, sizeof(int) * p_index_count);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- _commit(p_vertex_count, p_index_count);
} break;
case Item::Command::TYPE_NINEPATCH: {
- const int p_vertex_count = 16;
- const int p_index_count = 54;
-
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
Item::CommandNinePatch *np = static_cast<Item::CommandNinePatch *>(command);
- _bind_shader(p_material);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
+
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4fv(VS::ARRAY_COLOR, np->color.components);
+
RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(np->texture, np->normal_map);
if (!tex) {
@@ -457,7 +492,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height);
- state.uniforms.texpixel_size = texpixel_size;
+ // state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix);
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
Rect2 source = np->source;
if (source.size.x == 0 && source.size.y == 0) {
@@ -469,334 +505,255 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
// this buffer contains [ POS POS UV UV ] *
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ float buffer[16 * 2 + 16 * 2];
- v[0].v = np->rect.position;
- v[0].c = np->color;
- v[0].uv = source.position * texpixel_size;
+ {
- v[1].v = np->rect.position + Vector2(np->margin[MARGIN_LEFT], 0);
- v[1].c = np->color;
- v[1].uv = (source.position + Vector2(np->margin[MARGIN_LEFT], 0)) * texpixel_size;
+ // first row
- v[2].v = np->rect.position + Vector2(np->rect.size.x - np->margin[MARGIN_RIGHT], 0);
- v[2].c = np->color;
- v[2].uv = (source.position + Vector2(source.size.x - np->margin[MARGIN_RIGHT], 0)) * texpixel_size;
+ buffer[(0 * 4 * 4) + 0] = np->rect.position.x;
+ buffer[(0 * 4 * 4) + 1] = np->rect.position.y;
- v[3].v = np->rect.position + Vector2(np->rect.size.x, 0);
- v[3].c = np->color;
- v[3].uv = (source.position + Vector2(source.size.x, 0)) * texpixel_size;
+ buffer[(0 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
+ buffer[(0 * 4 * 4) + 3] = source.position.y * texpixel_size.y;
- v[4].v = np->rect.position + Vector2(0, np->margin[MARGIN_TOP]);
- v[4].c = np->color;
- v[4].uv = (source.position + Vector2(0, np->margin[MARGIN_TOP])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+ buffer[(0 * 4 * 4) + 5] = np->rect.position.y;
- v[5].v = np->rect.position + Vector2(np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]);
- v[5].c = np->color;
- v[5].uv = (source.position + Vector2(np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
+ buffer[(0 * 4 * 4) + 7] = source.position.y * texpixel_size.y;
- v[6].v = np->rect.position + Vector2(np->rect.size.x - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]);
- v[6].c = np->color;
- v[6].uv = (source.position + Vector2(source.size.x - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+ buffer[(0 * 4 * 4) + 9] = np->rect.position.y;
- v[7].v = np->rect.position + Vector2(np->rect.size.x, np->margin[MARGIN_TOP]);
- v[7].c = np->color;
- v[7].uv = (source.position + Vector2(source.size.x, np->margin[MARGIN_TOP])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
+ buffer[(0 * 4 * 4) + 11] = source.position.y * texpixel_size.y;
- v[8].v = np->rect.position + Vector2(0, np->rect.size.y - np->margin[MARGIN_BOTTOM]);
- v[8].c = np->color;
- v[8].uv = (source.position + Vector2(0, source.size.y - np->margin[MARGIN_BOTTOM])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
+ buffer[(0 * 4 * 4) + 13] = np->rect.position.y;
- v[9].v = np->rect.position + Vector2(np->margin[MARGIN_LEFT], np->rect.size.y - np->margin[MARGIN_BOTTOM]);
- v[9].c = np->color;
- v[9].uv = (source.position + Vector2(np->margin[MARGIN_LEFT], source.size.y - np->margin[MARGIN_BOTTOM])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
+ buffer[(0 * 4 * 4) + 15] = source.position.y * texpixel_size.y;
- v[10].v = np->rect.position + np->rect.size - Vector2(np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]);
- v[10].c = np->color;
- v[10].uv = (source.position + source.size - Vector2(np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM])) * texpixel_size;
+ // second row
- v[11].v = np->rect.position + np->rect.size - Vector2(0, np->margin[MARGIN_BOTTOM]);
- v[11].c = np->color;
- v[11].uv = (source.position + source.size - Vector2(0, np->margin[MARGIN_BOTTOM])) * texpixel_size;
+ buffer[(1 * 4 * 4) + 0] = np->rect.position.x;
+ buffer[(1 * 4 * 4) + 1] = np->rect.position.y + np->margin[MARGIN_TOP];
- v[12].v = np->rect.position + Vector2(0, np->rect.size.y);
- v[12].c = np->color;
- v[12].uv = (source.position + Vector2(0, source.size.y)) * texpixel_size;
+ buffer[(1 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
+ buffer[(1 * 4 * 4) + 3] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- v[13].v = np->rect.position + Vector2(np->margin[MARGIN_LEFT], np->rect.size.y);
- v[13].c = np->color;
- v[13].uv = (source.position + Vector2(np->margin[MARGIN_LEFT], source.size.y)) * texpixel_size;
+ buffer[(1 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+ buffer[(1 * 4 * 4) + 5] = np->rect.position.y + np->margin[MARGIN_TOP];
- v[14].v = np->rect.position + np->rect.size - Vector2(np->margin[MARGIN_RIGHT], 0);
- v[14].c = np->color;
- v[14].uv = (source.position + source.size - Vector2(np->margin[MARGIN_RIGHT], 0)) * texpixel_size;
+ buffer[(1 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
+ buffer[(1 * 4 * 4) + 7] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- v[15].v = np->rect.position + np->rect.size;
- v[15].c = np->color;
- v[15].uv = (source.position + source.size) * texpixel_size;
+ buffer[(1 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+ buffer[(1 * 4 * 4) + 9] = np->rect.position.y + np->margin[MARGIN_TOP];
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, data.ninepatch_elements, sizeof(data.ninepatch_elements));
+ buffer[(1 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
+ buffer[(1 * 4 * 4) + 11] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- _commit(p_vertex_count, p_index_count - (np->draw_center ? 0 : 6));
- } break;
+ buffer[(1 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
+ buffer[(1 * 4 * 4) + 13] = np->rect.position.y + np->margin[MARGIN_TOP];
- case Item::Command::TYPE_CIRCLE: {
- Item::CommandCircle *circle = static_cast<Item::CommandCircle *>(command);
+ buffer[(1 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
+ buffer[(1 * 4 * 4) + 15] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- _bind_shader(p_material);
+ // thrid row
- const int num_points = 32;
+ buffer[(2 * 4 * 4) + 0] = np->rect.position.x;
+ buffer[(2 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
- Vector2 points[num_points + 1];
- points[num_points] = circle->pos;
+ buffer[(2 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
+ buffer[(2 * 4 * 4) + 3] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
- int indices[num_points * 3];
+ buffer[(2 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+ buffer[(2 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
- for (int i = 0; i < num_points; i++) {
- points[i] = circle->pos + Vector2(Math::sin(i * Math_PI * 2.0 / num_points), Math::cos(i * Math_PI * 2.0 / num_points)) * circle->radius;
- indices[i * 3 + 0] = i;
- indices[i * 3 + 1] = (i + 1) % num_points;
- indices[i * 3 + 2] = num_points;
- }
+ buffer[(2 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
+ buffer[(2 * 4 * 4) + 7] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
- _bind_canvas_texture(RID(), RID());
-
- _draw_polygon(indices, num_points * 3, num_points + 1, points, NULL, &circle->color, true);
- } break;
+ buffer[(2 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+ buffer[(2 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
- case Item::Command::TYPE_POLYGON: {
- Item::CommandPolygon *polygon = static_cast<Item::CommandPolygon *>(command);
+ buffer[(2 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
+ buffer[(2 * 4 * 4) + 11] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
- const int *indices = polygon->indices.ptr();
- if (!indices) // self-intersecting polygon
- break;
+ buffer[(2 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
+ buffer[(2 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
- _bind_shader(p_material);
- RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map);
+ buffer[(2 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
+ buffer[(2 * 4 * 4) + 15] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
- if (texture) {
- Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.uniforms.texpixel_size = texpixel_size;
- }
-
- _draw_polygon(indices, polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
- } break;
-
- case Item::Command::TYPE_POLYLINE: {
- Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(command);
+ // fourth row
- if (pline->triangles.size()) {
- const int p_vertex_count = pline->triangles.size();
- const int p_triangle_count = p_vertex_count - 2;
- const int p_index_count = p_triangle_count * 3;
+ buffer[(3 * 4 * 4) + 0] = np->rect.position.x;
+ buffer[(3 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y;
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
+ buffer[(3 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
+ buffer[(3 * 4 * 4) + 3] = (source.position.y + source.size.y) * texpixel_size.y;
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ buffer[(3 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+ buffer[(3 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y;
- const Vector2 *t = pline->triangles.ptr();
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ buffer[(3 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
+ buffer[(3 * 4 * 4) + 7] = (source.position.y + source.size.y) * texpixel_size.y;
- const bool p_singlecolor = pline->triangle_colors.size() == 1;
- const Color *p_colors = pline->triangle_colors.ptr();
+ buffer[(3 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+ buffer[(3 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y;
- bool single;
- Color color;
+ buffer[(3 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
+ buffer[(3 * 4 * 4) + 11] = (source.position.y + source.size.y) * texpixel_size.y;
- if (pline->triangle_colors.size() == 1) {
- single = true;
- color = *p_colors;
- } else if (!p_colors) {
- single = true;
- color = Color(1, 1, 1, 1);
- } else {
- single = false;
- }
+ buffer[(3 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
+ buffer[(3 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y;
- const bool use_single_color = single;
- const Color single_color = color;
+ buffer[(3 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
+ buffer[(3 * 4 * 4) + 15] = (source.position.y + source.size.y) * texpixel_size.y;
- for (int i = 0; i < p_vertex_count; ++i) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
+ // print_line(String::num((source.position.y + source.size.y) * texpixel_size.y));
+ }
- v->uv = Vector2();
- v->v = t[i];
+ glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * (16 + 16) * 2, buffer);
- ++v;
- }
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements);
- for (int i = 0; i < p_triangle_count; ++i) {
- const int indices[3] = {
- i, i + 1, i + 2
- };
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset + i * 3, indices, sizeof(indices));
- }
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), NULL);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (uint8_t *)0 + (sizeof(float) * 2));
- _commit(p_vertex_count, p_index_count);
- } else {
- _begin(GL_LINES);
+ glDrawElements(GL_TRIANGLES, 18 * 3 - (np->draw_center ? 0 : 6), GL_UNSIGNED_BYTE, NULL);
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- const Color *p_colors = pline->line_colors.ptr();
+ } break;
- bool single;
- Color color;
+ case Item::Command::TYPE_CIRCLE: {
- if (pline->line_colors.size() == 1) {
- single = true;
- color = *p_colors;
- } else if (!p_colors) {
- single = true;
- color = Color(1, 1, 1, 1);
- } else {
- single = false;
- }
+ Item::CommandCircle *circle = static_cast<Item::CommandCircle *>(command);
- const bool use_single_color = single;
- const Color single_color = color;
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
- const Vector2 *p_lines = pline->lines.ptr();
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
- if (pline->multiline) {
- const int p_lines_count = pline->lines.size() / 2;
+ static const int num_points = 32;
- for (int i = 0; i < p_lines_count; ++i) {
- const int p_vertex_count = 2;
- const int p_index_count = 2;
+ Vector2 points[num_points + 1];
+ points[num_points] = circle->pos;
- _prepare(p_vertex_count, p_index_count);
+ int indices[num_points * 3];
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ for (int i = 0; i < num_points; i++) {
+ points[i] = circle->pos + Vector2(Math::sin(i * Math_PI * 2.0 / num_points), Math::cos(i * Math_PI * 2.0 / num_points)) * circle->radius;
+ indices[i * 3 + 0] = i;
+ indices[i * 3 + 1] = (i + 1) % num_points;
+ indices[i * 3 + 2] = num_points;
+ }
- for (int j = 0; j < 2; ++j) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
+ _bind_canvas_texture(RID(), RID());
- v->uv = Vector2();
- v->v = p_lines[i * 2 + j];
+ _draw_polygon(indices, num_points * 3, num_points + 1, points, NULL, &circle->color, true);
+ } break;
- ++v;
- }
+ case Item::Command::TYPE_POLYGON: {
- const int indices[p_index_count] = { 0, 1 };
+ Item::CommandPolygon *polygon = static_cast<Item::CommandPolygon *>(command);
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, indices, sizeof(indices));
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
- _commit(p_vertex_count, p_index_count);
- }
- } else {
- const int p_vertex_count = pline->lines.size();
- const int p_lines_count = p_vertex_count - 1;
- const int p_index_count = p_lines_count * 2;
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
- _prepare(p_vertex_count, p_index_count);
+ RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map);
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ if (texture) {
+ Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
+ }
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+ } break;
- for (int i = 0; i < p_vertex_count; ++i) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
+ case Item::Command::TYPE_POLYLINE: {
+ Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(command);
- v->uv = Vector2();
- v->v = p_lines[i];
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
- ++v;
- }
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
- for (int i = 0; i < p_lines_count; ++i) {
- const int indices[2] = { i, i + 1 };
+ _bind_canvas_texture(RID(), RID());
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset + i * 2, indices, sizeof(indices));
+ if (pline->triangles.size()) {
+ _draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1);
+ } else {
+ if (pline->multiline) {
+ int todo = pline->lines.size() / 2;
+ int max_per_call = data.polygon_buffer_size / (sizeof(real_t) * 4);
+ int offset = 0;
+
+ while (todo) {
+ int to_draw = MIN(max_per_call, todo);
+ _draw_generic(GL_LINES, to_draw * 2, &pline->lines.ptr()[offset], NULL, pline->line_colors.size() == 1 ? pline->line_colors.ptr() : &pline->line_colors.ptr()[offset], pline->line_colors.size() == 1);
+ todo -= to_draw;
+ offset += to_draw * 2;
}
-
- _commit(p_vertex_count, p_index_count);
+ } else {
+ _draw_generic(GL_LINES, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1);
}
}
} break;
case Item::Command::TYPE_PRIMITIVE: {
+
Item::CommandPrimitive *primitive = static_cast<Item::CommandPrimitive *>(command);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
- const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN };
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
ERR_CONTINUE(primitive->points.size() < 1);
- _bind_shader(p_material);
RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(primitive->texture, primitive->normal_map);
if (texture) {
Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.uniforms.texpixel_size = texpixel_size;
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
}
- const int p_vertex_count = primitive->points.size();
- const int p_index_count = p_vertex_count;
-
- _begin(prim[p_vertex_count]);
- _prepare(p_vertex_count, p_index_count);
-
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
- int *index = data.mem_index_buffer + data.mem_index_buffer_offset;
-
- Color c;
- bool p_single_color;
-
- const Color *p_colors = primitive->colors.ptr();
- const Vector2 *p_uvs = primitive->uvs.ptr();
- const Vector2 *p_points = primitive->points.ptr();
-
if (primitive->colors.size() == 1 && primitive->points.size() > 1) {
- p_single_color = true;
- c = primitive->colors[0];
+ Color c = primitive->colors[0];
+ glVertexAttrib4f(VS::ARRAY_COLOR, c.r, c.g, c.b, c.a);
} else if (primitive->colors.empty()) {
- p_single_color = true;
- c = Color(1, 1, 1, 1);
- } else {
- p_single_color = false;
- }
-
- const bool use_single_color = p_single_color;
- const Color single_color = c;
-
- for (int i = 0; i < p_vertex_count; ++i) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
-
- if (p_uvs)
- v->uv = p_uvs[i];
- else
- v->uv = Vector2();
-
- v->v = p_points[i];
-
- index[i] = i;
-
- ++v;
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
}
- _commit(p_vertex_count, p_index_count);
+ _draw_gui_primitive(primitive->points.size(), primitive->points.ptr(), primitive->colors.ptr(), primitive->uvs.ptr());
} break;
case Item::Command::TYPE_TRANSFORM: {
Item::CommandTransform *transform = static_cast<Item::CommandTransform *>(command);
state.uniforms.extra_matrix = transform->xform;
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, state.uniforms.extra_matrix);
} break;
case Item::Command::TYPE_PARTICLES: {
@@ -859,7 +816,6 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
- data.texture = storage->resources.white_tex;
int last_blend_mode = -1;
@@ -869,9 +825,8 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
Item *ci = p_item_list;
- Item *material_owner = ci->material_owner ? ci->material_owner : ci;
-
if (current_clip != ci->final_clip_owner) {
+
current_clip = ci->final_clip_owner;
if (current_clip) {
@@ -895,6 +850,8 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
}
}
+ Item *material_owner = ci->material_owner ? ci->material_owner : ci;
+
RID material = material_owner->material;
RasterizerStorageGLES2::Material *material_ptr = storage->material_owner.getornull(material);
@@ -1024,10 +981,8 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
state.uniforms.extra_matrix = Transform2D();
_set_uniforms();
- _canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr);
- // TODO: figure out when to _flush to get better batching results
- _flush();
+ _canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr);
rebind_shader = true; // hacked in for now.
@@ -1042,8 +997,6 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
p_item_list = p_item_list->next;
}
- _flush();
-
if (current_clip) {
glDisable(GL_SCISSOR_TEST);
}
@@ -1082,40 +1035,17 @@ void RasterizerCanvasGLES2::reset_canvas() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
-void RasterizerCanvasGLES2::draw_generic_textured_rect(const Rect2 &dst_rect, const Rect2 &src_rect) {
-
- const int p_index_count = 6;
- const int p_vertex_count = 4;
-
- Vertex v[p_vertex_count];
- Color c(1, 1, 1, 1);
-
- // 0,0
- v[0].v = dst_rect.position;
- v[0].c = c;
- v[0].uv = src_rect.position;
-
- // 0,1
- v[1].v = Vector2(dst_rect.position.x, dst_rect.position.y + dst_rect.size.y);
- v[1].c = c;
- v[1].uv = Vector2(src_rect.position.x, src_rect.position.y + src_rect.size.y);
-
- // 1,1
- v[2].v = Vector2(dst_rect.position.x + dst_rect.size.x, dst_rect.position.y + dst_rect.size.y);
- v[2].c = c;
- v[2].uv = Vector2(src_rect.position.x + src_rect.size.x, src_rect.position.y + src_rect.size.y);
-
- // 1,0
- v[3].v = Vector2(dst_rect.position.x + dst_rect.size.x, dst_rect.position.y);
- v[3].c = c;
- v[3].uv = Vector2(src_rect.position.x + src_rect.size.x, src_rect.position.y);
+void RasterizerCanvasGLES2::_bind_quad_buffer() {
+ glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices);
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, NULL);
+}
+void RasterizerCanvasGLES2::draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src) {
- const int indices[p_index_count] = {
- 0, 1, 2,
- 2, 3, 0
- };
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y));
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(p_src.position.x, p_src.position.y, p_src.size.x, p_src.size.y));
- _draw(GL_TRIANGLES, p_vertex_count, v, p_index_count, indices);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void RasterizerCanvasGLES2::draw_window_margins(int *black_margin, RID *black_image) {
@@ -1123,36 +1053,60 @@ void RasterizerCanvasGLES2::draw_window_margins(int *black_margin, RID *black_im
void RasterizerCanvasGLES2::initialize() {
+ // quad buffer
+ {
+ glGenBuffers(1, &data.canvas_quad_vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices);
+
+ const float qv[8] = {
+ 0, 0,
+ 0, 1,
+ 1, 1,
+ 1, 0
+ };
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, qv, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
// polygon buffer
{
uint32_t poly_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128);
poly_size *= 1024;
poly_size = MAX(poly_size, (2 + 2 + 4) * 4 * sizeof(float));
- glGenBuffers(1, &data.vertex_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, data.vertex_buffer);
+ glGenBuffers(1, &data.polygon_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
glBufferData(GL_ARRAY_BUFFER, poly_size, NULL, GL_DYNAMIC_DRAW);
- data.vertex_buffer_size = poly_size;
+ data.polygon_buffer_size = poly_size;
glBindBuffer(GL_ARRAY_BUFFER, 0);
uint32_t index_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_index_size_kb", 128);
index_size *= 1024; // kb
- glGenBuffers(1, &data.index_buffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.index_buffer);
+ glGenBuffers(1, &data.polygon_index_buffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, NULL, GL_DYNAMIC_DRAW);
-
- data.index_buffer_size = index_size;
-
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
// ninepatch buffers
{
// array buffer
+ glGenBuffers(1, &data.ninepatch_vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices);
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (16 + 16) * 2, NULL, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ // element buffer
+ glGenBuffers(1, &data.ninepatch_elements);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements);
#define _EIDX(y, x) (y * 4 + x)
- const int elems[3 * 2 * 9] = {
+ uint8_t elems[3 * 2 * 9] = {
// first row
@@ -1196,25 +1150,15 @@ void RasterizerCanvasGLES2::initialize() {
;
#undef _EIDX
- memcpy(data.ninepatch_elements, elems, sizeof(elems));
- }
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elems), elems, GL_STATIC_DRAW);
- {
- const uint32_t size = data.vertex_buffer_size / sizeof(Vertex);
- data.mem_vertex_buffer = (Vertex *)memalloc(sizeof(Vertex) * size);
- data.mem_vertex_buffer_offset = 0;
- data.mem_vertex_buffer_size = size;
- }
-
- {
- const uint32_t size = data.index_buffer_size / sizeof(int);
- data.mem_index_buffer = (int *)memalloc(sizeof(int) * size);
- data.mem_index_buffer_offset = 0;
- data.mem_index_buffer_size = size;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
state.canvas_shader.init();
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
+
state.canvas_shader.bind();
}
@@ -1223,92 +1167,3 @@ void RasterizerCanvasGLES2::finalize() {
RasterizerCanvasGLES2::RasterizerCanvasGLES2() {
}
-
-void RasterizerCanvasGLES2::_begin(const GLuint p_primitive) {
- if (data.primitive != p_primitive) {
- _flush();
- data.primitive = p_primitive;
- }
-}
-
-void RasterizerCanvasGLES2::_prepare(const int p_vertex_count, const int p_index_count) {
- if (data.mem_vertex_buffer_size - data.mem_vertex_buffer_offset < p_vertex_count ||
- data.mem_index_buffer_size - data.mem_index_buffer_offset < p_index_count) {
- _flush();
- }
-}
-
-void RasterizerCanvasGLES2::_draw(const GLuint p_primitive, const int p_vertex_count, const Vertex *p_vertices, const int p_index_count, const int *p_indices) {
- glBindBuffer(GL_ARRAY_BUFFER, data.vertex_buffer);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * p_vertex_count, p_vertices);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.index_buffer);
- glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices);
-
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), NULL);
-
- glEnableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), ((uint8_t *)0) + sizeof(Vector2));
-
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), ((uint8_t *)0) + sizeof(Vector2) + sizeof(Color));
-
- glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-}
-
-void RasterizerCanvasGLES2::_flush() {
- if (data.mem_vertex_buffer_offset) {
- _draw(data.primitive, data.mem_vertex_buffer_offset, data.mem_vertex_buffer, data.mem_index_buffer_offset, data.mem_index_buffer);
- }
-
- data.mem_vertex_buffer_offset = 0;
- data.mem_index_buffer_offset = 0;
-}
-
-void RasterizerCanvasGLES2::_commit(const int p_vertex_count, const int p_index_count) {
- ERR_FAIL_COND(!p_vertex_count);
- ERR_FAIL_COND(!p_index_count);
-
- if (state.uniforms.extra_matrix != state.prev_uniforms.extra_matrix ||
- state.uniforms.final_modulate != state.prev_uniforms.final_modulate ||
- state.uniforms.modelview_matrix != state.prev_uniforms.modelview_matrix ||
- state.uniforms.projection_matrix != state.prev_uniforms.projection_matrix ||
- state.uniforms.texpixel_size != state.prev_uniforms.texpixel_size ||
- state.uniforms.time != state.prev_uniforms.time) {
-
- _set_uniforms();
- state.prev_uniforms = state.uniforms;
- _flush();
- }
-
- const int new_index_offset = data.mem_index_buffer_offset + p_index_count;
-
- for (int i = data.mem_index_buffer_offset; i < new_index_offset; ++i)
- data.mem_index_buffer[i] += data.mem_vertex_buffer_offset;
-
- data.mem_vertex_buffer_offset += p_vertex_count;
- data.mem_index_buffer_offset = new_index_offset;
-}
-
-void RasterizerCanvasGLES2::_untile() {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- state.tiled = false;
-}
-
-void RasterizerCanvasGLES2::_bind_shader(RasterizerStorageGLES2::Material *p_material) {
- if (!state.canvas_shader.is_dirty()) {
- return;
- }
-
- _flush();
-
- if (state.canvas_shader.bind()) {
- state.canvas_shader.use_material((void *)p_material);
- }
-}
diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h
index d5a122e533..cda3ec79e7 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.h
+++ b/drivers/gles2/rasterizer_canvas_gles2.h
@@ -50,44 +50,23 @@ public:
Color final_modulate;
float time;
-
- Size2 texpixel_size;
- };
-
- struct Vertex {
- Vector2 v;
- Color c;
- Vector2 uv;
};
struct Data {
- GLuint vertex_buffer;
- GLuint index_buffer;
-
- uint32_t vertex_buffer_size;
- uint32_t index_buffer_size;
-
- int ninepatch_elements[3 * 2 * 9];
+ GLuint canvas_quad_vertices;
+ GLuint polygon_buffer;
+ GLuint polygon_index_buffer;
- int *mem_index_buffer;
- uint32_t mem_index_buffer_offset;
- uint32_t mem_index_buffer_size;
+ uint32_t polygon_buffer_size;
- Vertex *mem_vertex_buffer;
- uint32_t mem_vertex_buffer_offset;
- uint32_t mem_vertex_buffer_size;
+ GLuint ninepatch_vertices;
+ GLuint ninepatch_elements;
- GLuint primitive;
- GLuint texture;
} data;
struct State {
Uniforms uniforms;
- Uniforms prev_uniforms;
-
- bool tiled;
-
bool canvas_texscreen_used;
CanvasShaderGLES2 canvas_shader;
// CanvasShadowShaderGLES3 canvas_shadow_shader;
@@ -120,16 +99,9 @@ public:
_FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false);
+ _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs);
_FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
-
- _FORCE_INLINE_ void _begin(const GLuint p_primitive);
- _FORCE_INLINE_ void _prepare(const int p_vertex_count, const int p_index_count);
- _FORCE_INLINE_ void _commit(const int p_vertex_count, const int p_index_count);
-
- _FORCE_INLINE_ void _flush();
- _FORCE_INLINE_ void _draw(const GLuint p_primitive, const int p_vertex_count, const Vertex *p_vertices, const int p_index_count, const int *p_indices);
-
- _FORCE_INLINE_ void _untile();
+ _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material);
_FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect);
@@ -142,8 +114,8 @@ public:
virtual void reset_canvas();
RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map);
- _FORCE_INLINE_ void _bind_shader(RasterizerStorageGLES2::Material *p_material);
+ void _bind_quad_buffer();
void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src);
void initialize();
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 165ffc0412..a1a0b9e2c6 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -345,6 +345,9 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
RasterizerStorageGLES2::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
+ canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
+ canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
+
canvas->state.canvas_shader.set_custom_shader(0);
canvas->state.canvas_shader.bind();
@@ -356,7 +359,7 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
// TODO normals
- canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 1, 1, -1));
+ canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 0, 1, -1));
glBindTexture(GL_TEXTURE_2D, 0);
canvas->canvas_end();
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 38c0ccaac2..c1fbf73254 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -252,7 +252,7 @@ public:
int mipmaps;
bool active;
- GLuint tex_id;
+ GLenum tex_id;
uint16_t stored_cube_sides;
@@ -429,8 +429,6 @@ public:
bool uses_screen_texture;
bool uses_screen_uv;
bool uses_time;
- bool uses_modelview_matrix;
- bool uses_vertex;
} canvas_item;
diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp
index 89c1b6490d..e9b58cb272 100644
--- a/drivers/gles2/shader_gles2.cpp
+++ b/drivers/gles2/shader_gles2.cpp
@@ -122,11 +122,13 @@ GLint ShaderGLES2::get_uniform_location(int p_index) const {
}
bool ShaderGLES2::bind() {
- if (!is_dirty())
- return false;
- conditional_version = new_conditional_version;
- version = get_current_version();
+ if (active != this || !version || new_conditional_version.key != conditional_version.key) {
+ conditional_version = new_conditional_version;
+ version = get_current_version();
+ } else {
+ return false;
+ }
ERR_FAIL_COND_V(!version, false);
@@ -1107,7 +1109,3 @@ ShaderGLES2::ShaderGLES2() {
ShaderGLES2::~ShaderGLES2() {
finish();
}
-
-bool ShaderGLES2::is_dirty() const {
- return active != this || !version || new_conditional_version.key != conditional_version.key;
-}
diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h
index 99513abfe9..cb515c199c 100644
--- a/drivers/gles2/shader_gles2.h
+++ b/drivers/gles2/shader_gles2.h
@@ -208,7 +208,6 @@ public:
GLint get_uniform_location(int p_index) const;
static _FORCE_INLINE_ ShaderGLES2 *get_active() { return active; }
- bool is_dirty() const;
bool bind();
void unbind();
void bind_uniforms();
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index a63c7675d8..29d81bb2c4 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -20,6 +20,13 @@ varying vec4 color_interp;
uniform highp vec2 color_texpixel_size;
+#ifdef USE_TEXTURE_RECT
+
+uniform vec4 dst_rect;
+uniform vec4 src_rect;
+
+#endif
+
uniform highp float time;
VERTEX_SHADER_GLOBALS
@@ -37,9 +44,35 @@ void main() {
vec4 color = color_attrib;
+#ifdef USE_TEXTURE_RECT
+
+ if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z
+ uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx;
+ } else {
+ uv_interp = src_rect.xy + abs(src_rect.zw) * vertex;
+ }
+
+ vec4 outvec = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // This is what is done in the GLES 3 bindings and should
+ // take care of flipped rects.
+ //
+ // But it doesn't.
+ // I don't know why, will need to investigate further.
+
+ outvec.xy = dst_rect.xy + abs(dst_rect.zw) * select(vertex, vec2(1.0, 1.0) - vertex, lessThan(src_rect.zw, vec2(0.0, 0.0)));
+
+ // outvec.xy = dst_rect.xy + abs(dst_rect.zw) * vertex;
+#else
vec4 outvec = vec4(vertex.xy, 0.0, 1.0);
+#ifdef USE_UV_ATTRIBUTE
uv_interp = uv_attrib;
+#else
+ uv_interp = vertex.xy;
+#endif
+
+#endif
{
vec2 src_vtx=outvec.xy;
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 60826aa81b..65c41ef579 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -1781,7 +1781,7 @@ void EditorHelp::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
+ class_desc->add_color_override("selection_color", EditorSettings::get_singleton()->get("text_editor/theme/selection_color"));
_update_doc();
} break;
@@ -1863,7 +1863,7 @@ EditorHelp::EditorHelp() {
class_desc = memnew(RichTextLabel);
add_child(class_desc);
class_desc->set_v_size_flags(SIZE_EXPAND_FILL);
- class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
+ class_desc->add_color_override("selection_color", EditorSettings::get_singleton()->get("text_editor/theme/selection_color"));
class_desc->connect("meta_clicked", this, "_class_desc_select");
class_desc->connect("gui_input", this, "_class_desc_input");
@@ -1929,7 +1929,7 @@ void EditorHelpBit::_notification(int p_what) {
switch (p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- rich_text->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
+ rich_text->add_color_override("selection_color", EditorSettings::get_singleton()->get("text_editor/theme/selection_color"));
} break;
default: break;
@@ -1948,7 +1948,7 @@ EditorHelpBit::EditorHelpBit() {
add_child(rich_text);
//rich_text->set_anchors_and_margins_preset(Control::PRESET_WIDE);
rich_text->connect("meta_clicked", this, "_meta_clicked");
- rich_text->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
+ rich_text->add_color_override("selection_color", EditorSettings::get_singleton()->get("text_editor/theme/selection_color"));
rich_text->set_override_selected_font_color(false);
set_custom_minimum_size(Size2(0, 70 * EDSCALE));
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index d673cc1b29..85186440ab 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -357,6 +357,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Adaptive,Default,Custom");
_initial_set("text_editor/theme/line_spacing", 4);
+ _initial_set("text_editor/theme/selection_color", Color::html("40808080"));
_load_default_text_editor_theme();
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index 2be1f1644e..ef7409fd43 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -37,10 +37,10 @@
#include "scene/gui/check_box.h"
#include "scene/gui/file_dialog.h"
#include "scene/gui/grid_container.h"
-#include "scene/gui/item_list.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/progress_bar.h"
+#include "scene/gui/tree.h"
#define ROOT_PREFIX "res://"
@@ -58,6 +58,34 @@ static bool is_text_char(CharType c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
+static bool find_next(const String &line, String pattern, int from, bool match_case, bool whole_words, int &out_begin, int &out_end) {
+
+ int end = from;
+
+ while (true) {
+ int begin = match_case ? line.find(pattern, end) : line.findn(pattern, end);
+
+ if (begin == -1)
+ return false;
+
+ end = begin + pattern.length();
+ out_begin = begin;
+ out_end = end;
+
+ if (whole_words) {
+ if (begin > 0 && is_text_char(line[begin - 1])) {
+ continue;
+ }
+ if (end < line.size() && is_text_char(line[end])) {
+ continue;
+ }
+ }
+
+ return true;
+ }
+}
+
+//--------------------------------------------------------------------------------
FindInFiles::FindInFiles() {
_root_prefix = ROOT_PREFIX;
_extension_filter.insert("gd");
@@ -246,24 +274,7 @@ void FindInFiles::_scan_file(String fpath) {
String line = f->get_line();
- // Find all occurrences in the current line
- while (true) {
- begin = _match_case ? line.find(_pattern, end) : line.findn(_pattern, end);
-
- if (begin == -1)
- break;
-
- end = begin + _pattern.length();
-
- if (_whole_words) {
- if (begin > 0 && is_text_char(line[begin - 1])) {
- continue;
- }
- if (end < line.size() && is_text_char(line[end])) {
- continue;
- }
- }
-
+ while (find_next(line, _pattern, end, _match_case, _whole_words, begin, end)) {
emit_signal(SIGNAL_RESULT_FOUND, fpath, line_number, begin, end, line);
}
}
@@ -567,14 +578,18 @@ FindInFilesPanel::FindInFilesPanel() {
vbc->add_child(hbc);
}
- // In the future, this should be replaced by a more specific list container,
- // which can highlight text regions and change opacity for enabled/disabled states
- _results_display = memnew(ItemList);
+ _results_display = memnew(Tree);
_results_display->add_font_override("font", get_font("source", "EditorFonts"));
_results_display->set_v_size_flags(SIZE_EXPAND_FILL);
_results_display->connect("item_selected", this, "_on_result_selected");
+ _results_display->connect("item_edited", this, "_on_item_edited");
+ _results_display->set_hide_root(true);
+ _results_display->set_select_mode(Tree::SELECT_ROW);
+ _results_display->create_item(); // Root
vbc->add_child(_results_display);
+ _with_replace = false;
+
{
_replace_container = memnew(HBoxContainer);
@@ -600,12 +615,33 @@ FindInFilesPanel::FindInFilesPanel() {
void FindInFilesPanel::set_with_replace(bool with_replace) {
+ _with_replace = with_replace;
_replace_container->set_visible(with_replace);
+
+ if (with_replace) {
+ // Results show checkboxes on their left so they can be opted out
+ _results_display->set_columns(2);
+ _results_display->set_column_expand(0, false);
+ _results_display->set_column_min_width(0, 48 * EDSCALE);
+
+ } else {
+ // Results are single-cell items
+ _results_display->set_column_expand(0, true);
+ _results_display->set_columns(1);
+ }
+}
+
+void FindInFilesPanel::clear() {
+ _file_items.clear();
+ _result_items.clear();
+ _results_display->clear();
+ _results_display->create_item(); // Root
}
void FindInFilesPanel::start_search() {
- _results_display->clear();
+ clear();
+
_status_label->set_text(TTR("Searching..."));
_search_text_label->set_text(_finder->get_search_text());
@@ -636,9 +672,90 @@ void FindInFilesPanel::_notification(int p_what) {
void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin, int end, String text) {
- int i = _results_display->get_item_count();
- _results_display->add_item(fpath + ": " + String::num(line_number) + ": " + text.replace("\t", " "));
- _results_display->set_item_metadata(i, varray(fpath, line_number, begin, end));
+ TreeItem *file_item;
+ Map<String, TreeItem *>::Element *E = _file_items.find(fpath);
+
+ if (E == NULL) {
+ file_item = _results_display->create_item();
+ file_item->set_text(0, fpath);
+ file_item->set_metadata(0, fpath);
+
+ // The width of this column is restrained to checkboxes, but that doesn't make sense for the parent items,
+ // so we override their width so they can expand to full width
+ file_item->set_expand_right(0, true);
+
+ _file_items[fpath] = file_item;
+
+ } else {
+ file_item = E->value();
+ }
+
+ int text_index = _with_replace ? 1 : 0;
+
+ TreeItem *item = _results_display->create_item(file_item);
+
+ // Do this first because it resets properties of the cell...
+ item->set_cell_mode(text_index, TreeItem::CELL_MODE_CUSTOM);
+
+ String item_text = String::num_int64(line_number) + ": " + text.replace("\t", " ");
+
+ item->set_text(text_index, item_text);
+ item->set_custom_draw(text_index, this, "_draw_result_text");
+
+ Ref<Font> font = _results_display->get_font("font");
+
+ float raw_text_width = font->get_string_size(text).x;
+ float item_text_width = font->get_string_size(item_text).x;
+
+ Result r;
+ r.line_number = line_number;
+ r.begin = begin;
+ r.end = end;
+ r.draw_begin = (item_text_width - raw_text_width) + font->get_string_size(text.left(r.begin)).x;
+ r.draw_width = font->get_string_size(text.substr(r.begin, r.end - r.begin + 1)).x;
+ _result_items[item] = r;
+
+ if (_with_replace) {
+ item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ item->set_checked(0, true);
+ item->set_editable(0, true);
+ }
+}
+
+void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) {
+
+ TreeItem *item = Object::cast_to<TreeItem>(item_obj);
+ if (!item)
+ return;
+
+ Map<TreeItem *, Result>::Element *E = _result_items.find(item);
+ if (!E)
+ return;
+ Result r = E->value();
+
+ Rect2 match_rect = rect;
+ match_rect.position.x += r.draw_begin;
+ match_rect.size.x = r.draw_width;
+ match_rect.position.y += 1 * EDSCALE;
+ match_rect.size.y -= 2 * EDSCALE;
+
+ _results_display->draw_rect(match_rect, Color(0, 0, 0, 0.5));
+ // Text is drawn by Tree already
+}
+
+void FindInFilesPanel::_on_item_edited() {
+
+ TreeItem *item = _results_display->get_selected();
+
+ if (item->is_checked(0)) {
+ item->set_custom_color(1, _results_display->get_color("font_color"));
+
+ } else {
+ // Grey out
+ Color color = _results_display->get_color("font_color");
+ color.a /= 2.0;
+ item->set_custom_color(1, color);
+ }
}
void FindInFilesPanel::_on_finished() {
@@ -653,10 +770,19 @@ void FindInFilesPanel::_on_cancel_button_clicked() {
stop_search();
}
-void FindInFilesPanel::_on_result_selected(int i) {
+void FindInFilesPanel::_on_result_selected() {
+
+ TreeItem *item = _results_display->get_selected();
+ Map<TreeItem *, Result>::Element *E = _result_items.find(item);
+
+ if (E == NULL)
+ return;
+ Result r = E->value();
+
+ TreeItem *file_item = item->get_parent();
+ String fpath = file_item->get_metadata(0);
- Array meta = _results_display->get_item_metadata(i);
- emit_signal(SIGNAL_RESULT_SELECTED, meta[0], meta[1], meta[2], meta[3]);
+ emit_signal(SIGNAL_RESULT_SELECTED, fpath, r.line_number, r.begin, r.end);
}
void FindInFilesPanel::_on_replace_text_changed(String text) {
@@ -668,39 +794,33 @@ void FindInFilesPanel::_on_replace_all_clicked() {
String replace_text = get_replace_text();
ERR_FAIL_COND(replace_text.empty());
- String last_fpath;
- PoolIntArray locations;
PoolStringArray modified_files;
- for (int i = 0; i < _results_display->get_item_count(); ++i) {
+ for (Map<String, TreeItem *>::Element *E = _file_items.front(); E; E = E->next()) {
- Array meta = _results_display->get_item_metadata(i);
+ TreeItem *file_item = E->value();
+ String fpath = file_item->get_metadata(0);
- String fpath = meta[0];
+ Vector<Result> locations;
+ for (TreeItem *item = file_item->get_children(); item; item = item->get_next()) {
- // Results are sorted by file, so we can batch replaces
- if (fpath != last_fpath) {
- if (locations.size() != 0) {
- apply_replaces_in_file(last_fpath, locations, replace_text);
- modified_files.append(last_fpath);
- locations.resize(0);
- }
- }
+ if (!item->is_checked(0))
+ continue;
- locations.append(meta[1]); // line_number
- locations.append(meta[2]); // begin
- locations.append(meta[3]); // end
-
- last_fpath = fpath;
- }
+ Map<TreeItem *, Result>::Element *E = _result_items.find(item);
+ ERR_FAIL_COND(E == NULL);
+ locations.push_back(E->value());
+ }
- if (locations.size() != 0) {
- apply_replaces_in_file(last_fpath, locations, replace_text);
- modified_files.append(last_fpath);
+ if (locations.size() != 0) {
+ // Results are sorted by file, so we can batch replaces
+ apply_replaces_in_file(fpath, locations, replace_text);
+ modified_files.append(fpath);
+ }
}
// Hide replace bar so we can't trigger the action twice without doing a new search
- set_with_replace(false);
+ _replace_container->hide();
emit_signal(SIGNAL_FILES_MODIFIED, modified_files);
}
@@ -740,11 +860,7 @@ private:
Vector<char> _line_buffer;
};
-void FindInFilesPanel::apply_replaces_in_file(String fpath, PoolIntArray locations, String text) {
-
- ERR_FAIL_COND(locations.size() % 3 != 0);
-
- //print_line(String("Replacing {0} occurrences in {1}").format(varray(fpath, locations.size() / 3)));
+void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result> &locations, String new_text) {
// If the file is already open, I assume the editor will reload it.
// If there are unsaved changes, the user will be asked on focus,
@@ -759,21 +875,34 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, PoolIntArray locatio
ConservativeGetLine conservative;
String line = conservative.get_line(f);
+ String search_text = _finder->get_search_text();
+
+ int offset = 0;
- PoolIntArray::Read locations_read = locations.read();
- for (int i = 0; i < locations.size(); i += 3) {
+ for (int i = 0; i < locations.size(); ++i) {
- int repl_line_number = locations_read[i];
- int repl_begin = locations_read[i + 1];
- int repl_end = locations_read[i + 2];
+ int repl_line_number = locations[i].line_number;
while (current_line < repl_line_number) {
buffer += line;
line = conservative.get_line(f);
++current_line;
+ offset = 0;
+ }
+
+ int repl_begin = locations[i].begin + offset;
+ int repl_end = locations[i].end + offset;
+
+ int _;
+ if (!find_next(line, search_text, repl_begin, _finder->is_match_case(), _finder->is_whole_words(), _, _)) {
+ // Make sure the replace is still valid in case the file was tampered with.
+ print_line(String("Occurrence no longer matches, replace will be ignored in {0}: line {1}, col {2}").format(varray(fpath, repl_line_number, repl_begin)));
+ continue;
}
- line = line.left(repl_begin) + text + line.right(repl_end);
+ line = line.left(repl_begin) + new_text + line.right(repl_end);
+ // keep an offset in case there are successive replaces in the same line
+ offset += new_text.length() - (repl_end - repl_begin);
}
buffer += line;
@@ -811,11 +940,13 @@ void FindInFilesPanel::set_progress_visible(bool visible) {
void FindInFilesPanel::_bind_methods() {
ClassDB::bind_method("_on_result_found", &FindInFilesPanel::_on_result_found);
+ ClassDB::bind_method("_on_item_edited", &FindInFilesPanel::_on_item_edited);
ClassDB::bind_method("_on_finished", &FindInFilesPanel::_on_finished);
ClassDB::bind_method("_on_cancel_button_clicked", &FindInFilesPanel::_on_cancel_button_clicked);
ClassDB::bind_method("_on_result_selected", &FindInFilesPanel::_on_result_selected);
ClassDB::bind_method("_on_replace_text_changed", &FindInFilesPanel::_on_replace_text_changed);
ClassDB::bind_method("_on_replace_all_clicked", &FindInFilesPanel::_on_replace_all_clicked);
+ ClassDB::bind_method("_draw_result_text", &FindInFilesPanel::draw_result_text);
ADD_SIGNAL(MethodInfo(SIGNAL_RESULT_SELECTED,
PropertyInfo(Variant::STRING, "path"),
diff --git a/editor/find_in_files.h b/editor/find_in_files.h
index d57184960b..75ea1c3161 100644
--- a/editor/find_in_files.h
+++ b/editor/find_in_files.h
@@ -131,7 +131,8 @@ private:
};
class Button;
-class ItemList;
+class Tree;
+class TreeItem;
class ProgressBar;
// Display search results
@@ -159,22 +160,37 @@ private:
void _on_result_found(String fpath, int line_number, int begin, int end, String text);
void _on_finished();
void _on_cancel_button_clicked();
- void _on_result_selected(int i);
+ void _on_result_selected();
+ void _on_item_edited();
void _on_replace_text_changed(String text);
void _on_replace_all_clicked();
- void apply_replaces_in_file(String fpath, PoolIntArray locations, String text);
+ struct Result {
+ int line_number;
+ int begin;
+ int end;
+ float draw_begin;
+ float draw_width;
+ };
+ void apply_replaces_in_file(String fpath, const Vector<Result> &locations, String new_text);
void update_replace_buttons();
String get_replace_text();
+
+ void draw_result_text(Object *item_obj, Rect2 rect);
+
void set_progress_visible(bool visible);
+ void clear();
FindInFiles *_finder;
Label *_search_text_label;
- ItemList *_results_display;
+ Tree *_results_display;
Label *_status_label;
Button *_cancel_button;
ProgressBar *_progress_bar;
+ Map<String, TreeItem *> _file_items;
+ Map<TreeItem *, Result> _result_items;
+ bool _with_replace;
HBoxContainer *_replace_container;
LineEdit *_replace_line_edit;
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
index 197550d686..815ad9c10f 100644
--- a/modules/bullet/godot_result_callbacks.cpp
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -51,8 +51,8 @@ bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) co
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
- if (m_pickRay && gObj->is_ray_pickable()) {
- return true;
+ if (m_pickRay && !gObj->is_ray_pickable()) {
+ return false;
} else if (m_exclude->has(gObj->get_self())) {
return false;
}
diff --git a/modules/mono/config.py b/modules/mono/config.py
index c4f8dcfde8..70fd1a35f1 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -265,11 +265,13 @@ def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext):
def pkgconfig_try_find_mono_version():
+ from compat import decode_utf8
+
lines = subprocess.check_output(['pkg-config', 'monosgen-2', '--modversion']).splitlines()
greater_version = None
for line in lines:
try:
- version = LooseVersion(line)
+ version = LooseVersion(decode_utf8(line))
if greater_version is None or version > greater_version:
greater_version = version
except ValueError:
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 875b72159a..143a1438ea 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -34,6 +34,8 @@
void Material::set_next_pass(const Ref<Material> &p_pass) {
+ ERR_FAIL_COND(p_pass == this);
+
if (next_pass == p_pass)
return;