Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/overlay/overlay_edit_uv.c')
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_uv.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c
new file mode 100644
index 00000000000..109db6433e0
--- /dev/null
+++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c
@@ -0,0 +1,394 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2019, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+#include "DRW_render.h"
+
+#include "draw_cache_impl.h"
+#include "draw_manager_text.h"
+
+#include "BKE_image.h"
+
+#include "DNA_mesh_types.h"
+
+#include "ED_image.h"
+
+#include "GPU_batch.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "overlay_private.h"
+
+typedef struct OVERLAY_StretchingAreaTotals {
+ void *next, *prev;
+ float *total_area;
+ float *total_area_uv;
+} OVERLAY_StretchingAreaTotals;
+
+static OVERLAY_UVLineStyle edit_uv_line_style_from_space_image(const SpaceImage *sima)
+{
+ const bool is_uv_editor = sima->mode == SI_MODE_UV;
+ if (is_uv_editor) {
+ switch (sima->dt_uv) {
+ case SI_UVDT_OUTLINE:
+ return OVERLAY_UV_LINE_STYLE_OUTLINE;
+ case SI_UVDT_BLACK:
+ return OVERLAY_UV_LINE_STYLE_BLACK;
+ case SI_UVDT_WHITE:
+ return OVERLAY_UV_LINE_STYLE_WHITE;
+ case SI_UVDT_DASH:
+ return OVERLAY_UV_LINE_STYLE_DASH;
+ default:
+ return OVERLAY_UV_LINE_STYLE_BLACK;
+ }
+ }
+ else {
+ return OVERLAY_UV_LINE_STYLE_SHADOW;
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Internal API
+ * \{ */
+
+void OVERLAY_edit_uv_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
+ const Scene *scene = draw_ctx->scene;
+ const ToolSettings *ts = scene->toolsettings;
+
+ Image *image = sima->image;
+ /* By design no image is an image type. This so editor shows UV's by default. */
+ const bool is_image_type =
+ (image == NULL) || ELEM(image->type, IMA_TYPE_IMAGE, IMA_TYPE_MULTILAYER, IMA_TYPE_UV_TEST);
+ const bool is_uv_editor = sima->mode == SI_MODE_UV;
+ const bool has_edit_object = (draw_ctx->object_edit) != NULL;
+ const bool is_paint_mode = sima->mode == SI_MODE_PAINT;
+ const bool is_view_mode = sima->mode == SI_MODE_VIEW;
+ const bool is_edit_mode = draw_ctx->object_mode == OB_MODE_EDIT;
+ const bool do_uv_overlay = is_image_type && is_uv_editor && has_edit_object;
+ const bool show_modified_uvs = sima->flag & SI_DRAWSHADOW;
+ const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
+ const bool do_faces = ((sima->flag & SI_NO_DRAWFACES) == 0);
+ const bool do_face_dots = (ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode & SCE_SELECT_FACE) != 0 :
+ (ts->uv_selectmode == UV_SELECT_FACE);
+ const bool do_uvstretching_overlay = is_image_type && is_uv_editor && is_edit_mode &&
+ ((sima->flag & SI_DRAW_STRETCH) != 0);
+ pd->edit_uv.do_faces = do_faces && !do_uvstretching_overlay;
+ pd->edit_uv.do_face_dots = do_faces && do_face_dots;
+
+ pd->edit_uv.do_uv_overlay = do_uv_overlay;
+ pd->edit_uv.do_uv_shadow_overlay =
+ is_image_type &&
+ ((is_paint_mode &&
+ ((draw_ctx->object_mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_EDIT)) != 0)) ||
+ (is_view_mode && ((draw_ctx->object_mode & (OB_MODE_TEXTURE_PAINT)) != 0)) ||
+ (do_uv_overlay && (show_modified_uvs)));
+ pd->edit_uv.do_uv_stretching_overlay = do_uvstretching_overlay;
+ pd->edit_uv.uv_opacity = sima->uv_opacity;
+ pd->edit_uv.do_tiled_image_overlay = is_image_type && is_tiled_image;
+
+ pd->edit_uv.dash_length = 4.0f * UI_DPI_FAC;
+ pd->edit_uv.line_style = edit_uv_line_style_from_space_image(sima);
+ pd->edit_uv.do_smooth_wire = ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) > 0);
+
+ pd->edit_uv.draw_type = sima->dt_uvstretch;
+ BLI_listbase_clear(&pd->edit_uv.totals);
+ pd->edit_uv.total_area_ratio = 0.0f;
+ pd->edit_uv.total_area_ratio_inv = 0.0f;
+
+ ED_space_image_get_uv_aspect(sima, &pd->edit_uv.aspect[0], &pd->edit_uv.aspect[1]);
+}
+
+void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = stl->pd;
+
+ if (pd->edit_uv.do_uv_overlay || pd->edit_uv.do_uv_shadow_overlay) {
+ /* uv edges */
+ {
+ DRW_PASS_CREATE(psl->edit_uv_edges_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
+ DRW_STATE_BLEND_ALPHA);
+ GPUShader *sh = OVERLAY_shader_edit_uv_edges_get();
+ if (pd->edit_uv.do_uv_shadow_overlay) {
+ pd->edit_uv_shadow_edges_grp = DRW_shgroup_create(sh, psl->edit_uv_edges_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_shadow_edges_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_int_copy(
+ pd->edit_uv_shadow_edges_grp, "lineStyle", OVERLAY_UV_LINE_STYLE_SHADOW);
+ DRW_shgroup_uniform_float_copy(
+ pd->edit_uv_shadow_edges_grp, "alpha", pd->edit_uv.uv_opacity);
+ DRW_shgroup_uniform_float(
+ pd->edit_uv_shadow_edges_grp, "dashLength", &pd->edit_uv.dash_length, 1);
+ DRW_shgroup_uniform_bool(
+ pd->edit_uv_shadow_edges_grp, "doSmoothWire", &pd->edit_uv.do_smooth_wire, 1);
+ }
+
+ if (pd->edit_uv.do_uv_overlay) {
+ pd->edit_uv_edges_grp = DRW_shgroup_create(sh, psl->edit_uv_edges_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_edges_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_int_copy(pd->edit_uv_edges_grp, "lineStyle", pd->edit_uv.line_style);
+ DRW_shgroup_uniform_float_copy(pd->edit_uv_edges_grp, "alpha", pd->edit_uv.uv_opacity);
+ DRW_shgroup_uniform_float(
+ pd->edit_uv_edges_grp, "dashLength", &pd->edit_uv.dash_length, 1);
+ DRW_shgroup_uniform_bool(
+ pd->edit_uv_edges_grp, "doSmoothWire", &pd->edit_uv.do_smooth_wire, 1);
+ }
+ }
+ }
+
+ if (pd->edit_uv.do_uv_overlay) {
+ /* uv verts */
+ {
+ DRW_PASS_CREATE(psl->edit_uv_verts_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
+ DRW_STATE_BLEND_ALPHA);
+ GPUShader *sh = OVERLAY_shader_edit_uv_verts_get();
+ pd->edit_uv_verts_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps);
+
+ const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+
+ DRW_shgroup_uniform_block(pd->edit_uv_verts_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float_copy(
+ pd->edit_uv_verts_grp, "pointSize", (point_size + 1.5f) * M_SQRT2);
+ DRW_shgroup_uniform_float_copy(pd->edit_uv_verts_grp, "outlineWidth", 0.75f);
+ }
+
+ /* uv faces */
+ if (pd->edit_uv.do_faces) {
+ DRW_PASS_CREATE(psl->edit_uv_faces_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA);
+ GPUShader *sh = OVERLAY_shader_edit_uv_face_get();
+ pd->edit_uv_faces_grp = DRW_shgroup_create(sh, psl->edit_uv_faces_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_faces_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float(pd->edit_uv_faces_grp, "uvOpacity", &pd->edit_uv.uv_opacity, 1);
+ }
+
+ /* uv face dots */
+ if (pd->edit_uv.do_face_dots) {
+ const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+ GPUShader *sh = OVERLAY_shader_edit_uv_face_dots_get();
+ pd->edit_uv_face_dots_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_face_dots_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float_copy(pd->edit_uv_face_dots_grp, "pointSize", point_size);
+ }
+ }
+
+ /* uv stretching */
+ if (pd->edit_uv.do_uv_stretching_overlay) {
+ DRW_PASS_CREATE(psl->edit_uv_stretching_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA);
+ if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) {
+ GPUShader *sh = OVERLAY_shader_edit_uv_stretching_angle_get();
+ pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_vec2_copy(pd->edit_uv_stretching_grp, "aspect", pd->edit_uv.aspect);
+ }
+ else /* SI_UVDT_STRETCH_AREA */ {
+ GPUShader *sh = OVERLAY_shader_edit_uv_stretching_area_get();
+ pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps);
+ DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float(
+ pd->edit_uv_stretching_grp, "totalAreaRatio", &pd->edit_uv.total_area_ratio, 1);
+ DRW_shgroup_uniform_float(
+ pd->edit_uv_stretching_grp, "totalAreaRatioInv", &pd->edit_uv.total_area_ratio_inv, 1);
+ }
+ }
+
+ if (pd->edit_uv.do_tiled_image_overlay) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
+ Image *image = sima->image;
+ GPUBatch *geom = DRW_cache_quad_wires_get();
+ float obmat[4][4];
+ unit_m4(obmat);
+
+ DRW_PASS_CREATE(psl->edit_uv_tiled_image_borders_ps,
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS);
+ GPUShader *sh = OVERLAY_shader_edit_uv_tiled_image_borders_get();
+
+ float theme_color[4], selected_color[4];
+ UI_GetThemeColorShade4fv(TH_BACK, 60, theme_color);
+ UI_GetThemeColor4fv(TH_FACE_SELECT, selected_color);
+ srgb_to_linearrgb_v4(theme_color, theme_color);
+ srgb_to_linearrgb_v4(selected_color, selected_color);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->edit_uv_tiled_image_borders_ps);
+ DRW_shgroup_uniform_vec4_copy(grp, "color", theme_color);
+ DRW_shgroup_uniform_vec3_copy(grp, "offset", (float[3]){0.0f, 0.0f, 0.0f});
+
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ const int tile_x = ((tile->tile_number - 1001) % 10);
+ const int tile_y = ((tile->tile_number - 1001) / 10);
+ obmat[3][1] = (float)tile_y;
+ obmat[3][0] = (float)tile_x;
+ DRW_shgroup_call_obmat(grp, geom, obmat);
+ }
+
+ /* Active tile border */
+ ImageTile *active_tile = BLI_findlink(&image->tiles, image->active_tile_index);
+ obmat[3][0] = (float)((active_tile->tile_number - 1001) % 10);
+ obmat[3][1] = (float)((active_tile->tile_number - 1001) / 10);
+ grp = DRW_shgroup_create(sh, psl->edit_uv_tiled_image_borders_ps);
+ DRW_shgroup_uniform_vec4_copy(grp, "color", selected_color);
+ DRW_shgroup_call_obmat(grp, geom, obmat);
+
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ uchar color[4];
+ /* Color Management: Exception here as texts are drawn in sRGB space directly. */
+ UI_GetThemeColorShade4ubv(TH_BACK, 60, color);
+ char text[16];
+ LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+ BLI_snprintf(text, 5, "%d", tile->tile_number);
+ float tile_location[3] = {
+ ((tile->tile_number - 1001) % 10), ((tile->tile_number - 1001) / 10), 0.0f};
+ DRW_text_cache_add(dt,
+ tile_location,
+ text,
+ strlen(text),
+ 10,
+ 10,
+ DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII,
+ color);
+ }
+ }
+}
+
+void OVERLAY_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob)
+{
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+ GPUBatch *geom;
+ const bool is_edit_object = DRW_object_is_in_edit_mode(ob);
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const bool draw_shadows = (draw_ctx->object_mode != OB_MODE_OBJECT) &&
+ (ob->mode == draw_ctx->object_mode);
+ if (is_edit_object) {
+ if (pd->edit_uv.do_uv_overlay) {
+ geom = DRW_mesh_batch_cache_get_edituv_edges(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_edges_grp, geom, NULL);
+ }
+ geom = DRW_mesh_batch_cache_get_edituv_verts(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_verts_grp, geom, NULL);
+ }
+ if (pd->edit_uv.do_faces) {
+ geom = DRW_mesh_batch_cache_get_edituv_faces(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_faces_grp, geom, NULL);
+ }
+ }
+ if (pd->edit_uv.do_face_dots) {
+ geom = DRW_mesh_batch_cache_get_edituv_facedots(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_face_dots_grp, geom, NULL);
+ }
+ }
+ }
+
+ if (pd->edit_uv.do_uv_stretching_overlay) {
+ Mesh *me = ob->data;
+
+ if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) {
+ geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(me);
+ }
+ else /* SI_UVDT_STRETCH_AREA */ {
+ OVERLAY_StretchingAreaTotals *totals = MEM_mallocN(sizeof(OVERLAY_StretchingAreaTotals),
+ __func__);
+ BLI_addtail(&pd->edit_uv.totals, totals);
+ geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_area(
+ me, &totals->total_area, &totals->total_area_uv);
+ }
+
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_stretching_grp, geom, NULL);
+ }
+ }
+ }
+
+ if (draw_shadows) {
+ if (pd->edit_uv.do_uv_shadow_overlay) {
+ geom = DRW_mesh_batch_cache_get_uv_edges(ob->data);
+ if (geom) {
+ DRW_shgroup_call_obmat(pd->edit_uv_shadow_edges_grp, geom, NULL);
+ }
+ }
+ }
+}
+
+static void edit_uv_stretching_update_ratios(OVERLAY_Data *vedata)
+{
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+
+ if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_AREA) {
+ float total_area = 0.0f;
+ float total_area_uv = 0.0f;
+
+ LISTBASE_FOREACH (OVERLAY_StretchingAreaTotals *, totals, &pd->edit_uv.totals) {
+ total_area += *totals->total_area;
+ total_area_uv += *totals->total_area_uv;
+ }
+
+ if (total_area > FLT_EPSILON && total_area_uv > FLT_EPSILON) {
+ pd->edit_uv.total_area_ratio = total_area / total_area_uv;
+ pd->edit_uv.total_area_ratio_inv = total_area_uv / total_area;
+ }
+ }
+ BLI_freelistN(&pd->edit_uv.totals);
+}
+
+void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_StorageList *stl = vedata->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+
+ if (pd->edit_uv.do_tiled_image_overlay) {
+ DRW_draw_pass(psl->edit_uv_tiled_image_borders_ps);
+ }
+
+ if (pd->edit_uv.do_uv_stretching_overlay) {
+ edit_uv_stretching_update_ratios(vedata);
+ DRW_draw_pass(psl->edit_uv_stretching_ps);
+ }
+ if (pd->edit_uv.do_uv_overlay) {
+ if (pd->edit_uv.do_faces) {
+ DRW_draw_pass(psl->edit_uv_faces_ps);
+ }
+ DRW_draw_pass(psl->edit_uv_edges_ps);
+
+ DRW_draw_pass(psl->edit_uv_verts_ps);
+ }
+ else if (pd->edit_uv.do_uv_shadow_overlay) {
+ DRW_draw_pass(psl->edit_uv_edges_ps);
+ }
+}
+
+/* \{ */