Rename any instance of scene layer or render layer in code with view layer
[blender.git] / source / blender / draw / intern / draw_view.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file blender/draw/intern/draw_view.c
23  *  \ingroup draw
24  *
25  * Contains dynamic drawing using immediate mode
26  */
27
28 #include "DNA_brush_types.h"
29 #include "DNA_screen_types.h"
30 #include "DNA_userdef_types.h"
31 #include "DNA_view3d_types.h"
32
33 #include "ED_screen.h"
34 #include "ED_transform.h"
35 #include "ED_view3d.h"
36
37 #include "GPU_draw.h"
38 #include "GPU_shader.h"
39 #include "GPU_immediate.h"
40 #include "GPU_matrix.h"
41
42 #include "UI_resources.h"
43
44 #include "WM_api.h"
45 #include "WM_types.h"
46
47 #include "BKE_global.h"
48 #include "BKE_object.h"
49 #include "BKE_paint.h"
50 #include "BKE_unit.h"
51
52 #include "DRW_render.h"
53
54 #include "view3d_intern.h"
55
56 #include "draw_view.h"
57
58 /* ******************** region info ***************** */
59
60 void DRW_draw_region_info(void)
61 {
62         const DRWContextState *draw_ctx = DRW_context_state_get();
63         ARegion *ar = draw_ctx->ar;
64         int offset;
65
66         DRW_draw_cursor();
67
68         offset = DRW_draw_region_engine_info_offset();
69
70         view3d_draw_region_info(draw_ctx->evil_C, ar, offset);
71
72         if (offset > 0) {
73                 DRW_draw_region_engine_info();
74         }
75 }
76
77 /* ************************* Grid ************************** */
78
79 static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count)
80 {
81         /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
82          * x0 is gridline 0, the axis in screen space
83          * Area covers [0 .. max) pixels */
84
85         int first = (int)ceil(-x0 / dx);
86         int last = (int)floor((max - x0) / dx);
87
88         if (first <= last) {
89                 *r_first = first;
90                 *r_count = last - first + 1;
91         }
92         else {
93                 *r_first = 0;
94                 *r_count = 0;
95         }
96 }
97
98 static int gridline_count(ARegion *ar, double x0, double y0, double dx)
99 {
100         /* x0 & y0 establish the "phase" of the grid within this 2D region
101          * dx is the frequency, shared by x & y directions
102          * pass in dx of smallest (highest precision) grid we want to draw */
103
104         int first, x_ct, y_ct;
105
106         gridline_range(x0, dx, ar->winx, &first, &x_ct);
107         gridline_range(y0, dx, ar->winy, &first, &y_ct);
108
109         int total_ct = x_ct + y_ct;
110
111         return total_ct;
112 }
113
114 static bool drawgrid_draw(
115         ARegion *ar, double x0, double y0, double dx, int skip_mod,
116         unsigned pos, unsigned col, GLubyte col_value[3])
117 {
118         /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw
119          * always skip exact x0 & y0 axes; they will be drawn later in color
120          *
121          * set grid color once, just before the first line is drawn
122          * it's harmless to set same color for every line, or every vertex
123          * but if no lines are drawn, color must not be set! */
124
125         const float x_max = (float)ar->winx;
126         const float y_max = (float)ar->winy;
127
128         int first, ct;
129         int x_ct = 0, y_ct = 0; /* count of lines actually drawn */
130         int lines_skipped_for_next_unit = 0;
131
132         /* draw vertical lines */
133         gridline_range(x0, dx, x_max, &first, &ct);
134
135         for (int i = first; i < first + ct; ++i) {
136                 if (i == 0)
137                         continue;
138                 else if (skip_mod && (i % skip_mod) == 0) {
139                         ++lines_skipped_for_next_unit;
140                         continue;
141                 }
142
143                 if (x_ct == 0)
144                         immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
145
146                 float x = (float)(x0 + i * dx);
147                 immVertex2f(pos, x, 0.0f);
148                 immVertex2f(pos, x, y_max);
149                 ++x_ct;
150         }
151
152         /* draw horizontal lines */
153         gridline_range(y0, dx, y_max, &first, &ct);
154
155         for (int i = first; i < first + ct; ++i) {
156                 if (i == 0)
157                         continue;
158                 else if (skip_mod && (i % skip_mod) == 0) {
159                         ++lines_skipped_for_next_unit;
160                         continue;
161                 }
162
163                 if (x_ct + y_ct == 0)
164                         immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
165
166                 float y = (float)(y0 + i * dx);
167                 immVertex2f(pos, 0.0f, y);
168                 immVertex2f(pos, x_max, y);
169                 ++y_ct;
170         }
171
172         return lines_skipped_for_next_unit > 0;
173 }
174
175 #define GRID_MIN_PX_D 6.0
176 #define GRID_MIN_PX_F 6.0f
177
178 static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
179 {
180         RegionView3D *rv3d = ar->regiondata;
181
182         double fx = rv3d->persmat[3][0];
183         double fy = rv3d->persmat[3][1];
184         double fw = rv3d->persmat[3][3];
185
186         const double wx = 0.5 * ar->winx;  /* use double precision to avoid rounding errors */
187         const double wy = 0.5 * ar->winy;
188
189         double x = wx * fx / fw;
190         double y = wy * fy / fw;
191
192         double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 };
193         mul_m4_v4d(rv3d->persmat, vec4);
194         fx = vec4[0];
195         fy = vec4[1];
196         fw = vec4[3];
197
198         double dx = fabs(x - wx * fx / fw);
199         if (dx == 0) dx = fabs(y - wy * fy / fw);
200
201         x += wx;
202         y += wy;
203
204         /* now x, y, and dx have their final values
205          * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space
206          * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */
207
208         glLineWidth(1.0f);
209
210 #if 0 /* TODO: write to UI/widget depth buffer, not scene depth */
211         glDepthMask(GL_FALSE);  /* disable write in zbuffer */
212 #endif
213
214         Gwn_VertFormat *format = immVertexFormat();
215         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
216         unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
217
218         immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
219
220         unsigned char col[3], col2[3];
221         UI_GetThemeColor3ubv(TH_GRID, col);
222
223         if (unit->system) {
224                 const void *usys;
225                 int len;
226
227                 bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
228
229                 bool first = true;
230
231                 if (usys) {
232                         int i = len;
233                         while (i--) {
234                                 double scalar = bUnit_GetScaler(usys, i);
235
236                                 double dx_scalar = dx * scalar / (double)unit->scale_length;
237                                 if (dx_scalar < (GRID_MIN_PX_D * 2.0)) {
238                                         /* very very small grid items are less useful when dealing with units */
239                                         continue;
240                                 }
241
242                                 if (first) {
243                                         first = false;
244
245                                         /* Store the smallest drawn grid size units name so users know how big each grid cell is */
246                                         *grid_unit = bUnit_GetNameDisplay(usys, i);
247                                         rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
248
249                                         int gridline_ct = gridline_count(ar, x, y, dx_scalar);
250                                         if (gridline_ct == 0)
251                                                 goto drawgrid_cleanup; /* nothing to draw */
252
253                                         immBegin(GWN_PRIM_LINES, gridline_ct * 2);
254                                 }
255
256                                 float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
257                                 /* tweak to have the fade a bit nicer */
258                                 blend_fac = (blend_fac * blend_fac) * 2.0f;
259                                 CLAMP(blend_fac, 0.3f, 1.0f);
260
261                                 UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2);
262
263                                 const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar);
264                                 if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2))
265                                         break;
266                         }
267                 }
268         }
269         else {
270                 const double sublines = v3d->gridsubdiv;
271                 const float  sublines_fl = v3d->gridsubdiv;
272
273                 int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */
274
275                 if (dx < GRID_MIN_PX_D) {
276                         rv3d->gridview *= sublines_fl;
277                         dx *= sublines;
278                         if (dx < GRID_MIN_PX_D) {
279                                 rv3d->gridview *= sublines_fl;
280                                 dx *= sublines;
281                                 if (dx < GRID_MIN_PX_D) {
282                                         rv3d->gridview *= sublines_fl;
283                                         dx *= sublines;
284                                         grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1;
285                                 }
286                         }
287                 }
288                 else {
289                         if (dx > (GRID_MIN_PX_D * 10.0)) {  /* start blending in */
290                                 rv3d->gridview /= sublines_fl;
291                                 dx /= sublines;
292                                 if (dx > (GRID_MIN_PX_D * 10.0)) {  /* start blending in */
293                                         rv3d->gridview /= sublines_fl;
294                                         dx /= sublines;
295                                         if (dx > (GRID_MIN_PX_D * 10.0)) {
296                                                 grids_to_draw = 1;
297                                         }
298                                 }
299                         }
300                 }
301
302                 int gridline_ct = gridline_count(ar, x, y, dx);
303                 if (gridline_ct == 0)
304                         goto drawgrid_cleanup; /* nothing to draw */
305
306                 immBegin(GWN_PRIM_LINES, gridline_ct * 2);
307
308                 if (grids_to_draw == 2) {
309                         UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
310                         if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2)) {
311                                 drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col);
312                         }
313                 }
314                 else if (grids_to_draw == 1) {
315                         drawgrid_draw(ar, x, y, dx, 0, pos, color, col);
316                 }
317         }
318
319         /* draw visible axes */
320         /* horizontal line */
321         if (0 <= y && y < ar->winy) {
322                 UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X');
323                 immAttrib3ub(color, col2[0], col2[1], col2[2]);
324                 immVertex2f(pos, 0.0f, y);
325                 immVertex2f(pos, (float)ar->winx, y);
326         }
327
328         /* vertical line */
329         if (0 <= x && x < ar->winx) {
330                 UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z');
331                 immAttrib3ub(color, col2[0], col2[1], col2[2]);
332                 immVertex2f(pos, x, 0.0f);
333                 immVertex2f(pos, x, (float)ar->winy);
334         }
335
336         immEnd();
337
338 drawgrid_cleanup:
339         immUnbindProgram();
340
341 #if 0 /* depth write is left enabled above */
342         glDepthMask(GL_TRUE);  /* enable write in zbuffer */
343 #endif
344 }
345
346 #undef DEBUG_GRID
347 #undef GRID_MIN_PX_D
348 #undef GRID_MIN_PX_F
349
350 static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
351 {
352         /* draw only if there is something to draw */
353         if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
354                 /* draw how many lines?
355                  * trunc(v3d->gridlines / 2) * 4
356                  * + 2 for xy axes (possibly with special colors)
357                  * + 1 for z axis (the only line not in xy plane)
358                  * even v3d->gridlines are honored, odd rounded down */
359                 const int gridlines = v3d->gridlines / 2;
360                 const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
361                 const float grid = gridlines * grid_scale;
362
363                 const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
364
365                 bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0;
366                 bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0;
367                 bool show_axis_z = (v3d->gridflag & V3D_SHOW_Z) != 0;
368
369                 unsigned char col_grid[3], col_axis[3];
370
371                 glLineWidth(1.0f);
372
373                 UI_GetThemeColor3ubv(TH_GRID, col_grid);
374
375                 if (show_floor) {
376                         const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
377                         const int sublines = v3d->gridsubdiv;
378
379                         unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
380
381                         Gwn_VertFormat *format = immVertexFormat();
382                         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
383                         unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
384
385                         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
386
387                         immBegin(GWN_PRIM_LINES, vertex_ct);
388
389                         /* draw normal grid lines */
390                         UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
391
392                         for (int a = 1; a <= gridlines; a++) {
393                                 /* skip emphasised divider lines */
394                                 if (a % sublines != 0) {
395                                         const float line = a * grid_scale;
396
397                                         immAttrib3ubv(color, col_grid_light);
398
399                                         immVertex2f(pos, -grid, -line);
400                                         immVertex2f(pos, +grid, -line);
401                                         immVertex2f(pos, -grid, +line);
402                                         immVertex2f(pos, +grid, +line);
403
404                                         immVertex2f(pos, -line, -grid);
405                                         immVertex2f(pos, -line, +grid);
406                                         immVertex2f(pos, +line, -grid);
407                                         immVertex2f(pos, +line, +grid);
408                                 }
409                         }
410
411                         /* draw emphasised grid lines */
412                         UI_GetThemeColor3ubv(TH_BACK, col_bg);
413                         /* emphasise division lines lighter instead of darker, if background is darker than grid */
414                         UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
415                                 (col_grid[0] + col_grid[1] + col_grid[2] + 30 >
416                                 col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
417
418                         if (sublines <= gridlines) {
419                                 immAttrib3ubv(color, col_grid_emphasise);
420
421                                 for (int a = sublines; a <= gridlines; a += sublines) {
422                                         const float line = a * grid_scale;
423
424                                         immVertex2f(pos, -grid, -line);
425                                         immVertex2f(pos, +grid, -line);
426                                         immVertex2f(pos, -grid, +line);
427                                         immVertex2f(pos, +grid, +line);
428
429                                         immVertex2f(pos, -line, -grid);
430                                         immVertex2f(pos, -line, +grid);
431                                         immVertex2f(pos, +line, -grid);
432                                         immVertex2f(pos, +line, +grid);
433                                 }
434                         }
435
436                         /* draw X axis */
437                         if (show_axis_x) {
438                                 show_axis_x = false; /* drawing now, won't need to draw later */
439                                 UI_make_axis_color(col_grid, col_axis, 'X');
440                                 immAttrib3ubv(color, col_axis);
441                         }
442                         else
443                                 immAttrib3ubv(color, col_grid_emphasise);
444
445                         immVertex2f(pos, -grid, 0.0f);
446                         immVertex2f(pos, +grid, 0.0f);
447
448                         /* draw Y axis */
449                         if (show_axis_y) {
450                                 show_axis_y = false; /* drawing now, won't need to draw later */
451                                 UI_make_axis_color(col_grid, col_axis, 'Y');
452                                 immAttrib3ubv(color, col_axis);
453                         }
454                         else
455                                 immAttrib3ubv(color, col_grid_emphasise);
456
457                         immVertex2f(pos, 0.0f, -grid);
458                         immVertex2f(pos, 0.0f, +grid);
459
460                         immEnd();
461                         immUnbindProgram();
462
463                         /* done with XY plane */
464                 }
465
466                 if (show_axis_x || show_axis_y || show_axis_z) {
467                         /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
468
469                         Gwn_VertFormat *format = immVertexFormat();
470                         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
471                         unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
472
473                         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
474                         immBegin(GWN_PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
475
476                         if (show_axis_x) {
477                                 UI_make_axis_color(col_grid, col_axis, 'X');
478                                 immAttrib3ubv(color, col_axis);
479                                 immVertex3f(pos, -grid, 0.0f, 0.0f);
480                                 immVertex3f(pos, +grid, 0.0f, 0.0f);
481                         }
482
483                         if (show_axis_y) {
484                                 UI_make_axis_color(col_grid, col_axis, 'Y');
485                                 immAttrib3ubv(color, col_axis);
486                                 immVertex3f(pos, 0.0f, -grid, 0.0f);
487                                 immVertex3f(pos, 0.0f, +grid, 0.0f);
488                         }
489
490                         if (show_axis_z) {
491                                 UI_make_axis_color(col_grid, col_axis, 'Z');
492                                 immAttrib3ubv(color, col_axis);
493                                 immVertex3f(pos, 0.0f, 0.0f, -grid);
494                                 immVertex3f(pos, 0.0f, 0.0f, +grid);
495                         }
496
497                         immEnd();
498                         immUnbindProgram();
499                 }
500         }
501 }
502
503 void DRW_draw_grid(void)
504 {
505         /* TODO viewport
506          * Missing is the flags to check whether to draw it
507          * for now now we are using the flags in v3d itself.
508          *
509          * Also for now always assume depth is there, so we
510          * draw on top of it.
511          */
512         /**
513          * Calculate pixel-size factor once, is used for lamps and object centers.
514          * Used by #ED_view3d_pixel_size and typically not accessed directly.
515          *
516          * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value,
517          * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value,
518          * but in perspective mode its offset by the near-clip.
519          *
520          * 'RegionView3D.pixsize' is used for viewport drawing, not rendering.
521          */
522         const DRWContextState *draw_ctx = DRW_context_state_get();
523         Scene *scene = draw_ctx->scene;
524         View3D *v3d = draw_ctx->v3d;
525         ARegion *ar = draw_ctx->ar;
526         RegionView3D *rv3d = draw_ctx->rv3d;
527
528         const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
529         const char *grid_unit = NULL;
530
531         /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
532          * objects if done last
533          * needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views.
534          */
535         rv3d->gridview = ED_view3d_grid_scale(scene, v3d, &grid_unit);
536
537         glEnable(GL_DEPTH_TEST);
538         glDepthFunc(GL_LESS);
539
540         if (!draw_floor) {
541                 /* Do not get in front of overlays */
542                 glDepthMask(GL_FALSE);
543
544                 ED_region_pixelspace(ar);
545                 *(&grid_unit) = NULL;  /* drawgrid need this to detect/affect smallest valid unit... */
546                 drawgrid(&scene->unit, ar, v3d, &grid_unit);
547
548                 gpuLoadProjectionMatrix(rv3d->winmat);
549                 gpuLoadMatrix(rv3d->viewmat);
550         }
551         else {
552                 glDepthMask(GL_TRUE);
553                 drawfloor(scene, v3d, &grid_unit);
554         }
555 }
556
557 /* ************************* Background ************************** */
558
559 void DRW_draw_background(void)
560 {
561         /* Just to make sure */
562         glDepthMask(GL_TRUE);
563         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
564         glStencilMask(0xFF);
565
566         if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
567                 float m[4][4];
568                 unit_m4(m);
569
570                 /* Gradient background Color */
571                 glDisable(GL_DEPTH_TEST);
572
573                 Gwn_VertFormat *format = immVertexFormat();
574                 unsigned pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
575                 unsigned color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
576                 unsigned char col_hi[3], col_lo[3];
577
578                 gpuPushMatrix();
579                 gpuLoadIdentity();
580                 gpuLoadProjectionMatrix(m);
581
582                 immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
583
584                 UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
585                 UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
586
587                 immBegin(GWN_PRIM_TRI_FAN, 4);
588                 immAttrib3ubv(color, col_lo);
589                 immVertex2f(pos, -1.0f, -1.0f);
590                 immVertex2f(pos, 1.0f, -1.0f);
591
592                 immAttrib3ubv(color, col_hi);
593                 immVertex2f(pos, 1.0f, 1.0f);
594                 immVertex2f(pos, -1.0f, 1.0f);
595                 immEnd();
596
597                 immUnbindProgram();
598
599                 gpuPopMatrix();
600
601                 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
602
603                 glEnable(GL_DEPTH_TEST);
604         }
605         else {
606                 /* Solid background Color */
607                 UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
608                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
609         }
610 }
611
612 /* **************************** 3D Cursor ******************************** */
613
614 static bool is_cursor_visible(Scene *scene, ViewLayer *view_layer)
615 {
616         Object *ob = OBACT(view_layer);
617
618         /* don't draw cursor in paint modes, but with a few exceptions */
619         if (ob && ob->mode & OB_MODE_ALL_PAINT) {
620                 /* exception: object is in weight paint and has deforming armature in pose mode */
621                 if (ob->mode & OB_MODE_WEIGHT_PAINT) {
622                         if (BKE_object_pose_armature_get(ob) != NULL) {
623                                 return true;
624                         }
625                 }
626                 /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
627                 else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
628                         const Paint *p = BKE_paint_get_active(scene, view_layer);
629
630                         if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
631                                 if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
632                                         return true;
633                                 }
634                         }
635                 }
636
637                 /* no exception met? then don't draw cursor! */
638                 return false;
639         }
640
641         return true;
642 }
643
644 void DRW_draw_cursor(void)
645 {
646         const DRWContextState *draw_ctx = DRW_context_state_get();
647         View3D *v3d = draw_ctx->v3d;
648         RegionView3D *rv3d = draw_ctx->rv3d;
649         Scene *scene = draw_ctx->scene;
650         ViewLayer *view_layer = draw_ctx->view_layer;
651
652         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
653         glDepthMask(GL_FALSE);
654         glDisable(GL_DEPTH_TEST);
655         glLineWidth(1.0f);
656
657         if (is_cursor_visible(scene, view_layer)) {
658                 float *co = ED_view3d_cursor3d_get(scene, v3d);
659                 unsigned char crosshair_color[3];
660
661                 const float f5 = 0.25f;
662                 const float f10 = 0.5f;
663                 const float f20 = 1.0f;
664
665                 Gwn_VertFormat *format = immVertexFormat();
666                 unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
667                 unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
668                 unsigned int wpos = GWN_vertformat_attr_add(format, "world_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
669
670                 /* XXX Using instance shader without instance */
671                 immBindBuiltinProgram(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR);
672                 immUniform1f("size", U.widget_unit);
673                 immUniform1f("pixel_size", *DRW_viewport_pixelsize_get());
674                 immUniformArray3fv("screen_vecs", DRW_viewport_screenvecs_get(), 2);
675                 immUniformMatrix4fv("ViewProjectionMatrix", rv3d->persmat);
676
677                 const int segments = 16;
678
679                 immBegin(GWN_PRIM_LINE_LOOP, segments);
680                 immAttrib3fv(wpos, co);
681
682                 for (int i = 0; i < segments; ++i) {
683                         float angle = (float)(2 * M_PI) * ((float)i / (float)segments);
684                         float x = f10 * cosf(angle);
685                         float y = f10 * sinf(angle);
686
687                         if (i % 2 == 0)
688                                 immAttrib3ub(color, 255, 0, 0);
689                         else
690                                 immAttrib3ub(color, 255, 255, 255);
691
692                         immVertex2f(pos, x, y);
693                 }
694                 immEnd();
695
696                 UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
697
698                 immBegin(GWN_PRIM_LINES, 8);
699                 immAttrib3ubv(color, crosshair_color);
700                 immAttrib3fv(wpos, co);
701
702                 immVertex2f(pos, -f20, 0);
703                 immVertex2f(pos, -f5, 0);
704                 immVertex2f(pos, +f5, 0);
705                 immVertex2f(pos, +f20, 0);
706                 immVertex2f(pos, 0, -f20);
707                 immVertex2f(pos, 0, -f5);
708                 immVertex2f(pos, 0, +f5);
709                 immVertex2f(pos, 0, +f20);
710                 immEnd();
711
712                 immUnbindProgram();
713         }
714 }
715
716 /* **************************** 3D Manipulator ******************************** */
717
718 void DRW_draw_manipulator(void)
719 {
720         const DRWContextState *draw_ctx = DRW_context_state_get();
721         View3D *v3d = draw_ctx->v3d;
722         v3d->zbuf = false;
723         ARegion *ar = draw_ctx->ar;
724
725
726         /* TODO, only draws 3D manipulators right now, need to see how 2D drawing will work in new viewport */
727
728         /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */
729         /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should
730          * later become _IN_SCENE (and draw _3D separate) */
731         WM_manipulatormap_draw(
732                 ar->manipulator_map, draw_ctx->evil_C,
733                 WM_MANIPULATORMAP_DRAWSTEP_3D);
734
735         /* We may want to split this into a separate pass.
736          * or maintain a stage in the draw manager where all pixel-space drawing happens. */
737         {
738                 float original_proj[4][4];
739                 gpuGetProjectionMatrix(original_proj);
740                 wmOrtho2_region_pixelspace(ar);
741
742                 gpuPushMatrix();
743                 gpuLoadIdentity();
744
745                 glDepthMask(GL_FALSE);
746
747                 WM_manipulatormap_draw(
748                         ar->manipulator_map, draw_ctx->evil_C,
749                         WM_MANIPULATORMAP_DRAWSTEP_2D);
750
751                 glDepthMask(GL_TRUE);
752
753                 gpuPopMatrix();
754                 gpuLoadProjectionMatrix(original_proj);
755         }
756 }