diff options
-rw-r--r-- | core/math/quick_hull.cpp | 11 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_canvas_gles2.cpp | 947 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_canvas_gles2.h | 46 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 5 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.h | 4 | ||||
-rw-r--r-- | drivers/gles2/shader_gles2.cpp | 14 | ||||
-rw-r--r-- | drivers/gles2/shader_gles2.h | 1 | ||||
-rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 33 | ||||
-rw-r--r-- | editor/editor_help.cpp | 8 | ||||
-rw-r--r-- | editor/editor_settings.cpp | 1 | ||||
-rw-r--r-- | editor/find_in_files.cpp | 257 | ||||
-rw-r--r-- | editor/find_in_files.h | 24 | ||||
-rw-r--r-- | modules/bullet/godot_result_callbacks.cpp | 4 | ||||
-rw-r--r-- | modules/mono/config.py | 4 | ||||
-rw-r--r-- | scene/resources/material.cpp | 2 |
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; |