fa2a7eb981221bdfcacdc45d4f562f4b50f52a20
[blender.git] / source / blender / editors / uvedit / uvedit_draw.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup eduv
22  */
23
24 #include <float.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "DNA_material_types.h"
32 #include "DNA_mesh_types.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36 #include "DNA_screen_types.h"
37 #include "DNA_space_types.h"
38
39 #include "../../draw/intern/draw_cache_impl.h"
40
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43
44 #include "BKE_deform.h"
45 #include "BKE_editmesh.h"
46 #include "BKE_material.h"
47 #include "BKE_layer.h"
48
49 #include "BKE_scene.h"
50
51 #include "DEG_depsgraph.h"
52 #include "DEG_depsgraph_query.h"
53
54 #include "GPU_batch.h"
55 #include "GPU_framebuffer.h"
56 #include "GPU_immediate.h"
57 #include "GPU_immediate_util.h"
58 #include "GPU_matrix.h"
59 #include "GPU_state.h"
60 #include "GPU_draw.h"
61
62 #include "ED_image.h"
63 #include "ED_mesh.h"
64 #include "ED_uvedit.h"
65
66 #include "UI_resources.h"
67 #include "UI_interface.h"
68 #include "UI_view2d.h"
69
70 #include "uvedit_intern.h"
71
72 static int draw_uvs_face_check(const ToolSettings *ts)
73 {
74   /* checks if we are selecting only faces */
75   if (ts->uv_flag & UV_SYNC_SELECTION) {
76     if (ts->selectmode == SCE_SELECT_FACE) {
77       return 2;
78     }
79     else if (ts->selectmode & SCE_SELECT_FACE) {
80       return 1;
81     }
82     else {
83       return 0;
84     }
85   }
86   else {
87     return (ts->uv_selectmode == UV_SELECT_FACE);
88   }
89 }
90
91 /* ------------------------- */
92
93 void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
94 {
95   float zoom[2], x_fac, y_fac;
96
97   UI_view2d_scale_get_inverse(&ar->v2d, &zoom[0], &zoom[1]);
98
99   mul_v2_fl(zoom, 256.0f * UI_DPI_FAC);
100   x_fac = zoom[0];
101   y_fac = zoom[1];
102
103   GPU_line_width(1.0f);
104
105   GPU_matrix_translate_2fv(cursor);
106
107   const uint shdr_pos = GPU_vertformat_attr_add(
108       immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
109
110   immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
111
112   float viewport_size[4];
113   GPU_viewport_size_get_f(viewport_size);
114   immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
115
116   immUniform1i("colors_len", 2); /* "advanced" mode */
117   immUniformArray4fv(
118       "colors", (float *)(float[][4]){{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
119   immUniform1f("dash_width", 8.0f);
120
121   immBegin(GPU_PRIM_LINES, 8);
122
123   immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
124   immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
125
126   immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
127   immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
128
129   immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
130   immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
131
132   immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
133   immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
134
135   immEnd();
136
137   immUniformArray4fv(
138       "colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
139   immUniform1f("dash_width", 2.0f);
140
141   immBegin(GPU_PRIM_LINES, 8);
142
143   immVertex2f(shdr_pos, -0.020f * x_fac, 0.0f);
144   immVertex2f(shdr_pos, -0.1f * x_fac, 0.0f);
145
146   immVertex2f(shdr_pos, 0.1f * x_fac, 0.0f);
147   immVertex2f(shdr_pos, 0.020f * x_fac, 0.0f);
148
149   immVertex2f(shdr_pos, 0.0f, -0.020f * y_fac);
150   immVertex2f(shdr_pos, 0.0f, -0.1f * y_fac);
151
152   immVertex2f(shdr_pos, 0.0f, 0.1f * y_fac);
153   immVertex2f(shdr_pos, 0.0f, 0.020f * y_fac);
154
155   immEnd();
156
157   immUnbindProgram();
158
159   GPU_matrix_translate_2f(-cursor[0], -cursor[1]);
160 }
161
162 static void uvedit_get_batches(Object *ob,
163                                SpaceImage *sima,
164                                const ToolSettings *ts,
165                                GPUBatch **faces,
166                                GPUBatch **edges,
167                                GPUBatch **verts,
168                                GPUBatch **facedots)
169 {
170   int drawfaces = draw_uvs_face_check(ts);
171   const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
172   const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0;
173
174   DRW_mesh_batch_cache_validate(ob->data);
175   *edges = DRW_mesh_batch_cache_get_edituv_edges(ob->data);
176   *verts = DRW_mesh_batch_cache_get_edituv_verts(ob->data);
177
178   if (drawfaces) {
179     *facedots = DRW_mesh_batch_cache_get_edituv_facedots(ob->data);
180   }
181   else {
182     *facedots = NULL;
183   }
184
185   if (draw_stretch && (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)) {
186     *faces = DRW_mesh_batch_cache_get_edituv_faces_strech_area(ob->data);
187   }
188   else if (draw_stretch) {
189     *faces = DRW_mesh_batch_cache_get_edituv_faces_strech_angle(ob->data);
190   }
191   else if (draw_faces) {
192     *faces = DRW_mesh_batch_cache_get_edituv_faces(ob->data);
193   }
194   else {
195     *faces = NULL;
196   }
197
198   DRW_mesh_batch_cache_create_requested(ob, ob->data, ts, false, false);
199 }
200
201 static void draw_uvs_shadow(SpaceImage *UNUSED(sima),
202                             Scene *scene,
203                             Object *obedit,
204                             Depsgraph *depsgraph)
205 {
206   Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
207   Mesh *me = eval_ob->data;
208   float col[4];
209   UI_GetThemeColor4fv(TH_UV_SHADOW, col);
210
211   DRW_mesh_batch_cache_validate(me);
212   GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
213   DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
214
215   if (edges) {
216     GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UV_UNIFORM_COLOR);
217     GPU_batch_uniform_4fv(edges, "color", col);
218     GPU_batch_draw(edges);
219   }
220 }
221
222 static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
223 {
224   Object *eval_ob = DEG_get_evaluated_object(depsgraph, ob);
225   Mesh *me = eval_ob->data;
226   ToolSettings *ts = scene->toolsettings;
227   float col[4];
228   UI_GetThemeColor4fv(TH_UV_SHADOW, col);
229
230   if (me->mloopuv == NULL) {
231     return;
232   }
233
234   DRW_mesh_batch_cache_validate(me);
235   GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
236   DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
237
238   GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR);
239   GPU_batch_uniform_4fv(geom, "color", col);
240
241   const bool do_material_masking = (ts->uv_flag & UV_SHOW_SAME_IMAGE);
242   if (do_material_masking && me->mloopuv) {
243     /* Render loops that have the active material. Minize draw calls. */
244     MPoly *mpoly = me->mpoly;
245     uint draw_start = 0;
246     uint idx = 0;
247     bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
248
249     GPU_matrix_bind(geom->interface);
250     GPU_batch_bind(geom);
251
252     /* TODO(fclem): If drawcall count becomes a problem in the future
253      * we can use multi draw indirect drawcalls for this.
254      * (not implemented in GPU module at the time of writing). */
255     for (int a = 0; a < me->totpoly; a++, mpoly++) {
256       bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
257       if (ma_match != prev_ma_match) {
258         if (ma_match == false) {
259           GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0);
260         }
261         else {
262           draw_start = idx;
263         }
264       }
265       idx += mpoly->totloop + 1;
266       prev_ma_match = ma_match;
267     }
268     if (prev_ma_match == true) {
269       GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0);
270     }
271
272     GPU_batch_program_use_end(geom);
273   }
274   else {
275     GPU_batch_draw(geom);
276   }
277 }
278
279 /* draws uv's in the image space */
280 static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *depsgraph)
281 {
282   GPUBatch *faces, *edges, *verts, *facedots;
283   Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
284   const ToolSettings *ts = scene->toolsettings;
285   float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f};
286
287   if (sima->flag & SI_DRAWSHADOW) {
288     bool is_cage_like_final_meshes = false;
289     Mesh *me = (Mesh *)eval_ob->data;
290     BMEditMesh *embm = me->edit_mesh;
291     is_cage_like_final_meshes = embm && embm->mesh_eval_final &&
292                                 embm->mesh_eval_final->runtime.is_original;
293
294     /* When sync selection is enabled, all faces are drawn (except for hidden)
295      * so if cage is the same as the final, there is no point in drawing this. */
296     if (!((ts->uv_flag & UV_SYNC_SELECTION) && is_cage_like_final_meshes)) {
297       draw_uvs_shadow(sima, scene, obedit, depsgraph);
298     }
299   }
300
301   uvedit_get_batches(eval_ob, sima, ts, &faces, &edges, &verts, &facedots);
302
303   bool interpedges;
304   bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
305   if (ts->uv_flag & UV_SYNC_SELECTION) {
306     interpedges = (ts->selectmode & SCE_SELECT_VERTEX) != 0;
307   }
308   else {
309     interpedges = (ts->uv_selectmode == UV_SELECT_VERTEX);
310   }
311
312   GPU_blend_set_func_separate(
313       GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
314
315   if (faces) {
316     GPU_batch_program_set_builtin(faces,
317                                   (draw_stretch) ? (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA) ?
318                                                    GPU_SHADER_2D_UV_FACES_STRETCH_AREA :
319                                                    GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE :
320                                                    GPU_SHADER_2D_UV_FACES);
321
322     if (!draw_stretch) {
323       GPU_blend(true);
324
325       UI_GetThemeColor4fv(TH_FACE, col1);
326       UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
327       UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3);
328       col3[3] *= 0.2; /* Simulate dithering */
329       GPU_batch_uniform_4fv(faces, "faceColor", col1);
330       GPU_batch_uniform_4fv(faces, "selectColor", col2);
331       GPU_batch_uniform_4fv(faces, "activeColor", col3);
332     }
333     else if (sima->dt_uvstretch == SI_UVDT_STRETCH_ANGLE) {
334       float asp[2];
335       ED_space_image_get_uv_aspect(sima, &asp[0], &asp[1]);
336       GPU_batch_uniform_2fv(faces, "aspect", asp);
337     }
338
339     GPU_batch_draw(faces);
340
341     if (!draw_stretch) {
342       GPU_blend(false);
343     }
344   }
345   if (edges) {
346     if (sima->flag & SI_SMOOTH_UV) {
347       GPU_line_smooth(true);
348       GPU_blend(true);
349     }
350     switch (sima->dt_uv) {
351       case SI_UVDT_DASH: {
352         float dash_colors[2][4] = {{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}};
353         float viewport_size[4];
354         GPU_viewport_size_get_f(viewport_size);
355
356         GPU_line_width(1.0f);
357         GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
358         GPU_batch_uniform_4fv_array(edges, "colors", 2, (float *)dash_colors);
359         GPU_batch_uniform_2f(
360             edges, "viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
361         GPU_batch_uniform_1i(edges, "colors_len", 2); /* "advanced" mode */
362         GPU_batch_uniform_1f(edges, "dash_width", 4.0f);
363         GPU_batch_draw(edges);
364         break;
365       }
366       case SI_UVDT_BLACK:
367       case SI_UVDT_WHITE: {
368         GPU_line_width(1.0f);
369         GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR);
370         if (sima->dt_uv == SI_UVDT_WHITE) {
371           GPU_batch_uniform_4f(edges, "color", 1.0f, 1.0f, 1.0f, 1.0f);
372         }
373         else {
374           GPU_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
375         }
376         GPU_batch_draw(edges);
377         break;
378       }
379       case SI_UVDT_OUTLINE: {
380         /* We could modify the vbo's data filling
381          * instead of modifying the provoking vert. */
382         glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
383
384         UI_GetThemeColor4fv(TH_WIRE_EDIT, col1);
385         UI_GetThemeColor4fv(TH_EDGE_SELECT, col2);
386
387         GPU_batch_program_set_builtin(
388             edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES);
389         /* Black Outline. */
390         GPU_line_width(3.0f);
391         GPU_batch_uniform_4f(edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f);
392         GPU_batch_uniform_4f(edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f);
393         GPU_batch_draw(edges);
394         /* Inner Line. Use depth test to insure selection is drawn on top. */
395         GPU_depth_test(true);
396         GPU_line_width(1.0f);
397         GPU_batch_uniform_4fv(edges, "edgeColor", col1);
398         GPU_batch_uniform_4fv(edges, "selectColor", col2);
399         GPU_batch_draw(edges);
400         GPU_depth_test(false);
401
402         glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
403         break;
404       }
405     }
406     if (sima->flag & SI_SMOOTH_UV) {
407       GPU_line_smooth(false);
408       GPU_blend(false);
409     }
410   }
411   if (verts || facedots) {
412     float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
413     UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2);
414     if (verts) {
415       float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */
416       UI_GetThemeColor4fv(TH_VERTEX, col1);
417       GPU_blend(true);
418       GPU_program_point_size(true);
419
420       GPU_batch_program_set_builtin(verts, GPU_SHADER_2D_UV_VERTS);
421       GPU_batch_uniform_4f(verts, "vertColor", col1[0], col1[1], col1[2], 1.0f);
422       GPU_batch_uniform_4fv(verts, "selectColor", transparent);
423       GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col);
424       GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
425       GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
426       GPU_batch_draw(verts);
427
428       /* We have problem in this mode when face order make some verts
429        * appear unselected because an adjacent face is not selected and
430        * render after the selected face.
431        * So, to avoid sorting verts by state we just render selected verts
432        * on top. A bit overkill but it's simple. */
433       GPU_batch_uniform_4fv(verts, "vertColor", transparent);
434       GPU_batch_uniform_4fv(verts, "selectColor", col2);
435       GPU_batch_draw(verts);
436
437       GPU_blend(false);
438       GPU_program_point_size(false);
439     }
440     if (facedots) {
441       GPU_point_size(pointsize);
442
443       UI_GetThemeColor4fv(TH_WIRE, col1);
444       GPU_batch_program_set_builtin(facedots, GPU_SHADER_2D_UV_FACEDOTS);
445       GPU_batch_uniform_4fv(facedots, "vertColor", col1);
446       GPU_batch_uniform_4fv(facedots, "selectColor", col2);
447       GPU_batch_draw(facedots);
448     }
449   }
450 }
451
452 static void draw_uv_shadows_get(
453     SpaceImage *sima, Object *ob, Object *obedit, bool *show_shadow, bool *show_texpaint)
454 {
455   *show_shadow = *show_texpaint = false;
456
457   if (ED_space_image_show_render(sima) || (sima->flag & SI_NO_DRAW_TEXPAINT)) {
458     return;
459   }
460
461   if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) {
462     struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
463
464     *show_shadow = EDBM_uv_check(em);
465   }
466
467   *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
468 }
469
470 void ED_uvedit_draw_main(SpaceImage *sima,
471                          Scene *scene,
472                          ViewLayer *view_layer,
473                          Object *obedit,
474                          Object *obact,
475                          Depsgraph *depsgraph)
476 {
477   bool show_uvedit, show_uvshadow, show_texpaint_uvshadow;
478
479   show_uvedit = ED_space_image_show_uvedit(sima, obedit);
480   draw_uv_shadows_get(sima, obact, obedit, &show_uvshadow, &show_texpaint_uvshadow);
481
482   if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) {
483     if (show_uvshadow) {
484       draw_uvs_shadow(sima, scene, obedit, depsgraph);
485     }
486     else if (show_uvedit) {
487       uint objects_len = 0;
488       Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
489           view_layer, ((View3D *)NULL), &objects_len);
490       if (objects_len > 0) {
491         GPU_clear_depth(1.0f);
492         GPU_clear(GPU_DEPTH_BIT);
493       }
494       for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
495         Object *ob_iter = objects[ob_index];
496         draw_uvs(sima, scene, ob_iter, depsgraph);
497       }
498       MEM_freeN(objects);
499     }
500     else {
501       draw_uvs_texpaint(scene, obact, depsgraph);
502     }
503   }
504 }