Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / interface / interface_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/interface/interface_draw.c
27  *  \ingroup edinterface
28  */
29
30
31 #include <math.h>
32 #include <string.h>
33
34 #include "DNA_color_types.h"
35 #include "DNA_screen_types.h"
36 #include "DNA_movieclip_types.h"
37
38 #include "BLI_math.h"
39 #include "BLI_rect.h"
40 #include "BLI_string.h"
41 #include "BLI_utildefines.h"
42
43 #include "BKE_colorband.h"
44 #include "BKE_colortools.h"
45 #include "BKE_node.h"
46 #include "BKE_tracking.h"
47
48
49 #include "IMB_imbuf.h"
50 #include "IMB_imbuf_types.h"
51 #include "IMB_colormanagement.h"
52
53 #include "BIF_glutil.h"
54
55 #include "BLF_api.h"
56
57 #include "GPU_batch.h"
58 #include "GPU_immediate.h"
59 #include "GPU_immediate_util.h"
60 #include "GPU_matrix.h"
61
62 #include "UI_interface.h"
63
64 /* own include */
65 #include "interface_intern.h"
66
67
68 static int roundboxtype = UI_CNR_ALL;
69
70 void UI_draw_roundbox_corner_set(int type)
71 {
72         /* Not sure the roundbox function is the best place to change this
73          * if this is undone, it's not that big a deal, only makes curves edges
74          * square for the  */
75         roundboxtype = type;
76 }
77
78 #if 0 /* unused */
79 int UI_draw_roundbox_corner_get(void)
80 {
81         return roundboxtype;
82 }
83 #endif
84
85 void UI_draw_roundbox_3ubAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const unsigned char col[3], unsigned char alpha)
86 {
87         float colv[4];
88         colv[0] = ((float)col[0]) / 255;
89         colv[1] = ((float)col[1]) / 255;
90         colv[2] = ((float)col[2]) / 255;
91         colv[3] = ((float)alpha) / 255;
92         UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
93 }
94
95 void UI_draw_roundbox_3fvAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[3], float alpha)
96 {
97         float colv[4];
98         colv[0] = col[0];
99         colv[1] = col[1];
100         colv[2] = col[2];
101         colv[3] = alpha;
102         UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
103 }
104
105 void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4])
106 {
107         uiWidgetBaseParameters widget_params = {
108                 .recti.xmin = minx, .recti.ymin = miny,
109                 .recti.xmax = maxx, .recti.ymax = maxy,
110                 .radi = rad,
111                 .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
112                 .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
113                 .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
114                 .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
115                 .color_inner1[0] = color[0], .color_inner2[0] = color[0],
116                 .color_inner1[1] = color[1], .color_inner2[1] = color[1],
117                 .color_inner1[2] = color[2], .color_inner2[2] = color[2],
118                 .color_inner1[3] = color[3], .color_inner2[3] = color[3],
119                 .alpha_discard = 1.0f,
120         };
121
122         glEnable(GL_BLEND);
123
124         if (filled) {
125                 /* plain antialiased filled box */
126                 widget_params.color_inner1[3] *= 0.125f;
127                 widget_params.color_inner2[3] *= 0.125f;
128
129                 /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
130                  * If it has been scaled, then it's no longer valid. */
131                 Gwn_Batch *batch = ui_batch_roundbox_get(filled, true);
132                 GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
133                 GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
134                 GWN_batch_draw(batch);
135         }
136         else {
137                 /* plain antialiased unfilled box */
138                 glEnable(GL_LINE_SMOOTH);
139
140                 Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
141                 GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
142                 GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
143                 GWN_batch_draw(batch);
144
145                 glDisable(GL_LINE_SMOOTH);
146         }
147
148         glDisable(GL_BLEND);
149 }
150
151 void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4])
152 {
153 #if 0
154         float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
155                            {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
156         int a;
157
158         Gwn_VertFormat *format = immVertexFormat();
159         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
160
161         /* mult */
162         for (a = 0; a < 7; a++) {
163                 mul_v2_fl(vec[a], rad);
164         }
165
166         unsigned int vert_ct = 0;
167         vert_ct += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
168         vert_ct += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
169         vert_ct += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
170         vert_ct += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
171
172         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
173         immUniformColor4fv(col);
174
175         immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_ct);
176         /* start with corner right-bottom */
177         if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
178                 immVertex2f(pos, maxx - rad, miny);
179                 for (a = 0; a < 7; a++) {
180                         immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
181                 }
182                 immVertex2f(pos, maxx, miny + rad);
183         }
184         else {
185                 immVertex2f(pos, maxx, miny);
186         }
187
188         /* corner right-top */
189         if (roundboxtype & UI_CNR_TOP_RIGHT) {
190                 immVertex2f(pos, maxx, maxy - rad);
191                 for (a = 0; a < 7; a++) {
192                         immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
193                 }
194                 immVertex2f(pos, maxx - rad, maxy);
195         }
196         else {
197                 immVertex2f(pos, maxx, maxy);
198         }
199
200         /* corner left-top */
201         if (roundboxtype & UI_CNR_TOP_LEFT) {
202                 immVertex2f(pos, minx + rad, maxy);
203                 for (a = 0; a < 7; a++) {
204                         immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
205                 }
206                 immVertex2f(pos, minx, maxy - rad);
207         }
208         else {
209                 immVertex2f(pos, minx, maxy);
210         }
211
212         /* corner left-bottom */
213         if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
214                 immVertex2f(pos, minx, miny + rad);
215                 for (a = 0; a < 7; a++) {
216                         immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
217                 }
218                 immVertex2f(pos, minx + rad, miny);
219         }
220         else {
221                 immVertex2f(pos, minx, miny);
222         }
223
224         immEnd();
225         immUnbindProgram();
226 #endif
227
228         uiWidgetBaseParameters widget_params = {
229                 .recti.xmin = minx, .recti.ymin = miny,
230                 .recti.xmax = maxx, .recti.ymax = maxy,
231                 .radi = rad,
232                 .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
233                 .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
234                 .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
235                 .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
236                 .color_inner1[0] = col[0], .color_inner2[0] = col[0],
237                 .color_inner1[1] = col[1], .color_inner2[1] = col[1],
238                 .color_inner1[2] = col[2], .color_inner2[2] = col[2],
239                 .color_inner1[3] = col[3], .color_inner2[3] = col[3],
240                 .alpha_discard = 1.0f,
241         };
242
243         Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
244         GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
245         GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
246         GWN_batch_draw(batch);
247 }
248
249 #if 0
250 static void round_box_shade_col(unsigned attrib, const float col1[3], float const col2[3], const float fac)
251 {
252         float col[4] = {
253                 fac * col1[0] + (1.0f - fac) * col2[0],
254                 fac * col1[1] + (1.0f - fac) * col2[1],
255                 fac * col1[2] + (1.0f - fac) * col2[2],
256                 1.0f
257         };
258         immAttrib4fv(attrib, col);
259 }
260 #endif
261
262 /* linear horizontal shade within button or in outline */
263 /* view2d scrollers use it */
264 void UI_draw_roundbox_shade_x(
265         bool filled, float minx, float miny, float maxx, float maxy,
266         float rad, float shadetop, float shadedown, const float col[4])
267 {
268 #if 0
269         float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
270                            {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
271         const float div = maxy - miny;
272         const float idiv = 1.0f / div;
273         float coltop[3], coldown[3];
274         int vert_count = 0;
275         int a;
276
277         Gwn_VertFormat *format = immVertexFormat();
278         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
279         unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
280
281         immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
282
283         /* mult */
284         for (a = 0; a < 7; a++) {
285                 mul_v2_fl(vec[a], rad);
286         }
287
288         /* 'shade' defines strength of shading */
289         coltop[0]  = min_ff(1.0f, col[0] + shadetop);
290         coltop[1]  = min_ff(1.0f, col[1] + shadetop);
291         coltop[2]  = min_ff(1.0f, col[2] + shadetop);
292         coldown[0] = max_ff(0.0f, col[0] + shadedown);
293         coldown[1] = max_ff(0.0f, col[1] + shadedown);
294         coldown[2] = max_ff(0.0f, col[2] + shadedown);
295
296         vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
297         vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
298         vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
299         vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
300
301         immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count);
302
303         /* start with corner right-bottom */
304         if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
305
306                 round_box_shade_col(color, coltop, coldown, 0.0);
307                 immVertex2f(pos, maxx - rad, miny);
308
309                 for (a = 0; a < 7; a++) {
310                         round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv);
311                         immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
312                 }
313
314                 round_box_shade_col(color, coltop, coldown, rad * idiv);
315                 immVertex2f(pos, maxx, miny + rad);
316         }
317         else {
318                 round_box_shade_col(color, coltop, coldown, 0.0);
319                 immVertex2f(pos, maxx, miny);
320         }
321
322         /* corner right-top */
323         if (roundboxtype & UI_CNR_TOP_RIGHT) {
324
325                 round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
326                 immVertex2f(pos, maxx, maxy - rad);
327
328                 for (a = 0; a < 7; a++) {
329                         round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv);
330                         immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
331                 }
332                 round_box_shade_col(color, coltop, coldown, 1.0);
333                 immVertex2f(pos, maxx - rad, maxy);
334         }
335         else {
336                 round_box_shade_col(color, coltop, coldown, 1.0);
337                 immVertex2f(pos, maxx, maxy);
338         }
339
340         /* corner left-top */
341         if (roundboxtype & UI_CNR_TOP_LEFT) {
342
343                 round_box_shade_col(color, coltop, coldown, 1.0);
344                 immVertex2f(pos, minx + rad, maxy);
345
346                 for (a = 0; a < 7; a++) {
347                         round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv);
348                         immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
349                 }
350
351                 round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
352                 immVertex2f(pos, minx, maxy - rad);
353         }
354         else {
355                 round_box_shade_col(color, coltop, coldown, 1.0);
356                 immVertex2f(pos, minx, maxy);
357         }
358
359         /* corner left-bottom */
360         if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
361
362                 round_box_shade_col(color, coltop, coldown, rad * idiv);
363                 immVertex2f(pos, minx, miny + rad);
364
365                 for (a = 0; a < 7; a++) {
366                         round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv);
367                         immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
368                 }
369
370                 round_box_shade_col(color, coltop, coldown, 0.0);
371                 immVertex2f(pos, minx + rad, miny);
372         }
373         else {
374                 round_box_shade_col(color, coltop, coldown, 0.0);
375                 immVertex2f(pos, minx, miny);
376         }
377
378         immEnd();
379         immUnbindProgram();
380 #endif
381
382         uiWidgetBaseParameters widget_params = {
383                 .recti.xmin = minx, .recti.ymin = miny,
384                 .recti.xmax = maxx, .recti.ymax = maxy,
385                 .radi = rad,
386                 .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
387                 .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
388                 .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
389                 .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
390                 .color_inner1[0] = min_ff(1.0f, col[0] + shadetop),
391                 .color_inner2[0] = max_ff(0.0f, col[0] + shadedown),
392                 .color_inner1[1] = min_ff(1.0f, col[1] + shadetop),
393                 .color_inner2[1] = max_ff(0.0f, col[1] + shadedown),
394                 .color_inner1[2] = min_ff(1.0f, col[2] + shadetop),
395                 .color_inner2[2] = max_ff(0.0f, col[2] + shadedown),
396                 .color_inner1[3] = 1.0f,
397                 .color_inner2[3] = 1.0f,
398                 .alpha_discard = 1.0f,
399         };
400
401         Gwn_Batch *batch = ui_batch_roundbox_get(filled, false);
402         GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
403         GWN_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params);
404         GWN_batch_draw(batch);
405 }
406
407 #if 0 /* unused */
408 /* linear vertical shade within button or in outline */
409 /* view2d scrollers use it */
410 void UI_draw_roundbox_shade_y(
411         bool filled, float minx, float miny, float maxx, float maxy,
412         float rad, float shadeleft, float shaderight, const float col[4])
413 {
414         float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
415                            {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
416         const float div = maxx - minx;
417         const float idiv = 1.0f / div;
418         float colLeft[3], colRight[3];
419         int vert_count = 0;
420         int a;
421
422         /* mult */
423         for (a = 0; a < 7; a++) {
424                 mul_v2_fl(vec[a], rad);
425         }
426
427         Gwn_VertFormat *format = immVertexFormat();
428         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
429         unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
430
431         immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
432
433         /* 'shade' defines strength of shading */
434         colLeft[0]  = min_ff(1.0f, col[0] + shadeleft);
435         colLeft[1]  = min_ff(1.0f, col[1] + shadeleft);
436         colLeft[2]  = min_ff(1.0f, col[2] + shadeleft);
437         colRight[0] = max_ff(0.0f, col[0] + shaderight);
438         colRight[1] = max_ff(0.0f, col[1] + shaderight);
439         colRight[2] = max_ff(0.0f, col[2] + shaderight);
440
441
442         vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
443         vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
444         vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
445         vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
446
447         immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_count);
448
449         /* start with corner right-bottom */
450         if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
451                 round_box_shade_col(color, colLeft, colRight, 0.0);
452                 immVertex2f(pos, maxx - rad, miny);
453
454                 for (a = 0; a < 7; a++) {
455                         round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv);
456                         immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
457                 }
458
459                 round_box_shade_col(color, colLeft, colRight, rad * idiv);
460                 immVertex2f(pos, maxx, miny + rad);
461         }
462         else {
463                 round_box_shade_col(color, colLeft, colRight, 0.0);
464                 immVertex2f(pos, maxx, miny);
465         }
466
467         /* corner right-top */
468         if (roundboxtype & UI_CNR_TOP_RIGHT) {
469                 round_box_shade_col(color, colLeft, colRight, 0.0);
470                 immVertex2f(pos, maxx, maxy - rad);
471
472                 for (a = 0; a < 7; a++) {
473
474                         round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv);
475                         immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
476                 }
477                 round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
478                 immVertex2f(pos, maxx - rad, maxy);
479         }
480         else {
481                 round_box_shade_col(color, colLeft, colRight, 0.0);
482                 immVertex2f(pos, maxx, maxy);
483         }
484
485         /* corner left-top */
486         if (roundboxtype & UI_CNR_TOP_LEFT) {
487                 round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
488                 immVertex2f(pos, minx + rad, maxy);
489
490                 for (a = 0; a < 7; a++) {
491                         round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv);
492                         immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
493                 }
494
495                 round_box_shade_col(color, colLeft, colRight, 1.0);
496                 immVertex2f(pos, minx, maxy - rad);
497         }
498         else {
499                 round_box_shade_col(color, colLeft, colRight, 1.0);
500                 immVertex2f(pos, minx, maxy);
501         }
502
503         /* corner left-bottom */
504         if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
505                 round_box_shade_col(color, colLeft, colRight, 1.0);
506                 immVertex2f(pos, minx, miny + rad);
507
508                 for (a = 0; a < 7; a++) {
509                         round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv);
510                         immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
511                 }
512
513                 round_box_shade_col(color, colLeft, colRight, 1.0);
514                 immVertex2f(pos, minx + rad, miny);
515         }
516         else {
517                 round_box_shade_col(color, colLeft, colRight, 1.0);
518                 immVertex2f(pos, minx, miny);
519         }
520
521         immEnd();
522         immUnbindProgram();
523 }
524 #endif /* unused */
525
526 void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4])
527 {
528         int ofs_y = 4 * U.pixelsize;
529
530         Gwn_VertFormat *format = immVertexFormat();
531         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
532
533         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
534         immUniformColor4fv(color);
535
536         immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
537         immUnbindProgram();
538 }
539
540 /* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
541
542 /* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */
543 void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3])
544 {
545         Gwn_VertFormat *format = immVertexFormat();
546         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
547         unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
548         /* add a 1px offset, looks nicer */
549         const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize;
550         const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize;
551         int a;
552         float vec[4][2] = {
553             {0.195, 0.02},
554             {0.55, 0.169},
555             {0.831, 0.45},
556             {0.98, 0.805},
557         };
558
559
560         /* mult */
561         for (a = 0; a < 4; a++) {
562                 mul_v2_fl(vec[a], rad);
563         }
564
565         immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
566         immBeginAtMost(GWN_PRIM_LINE_STRIP, 25);
567
568         immAttrib3ubv(col, highlight);
569
570         /* start with corner left-top */
571         if (roundboxtype & UI_CNR_TOP_LEFT) {
572                 immVertex2f(pos, minx, maxy - rad);
573                 for (a = 0; a < 4; a++) {
574                         immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]);
575                 }
576                 immVertex2f(pos, minx + rad, maxy);
577         }
578         else {
579                 immVertex2f(pos, minx, maxy);
580         }
581
582         /* corner right-top */
583         if (roundboxtype & UI_CNR_TOP_RIGHT) {
584                 immVertex2f(pos, maxx - rad, maxy);
585                 for (a = 0; a < 4; a++) {
586                         immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]);
587                 }
588                 immVertex2f(pos, maxx, maxy - rad);
589         }
590         else {
591                 immVertex2f(pos, maxx, maxy);
592         }
593
594         immAttrib3ubv(col, highlight_fade);
595
596         /* corner right-bottom */
597         if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
598                 immVertex2f(pos, maxx, miny + rad);
599                 for (a = 0; a < 4; a++) {
600                         immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]);
601                 }
602                 immVertex2f(pos, maxx - rad, miny);
603         }
604         else {
605                 immVertex2f(pos, maxx, miny);
606         }
607
608         /* corner left-bottom */
609         if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
610                 immVertex2f(pos, minx + rad, miny);
611                 for (a = 0; a < 4; a++) {
612                         immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]);
613                 }
614                 immVertex2f(pos, minx, miny + rad);
615         }
616         else {
617                 immVertex2f(pos, minx, miny);
618         }
619
620         immAttrib3ubv(col, highlight);
621
622         /* back to corner left-top */
623         immVertex2f(pos, minx, roundboxtype & UI_CNR_TOP_LEFT ? maxy - rad : maxy);
624
625         immEnd();
626         immUnbindProgram();
627 }
628
629 void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
630 {
631 #ifdef WITH_HEADLESS
632         (void)rect;
633         (void)but;
634 #else
635         ImBuf *ibuf = (ImBuf *)but->poin;
636
637         if (!ibuf) return;
638
639         float facx = 1.0f;
640         float facy = 1.0f;
641
642         int w = BLI_rcti_size_x(rect);
643         int h = BLI_rcti_size_y(rect);
644
645         /* scissor doesn't seem to be doing the right thing...? */
646 #if 0
647         /* prevent drawing outside widget area */
648         GLint scissor[4];
649         glGetIntegerv(GL_SCISSOR_BOX, scissor);
650         glScissor(rect->xmin, rect->ymin, w, h);
651 #endif
652
653         glEnable(GL_BLEND);
654
655         if (w != ibuf->x || h != ibuf->y) {
656                 facx = (float)w / (float)ibuf->x;
657                 facy = (float)h / (float)ibuf->y;
658         }
659
660         IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
661         immDrawPixelsTex(&state, (float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect,
662                          facx, facy, NULL);
663
664         glDisable(GL_BLEND);
665
666 #if 0
667         // restore scissortest
668         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
669 #endif
670
671 #endif
672 }
673
674 /**
675  * Draw title and text safe areas.
676  *
677  * \Note This functionn is to be used with the 2D dashed shader enabled.
678  *
679  * \param pos is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib
680  * \param line_origin is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib
681  *
682  * The next 4 parameters are the offsets for the view, not the zones.
683  */
684 void UI_draw_safe_areas(
685         uint pos, float x1, float x2, float y1, float y2,
686         const float title_aspect[2], const float action_aspect[2])
687 {
688         const float size_x_half = (x2 - x1) * 0.5f;
689         const float size_y_half = (y2 - y1) * 0.5f;
690
691         const float *safe_areas[] = {title_aspect, action_aspect};
692         const int safe_len = ARRAY_SIZE(safe_areas);
693
694         for (int i = 0; i < safe_len; i++) {
695                 if (safe_areas[i][0] || safe_areas[i][1]) {
696                         float margin_x = safe_areas[i][0] * size_x_half;
697                         float margin_y = safe_areas[i][1] * size_y_half;
698
699                         float minx = x1 + margin_x;
700                         float miny = y1 + margin_y;
701                         float maxx = x2 - margin_x;
702                         float maxy = y2 - margin_y;
703
704                         imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
705                 }
706         }
707 }
708
709
710 static void draw_scope_end(const rctf *rect, GLint *scissor)
711 {
712         /* restore scissortest */
713         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
714
715         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
716
717         /* outline */
718         UI_draw_roundbox_corner_set(UI_CNR_ALL);
719         float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
720         UI_draw_roundbox_4fv(false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color);
721 }
722
723 static void histogram_draw_one(
724         float r, float g, float b, float alpha,
725         float x, float y, float w, float h, const float *data, int res, const bool is_line,
726         unsigned int pos_attrib)
727 {
728         float color[4] = {r, g, b, alpha};
729
730         /* that can happen */
731         if (res == 0)
732                 return;
733
734         glEnable(GL_LINE_SMOOTH);
735         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
736
737         immUniformColor4fv(color);
738
739         if (is_line) {
740                 /* curve outline */
741                 glLineWidth(1.5);
742
743                 immBegin(GWN_PRIM_LINE_STRIP, res);
744                 for (int i = 0; i < res; i++) {
745                         float x2 = x + i * (w / (float)res);
746                         immVertex2f(pos_attrib, x2, y + (data[i] * h));
747                 }
748                 immEnd();
749         }
750         else {
751                 /* under the curve */
752                 immBegin(GWN_PRIM_TRI_STRIP, res * 2);
753                 immVertex2f(pos_attrib, x, y);
754                 immVertex2f(pos_attrib, x, y + (data[0] * h));
755                 for (int i = 1; i < res; i++) {
756                         float x2 = x + i * (w / (float)res);
757                         immVertex2f(pos_attrib, x2, y + (data[i] * h));
758                         immVertex2f(pos_attrib, x2, y);
759                 }
760                 immEnd();
761
762                 /* curve outline */
763                 immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
764
765                 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
766                 immBegin(GWN_PRIM_LINE_STRIP, res);
767                 for (int i = 0; i < res; i++) {
768                         float x2 = x + i * (w / (float)res);
769                         immVertex2f(pos_attrib, x2, y + (data[i] * h));
770                 }
771                 immEnd();
772         }
773
774         glDisable(GL_LINE_SMOOTH);
775 }
776
777 #define HISTOGRAM_TOT_GRID_LINES 4
778
779 void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
780 {
781         Histogram *hist = (Histogram *)but->poin;
782         int res = hist->x_resolution;
783         const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0;
784
785         rctf rect = {
786                 .xmin = (float)recti->xmin + 1,
787                 .xmax = (float)recti->xmax - 1,
788                 .ymin = (float)recti->ymin + 1,
789                 .ymax = (float)recti->ymax - 1
790         };
791
792         float w = BLI_rctf_size_x(&rect);
793         float h = BLI_rctf_size_y(&rect) * hist->ymax;
794
795         glEnable(GL_BLEND);
796         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
797
798         float color[4];
799         UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
800         UI_draw_roundbox_corner_set(UI_CNR_ALL);
801         UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
802
803         /* need scissor test, histogram can draw outside of boundary */
804         GLint scissor[4];
805         glGetIntegerv(GL_SCISSOR_BOX, scissor);
806         glScissor((rect.xmin - 1),
807                   (rect.ymin - 1),
808                   (rect.xmax + 1) - (rect.xmin - 1),
809                   (rect.ymax + 1) - (rect.ymin - 1));
810
811         Gwn_VertFormat *format = immVertexFormat();
812         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
813
814         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
815
816         immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
817         /* draw grid lines here */
818         for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) {
819                 const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES;
820
821                 /* so we can tell the 1.0 color point */
822                 if (i == HISTOGRAM_TOT_GRID_LINES) {
823                         immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
824                 }
825
826                 immBegin(GWN_PRIM_LINES, 4);
827
828                 immVertex2f(pos, rect.xmin, rect.ymin + fac * h);
829                 immVertex2f(pos, rect.xmax, rect.ymin + fac * h);
830
831                 immVertex2f(pos, rect.xmin + fac * w, rect.ymin);
832                 immVertex2f(pos, rect.xmin + fac * w, rect.ymax);
833
834                 immEnd();
835         }
836
837         if (hist->mode == HISTO_MODE_LUMA) {
838                 histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos);
839         }
840         else if (hist->mode == HISTO_MODE_ALPHA) {
841                 histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos);
842         }
843         else {
844                 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R)
845                         histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos);
846                 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G)
847                         histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos);
848                 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B)
849                         histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos);
850         }
851
852         immUnbindProgram();
853
854         /* outline */
855         draw_scope_end(&rect, scissor);
856 }
857
858 #undef HISTOGRAM_TOT_GRID_LINES
859
860 static void waveform_draw_one(float *waveform, int nbr, const float col[3])
861 {
862         Gwn_VertFormat format = {0};
863         unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
864
865         Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
866         GWN_vertbuf_data_alloc(vbo, nbr);
867
868         GWN_vertbuf_attr_fill(vbo, pos_id, waveform);
869
870         /* TODO store the Gwn_Batch inside the scope */
871         Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
872         GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
873         GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
874         GWN_batch_draw(batch);
875
876         GWN_batch_discard(batch);
877 }
878
879 void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
880 {
881         Scopes *scopes = (Scopes *)but->poin;
882         GLint scissor[4];
883         float colors[3][3];
884         float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}};
885         float colors_alpha[3][3], colorsycc_alpha[3][3]; /* colors  pre multiplied by alpha for speed up */
886         float min, max;
887
888         if (scopes == NULL) return;
889
890         rctf rect = {
891                 .xmin = (float)recti->xmin + 1,
892                 .xmax = (float)recti->xmax - 1,
893                 .ymin = (float)recti->ymin + 1,
894                 .ymax = (float)recti->ymax - 1
895         };
896
897         if (scopes->wavefrm_yfac < 0.5f)
898                 scopes->wavefrm_yfac = 0.98f;
899         float w = BLI_rctf_size_x(&rect) - 7;
900         float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
901         float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f;
902         float w3 = w / 3.0f;
903
904         /* log scale for alpha */
905         float alpha = scopes->wavefrm_alpha * scopes->wavefrm_alpha;
906
907         unit_m3(colors);
908
909         for (int c = 0; c < 3; c++) {
910                 for (int i = 0; i < 3; i++) {
911                         colors_alpha[c][i] = colors[c][i] * alpha;
912                         colorsycc_alpha[c][i] = colorsycc[c][i] * alpha;
913                 }
914         }
915
916         /* Flush text cache before changing scissors. */
917         BLF_batch_draw_flush();
918
919         glEnable(GL_BLEND);
920         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
921
922         float color[4];
923         UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
924         UI_draw_roundbox_corner_set(UI_CNR_ALL);
925         UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
926
927         /* need scissor test, waveform can draw outside of boundary */
928         glGetIntegerv(GL_SCISSOR_BOX, scissor);
929         glScissor((rect.xmin - 1),
930                   (rect.ymin - 1),
931                   (rect.xmax + 1) - (rect.xmin - 1),
932                   (rect.ymax + 1) - (rect.ymin - 1));
933
934         /* draw scale numbers first before binding any shader */
935         for (int i = 0; i < 6; i++) {
936                 char str[4];
937                 BLI_snprintf(str, sizeof(str), "%-3d", i * 20);
938                 str[3] = '\0';
939                 BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f);
940                 BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1);
941         }
942
943         /* Flush text cache before drawing things on top. */
944         BLF_batch_draw_flush();
945
946         glEnable(GL_BLEND);
947         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
948
949         Gwn_VertFormat *format = immVertexFormat();
950         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
951
952         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
953
954         immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
955
956         /* draw grid lines here */
957         immBegin(GWN_PRIM_LINES, 12);
958
959         for (int i = 0; i < 6; i++) {
960                 immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h);
961                 immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h);
962         }
963
964         immEnd();
965
966         /* 3 vertical separation */
967         if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
968                 immBegin(GWN_PRIM_LINES, 4);
969
970                 for (int i = 1; i < 3; i++) {
971                         immVertex2f(pos, rect.xmin + i * w3, rect.ymin);
972                         immVertex2f(pos, rect.xmin + i * w3, rect.ymax);
973                 }
974
975                 immEnd();
976         }
977
978         /* separate min max zone on the right */
979         immBegin(GWN_PRIM_LINES, 2);
980         immVertex2f(pos, rect.xmin + w, rect.ymin);
981         immVertex2f(pos, rect.xmin + w, rect.ymax);
982         immEnd();
983
984         /* 16-235-240 level in case of ITU-R BT601/709 */
985         immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
986         if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
987                 immBegin(GWN_PRIM_LINES, 8);
988
989                 immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f);
990                 immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
991
992                 immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f);
993                 immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
994
995                 immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f);
996                 immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
997
998                 immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f);
999                 immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
1000
1001                 immEnd();
1002         }
1003         /* 7.5 IRE black point level for NTSC */
1004         if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
1005                 immBegin(GWN_PRIM_LINES, 2);
1006                 immVertex2f(pos, rect.xmin, yofs + h * 0.075f);
1007                 immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f);
1008                 immEnd();
1009         }
1010
1011         if (scopes->ok && scopes->waveform_1 != NULL) {
1012                 glBlendFunc(GL_ONE, GL_ONE);
1013                 glPointSize(1.0);
1014
1015                 /* LUMA (1 channel) */
1016                 if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
1017                         float col[3] = {alpha, alpha, alpha};
1018
1019                         gpuPushMatrix();
1020                         gpuTranslate2f(rect.xmin, yofs);
1021                         gpuScale2f(w, h);
1022
1023                         waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
1024
1025                         gpuPopMatrix();
1026
1027                         /* min max */
1028                         immUniformColor3f(0.5f, 0.5f, 0.5f);
1029                         min = yofs + scopes->minmax[0][0] * h;
1030                         max = yofs + scopes->minmax[0][1] * h;
1031                         CLAMP(min, rect.ymin, rect.ymax);
1032                         CLAMP(max, rect.ymin, rect.ymax);
1033
1034                         immBegin(GWN_PRIM_LINES, 2);
1035                         immVertex2f(pos, rect.xmax - 3, min);
1036                         immVertex2f(pos, rect.xmax - 3, max);
1037                         immEnd();
1038                 }
1039                 /* RGB (3 channel) */
1040                 else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
1041                         gpuPushMatrix();
1042                         gpuTranslate2f(rect.xmin, yofs);
1043                         gpuScale2f(w, h);
1044
1045                         waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]);
1046                         waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]);
1047                         waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]);
1048
1049                         gpuPopMatrix();
1050                 }
1051                 /* PARADE / YCC (3 channels) */
1052                 else if (ELEM(scopes->wavefrm_mode,
1053                               SCOPES_WAVEFRM_RGB_PARADE,
1054                               SCOPES_WAVEFRM_YCC_601,
1055                               SCOPES_WAVEFRM_YCC_709,
1056                               SCOPES_WAVEFRM_YCC_JPEG
1057                               ))
1058                 {
1059                         int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
1060
1061                         gpuPushMatrix();
1062                         gpuTranslate2f(rect.xmin, yofs);
1063                         gpuScale2f(w3, h);
1064
1065                         waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
1066
1067                         gpuTranslate2f(1.0f, 0.0f);
1068                         waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
1069
1070                         gpuTranslate2f(1.0f, 0.0f);
1071                         waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
1072
1073                         gpuPopMatrix();
1074                 }
1075
1076                 /* min max */
1077                 if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) {
1078                         for (int c = 0; c < 3; c++) {
1079                                 if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB))
1080                                         immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
1081                                 else
1082                                         immUniformColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
1083                                 min = yofs + scopes->minmax[c][0] * h;
1084                                 max = yofs + scopes->minmax[c][1] * h;
1085                                 CLAMP(min, rect.ymin, rect.ymax);
1086                                 CLAMP(max, rect.ymin, rect.ymax);
1087
1088                                 immBegin(GWN_PRIM_LINES, 2);
1089                                 immVertex2f(pos, rect.xmin + w + 2 + c * 2, min);
1090                                 immVertex2f(pos, rect.xmin + w + 2 + c * 2, max);
1091                                 immEnd();
1092                         }
1093                 }
1094         }
1095
1096         immUnbindProgram();
1097
1098         /* outline */
1099         draw_scope_end(&rect, scissor);
1100
1101         glDisable(GL_BLEND);
1102 }
1103
1104 static float polar_to_x(float center, float diam, float ampli, float angle)
1105 {
1106         return center + diam * ampli * cosf(angle);
1107 }
1108
1109 static float polar_to_y(float center, float diam, float ampli, float angle)
1110 {
1111         return center + diam * ampli * sinf(angle);
1112 }
1113
1114 static void vectorscope_draw_target(unsigned int pos, float centerx, float centery, float diam, const float colf[3])
1115 {
1116         float y, u, v;
1117         float tangle = 0.0f, tampli;
1118         float dangle, dampli, dangle2, dampli2;
1119
1120         rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v, BLI_YUV_ITU_BT709);
1121         if (u > 0 && v >= 0) tangle = atanf(v / u);
1122         else if (u > 0 && v < 0) tangle = atanf(v / u) + 2.0f * (float)M_PI;
1123         else if (u < 0) tangle = atanf(v / u) + (float)M_PI;
1124         else if (u == 0 && v > 0.0f) tangle = M_PI_2;
1125         else if (u == 0 && v < 0.0f) tangle = -M_PI_2;
1126         tampli = sqrtf(u * u + v * v);
1127
1128         /* small target vary by 2.5 degree and 2.5 IRE unit */
1129         immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
1130         dangle = DEG2RADF(2.5f);
1131         dampli = 2.5f / 200.0f;
1132         immBegin(GWN_PRIM_LINE_LOOP, 4);
1133         immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
1134         immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
1135         immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
1136         immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
1137         immEnd();
1138         /* big target vary by 10 degree and 20% amplitude */
1139         immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
1140         dangle = DEG2RADF(10.0f);
1141         dampli = 0.2f * tampli;
1142         dangle2 = DEG2RADF(5.0f);
1143         dampli2 = 0.5f * dampli;
1144         immBegin(GWN_PRIM_LINE_STRIP, 3);
1145         immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
1146         immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle), polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
1147         immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
1148         immEnd();
1149         immBegin(GWN_PRIM_LINE_STRIP, 3);
1150         immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
1151         immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle), polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
1152         immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2), polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
1153         immEnd();
1154         immBegin(GWN_PRIM_LINE_STRIP, 3);
1155         immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle), polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
1156         immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle), polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
1157         immVertex2f(pos, polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
1158         immEnd();
1159         immBegin(GWN_PRIM_LINE_STRIP, 3);
1160         immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle), polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
1161         immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle), polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
1162         immVertex2f(pos, polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2), polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
1163         immEnd();
1164 }
1165
1166 void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
1167 {
1168         const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
1169         Scopes *scopes = (Scopes *)but->poin;
1170
1171         const float colors[6][3] = {
1172             {0.75, 0.0, 0.0},  {0.75, 0.75, 0.0}, {0.0, 0.75, 0.0},
1173             {0.0, 0.75, 0.75}, {0.0, 0.0, 0.75},  {0.75, 0.0, 0.75}};
1174
1175         rctf rect = {
1176                 .xmin = (float)recti->xmin + 1,
1177                 .xmax = (float)recti->xmax - 1,
1178                 .ymin = (float)recti->ymin + 1,
1179                 .ymax = (float)recti->ymax - 1
1180         };
1181
1182         float w = BLI_rctf_size_x(&rect);
1183         float h = BLI_rctf_size_y(&rect);
1184         float centerx = rect.xmin + w * 0.5f;
1185         float centery = rect.ymin + h * 0.5f;
1186         float diam = (w < h) ? w : h;
1187
1188         float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
1189
1190         glEnable(GL_BLEND);
1191         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1192
1193         float color[4];
1194         UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
1195         UI_draw_roundbox_corner_set(UI_CNR_ALL);
1196         UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
1197
1198         /* need scissor test, hvectorscope can draw outside of boundary */
1199         GLint scissor[4];
1200         glGetIntegerv(GL_SCISSOR_BOX, scissor);
1201         glScissor((rect.xmin - 1),
1202                   (rect.ymin - 1),
1203                   (rect.xmax + 1) - (rect.xmin - 1),
1204                   (rect.ymax + 1) - (rect.ymin - 1));
1205
1206         Gwn_VertFormat *format = immVertexFormat();
1207         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1208
1209         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1210
1211         immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
1212         /* draw grid elements */
1213         /* cross */
1214         immBegin(GWN_PRIM_LINES, 4);
1215
1216         immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery);
1217         immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery);
1218
1219         immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5);
1220         immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5);
1221
1222         immEnd();
1223
1224         /* circles */
1225         for (int j = 0; j < 5; j++) {
1226                 const int increment = 15;
1227                 immBegin(GWN_PRIM_LINE_LOOP, (int)(360 / increment));
1228                 for (int i = 0; i <= 360 - increment; i += increment) {
1229                         const float a = DEG2RADF((float)i);
1230                         const float r = (j + 1) * 0.1f;
1231                         immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
1232                 }
1233                 immEnd();
1234         }
1235         /* skin tone line */
1236         immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
1237
1238         immBegin(GWN_PRIM_LINES, 2);
1239         immVertex2f(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad));
1240         immVertex2f(pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
1241         immEnd();
1242
1243         /* saturation points */
1244         for (int i = 0; i < 6; i++)
1245                 vectorscope_draw_target(pos, centerx, centery, diam, colors[i]);
1246
1247         if (scopes->ok && scopes->vecscope != NULL) {
1248                 /* pixel point cloud */
1249                 float col[3] = {alpha, alpha, alpha};
1250
1251                 glBlendFunc(GL_ONE, GL_ONE);
1252                 glPointSize(1.0);
1253
1254                 gpuPushMatrix();
1255                 gpuTranslate2f(centerx, centery);
1256                 gpuScaleUniform(diam);
1257
1258                 waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col);
1259
1260                 gpuPopMatrix();
1261         }
1262
1263         immUnbindProgram();
1264
1265         /* outline */
1266         draw_scope_end(&rect, scissor);
1267
1268         glDisable(GL_BLEND);
1269 }
1270
1271 static void ui_draw_colorband_handle_tri_hlight(unsigned int pos, float x1, float y1, float halfwidth, float height)
1272 {
1273         glEnable(GL_LINE_SMOOTH);
1274
1275         immBegin(GWN_PRIM_LINE_STRIP, 3);
1276         immVertex2f(pos, x1 + halfwidth, y1);
1277         immVertex2f(pos, x1, y1 + height);
1278         immVertex2f(pos, x1 - halfwidth, y1);
1279         immEnd();
1280
1281         glDisable(GL_LINE_SMOOTH);
1282 }
1283
1284 static void ui_draw_colorband_handle_tri(unsigned int pos, float x1, float y1, float halfwidth, float height, bool fill)
1285 {
1286         glEnable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
1287
1288         immBegin(fill ? GWN_PRIM_TRIS : GWN_PRIM_LINE_LOOP, 3);
1289         immVertex2f(pos, x1 + halfwidth, y1);
1290         immVertex2f(pos, x1, y1 + height);
1291         immVertex2f(pos, x1 - halfwidth, y1);
1292         immEnd();
1293
1294         glDisable(fill ? GL_POLYGON_SMOOTH : GL_LINE_SMOOTH);
1295 }
1296
1297 static void ui_draw_colorband_handle_box(unsigned int pos, float x1, float y1, float x2, float y2, bool fill)
1298 {
1299         immBegin(fill ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4);
1300         immVertex2f(pos, x1, y1);
1301         immVertex2f(pos, x1, y2);
1302         immVertex2f(pos, x2, y2);
1303         immVertex2f(pos, x2, y1);
1304         immEnd();
1305 }
1306
1307 static void ui_draw_colorband_handle(
1308         uint shdr_pos, const rcti *rect, float x,
1309         const float rgb[3], struct ColorManagedDisplay *display,
1310         bool active)
1311 {
1312         const float sizey = BLI_rcti_size_y(rect);
1313         const float min_width = 3.0f;
1314         float colf[3] = {UNPACK3(rgb)};
1315
1316         float half_width = floorf(sizey / 3.5f);
1317         float height = half_width * 1.4f;
1318
1319         float y1 = rect->ymin + (sizey * 0.16f);
1320         float y2 = rect->ymax;
1321
1322         /* align to pixels */
1323         x  = floorf(x  + 0.5f);
1324         y1 = floorf(y1 + 0.5f);
1325
1326         if (active || half_width < min_width) {
1327                 immUnbindProgram();
1328
1329                 immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
1330
1331                 float viewport_size[4];
1332                 glGetFloatv(GL_VIEWPORT, viewport_size);
1333                 immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
1334
1335                 immUniform1i("num_colors", 2);  /* "advanced" mode */
1336                 immUniformArray4fv("colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
1337                 immUniform1f("dash_width", active ? 4.0f : 2.0f);
1338
1339                 immBegin(GWN_PRIM_LINES, 2);
1340                 immVertex2f(shdr_pos, x, y1);
1341                 immVertex2f(shdr_pos, x, y2);
1342                 immEnd();
1343
1344                 immUnbindProgram();
1345
1346                 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1347
1348                 /* hide handles when zoomed out too far */
1349                 if (half_width < min_width) {
1350                         return;
1351                 }
1352         }
1353
1354         /* shift handle down */
1355         y1 -= half_width;
1356
1357         immUniformColor3ub(0, 0, 0);
1358         ui_draw_colorband_handle_box(shdr_pos, x - half_width, y1 - 1, x + half_width, y1 + height, false);
1359
1360         /* draw all triangles blended */
1361         glEnable(GL_BLEND);
1362
1363         ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
1364
1365         if (active)
1366                 immUniformColor3ub(196, 196, 196);
1367         else
1368                 immUniformColor3ub(96, 96, 96);
1369         ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
1370
1371         if (active)
1372                 immUniformColor3ub(255, 255, 255);
1373         else
1374                 immUniformColor3ub(128, 128, 128);
1375         ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height - 1, (half_width - 1), (half_width - 1));
1376
1377         immUniformColor3ub(0, 0, 0);
1378         ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height, half_width, half_width);
1379
1380         glDisable(GL_BLEND);
1381
1382         immUniformColor3ub(128, 128, 128);
1383         ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
1384
1385         if (display) {
1386                 IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1387         }
1388
1389         immUniformColor3fv(colf);
1390         ui_draw_colorband_handle_box(shdr_pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
1391 }
1392
1393 void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
1394 {
1395         struct ColorManagedDisplay *display = NULL;
1396         unsigned int position, color;
1397
1398         ColorBand *coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin);
1399         if (coba == NULL) return;
1400
1401         if (but->block->color_profile)
1402                 display = ui_block_cm_display_get(but->block);
1403
1404         float x1 = rect->xmin;
1405         float sizex = rect->xmax - x1;
1406         float sizey = BLI_rcti_size_y(rect);
1407         float sizey_solid = sizey * 0.25f;
1408         float y1 = rect->ymin;
1409
1410         Gwn_VertFormat *format = immVertexFormat();
1411         position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1412         immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
1413
1414         /* Drawing the checkerboard. */
1415         immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f);
1416         immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f);
1417         immUniform1i("size", 8);
1418         immRectf(position, x1, y1, x1 + sizex, rect->ymax);
1419         immUnbindProgram();
1420
1421         /* New format */
1422         format = immVertexFormat();
1423         position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1424         color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
1425         immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
1426
1427         /* layer: color ramp */
1428         glEnable(GL_BLEND);
1429
1430         CBData *cbd = coba->data;
1431
1432         float v1[2], v2[2];
1433         float colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */
1434
1435         v1[1] = y1 + sizey_solid;
1436         v2[1] = rect->ymax;
1437
1438         immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2);
1439         for (int a = 0; a <= sizex; a++) {
1440                 float pos = ((float)a) / sizex;
1441                 BKE_colorband_evaluate(coba, pos, colf);
1442                 if (display)
1443                         IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1444
1445                 v1[0] = v2[0] = x1 + a;
1446
1447                 immAttrib4fv(color, colf);
1448                 immVertex2fv(position, v1);
1449                 immVertex2fv(position, v2);
1450         }
1451         immEnd();
1452
1453         /* layer: color ramp without alpha for reference when manipulating ramp properties */
1454         v1[1] = y1;
1455         v2[1] = y1 + sizey_solid;
1456
1457         immBegin(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2);
1458         for (int a = 0; a <= sizex; a++) {
1459                 float pos = ((float)a) / sizex;
1460                 BKE_colorband_evaluate(coba, pos, colf);
1461                 if (display)
1462                         IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1463
1464                 v1[0] = v2[0] = x1 + a;
1465
1466                 immAttrib4f(color, colf[0], colf[1], colf[2], 1.0f);
1467                 immVertex2fv(position, v1);
1468                 immVertex2fv(position, v2);
1469         }
1470         immEnd();
1471
1472         immUnbindProgram();
1473
1474         glDisable(GL_BLEND);
1475
1476         /* New format */
1477         format = immVertexFormat();
1478         position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1479         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1480
1481         /* layer: box outline */
1482         immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1483         imm_draw_box_wire_2d(position, x1, y1, x1 + sizex, rect->ymax);
1484
1485         /* layer: box outline */
1486         glEnable(GL_BLEND);
1487         immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
1488
1489         immBegin(GWN_PRIM_LINES, 2);
1490         immVertex2f(position, x1, y1);
1491         immVertex2f(position, x1 + sizex, y1);
1492         immEnd();
1493
1494         immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
1495
1496         immBegin(GWN_PRIM_LINES, 2);
1497         immVertex2f(position, x1, y1 - 1);
1498         immVertex2f(position, x1 + sizex, y1 - 1);
1499         immEnd();
1500
1501         glDisable(GL_BLEND);
1502
1503         /* layer: draw handles */
1504         for (int a = 0; a < coba->tot; a++, cbd++) {
1505                 if (a != coba->cur) {
1506                         float pos = x1 + cbd->pos * (sizex - 1) + 1;
1507                         ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, false);
1508                 }
1509         }
1510
1511         /* layer: active handle */
1512         if (coba->tot != 0) {
1513                 cbd = &coba->data[coba->cur];
1514                 float pos = x1 + cbd->pos * (sizex - 1) + 1;
1515                 ui_draw_colorband_handle(position, rect, pos, &cbd->r, display, true);
1516         }
1517
1518         immUnbindProgram();
1519 }
1520
1521 void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
1522 {
1523         /* sphere color */
1524         float diffuse[3] = {1.0f, 1.0f, 1.0f};
1525         float light[3];
1526         float size;
1527
1528         /* backdrop */
1529         UI_draw_roundbox_corner_set(UI_CNR_ALL);
1530         UI_draw_roundbox_3ubAlpha(true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255);
1531
1532         glCullFace(GL_BACK);
1533         glEnable(GL_CULL_FACE);
1534
1535         /* setup lights */
1536         ui_but_v3_get(but, light);
1537
1538         /* transform to button */
1539         gpuPushMatrix();
1540
1541         if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect))
1542                 size = 0.5f * BLI_rcti_size_x(rect);
1543         else
1544                 size = 0.5f * BLI_rcti_size_y(rect);
1545
1546         gpuTranslate2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect));
1547         gpuScaleUniform(size);
1548
1549         Gwn_Batch *sphere = GPU_batch_preset_sphere(2);
1550         GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
1551         GWN_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
1552         GWN_batch_uniform_3fv(sphere, "light", light);
1553         GWN_batch_draw(sphere);
1554
1555         /* restore */
1556         glDisable(GL_CULL_FACE);
1557
1558         /* AA circle */
1559         Gwn_VertFormat *format = immVertexFormat();
1560         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1561         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1562         immUniformColor3ubv((unsigned char *)wcol->inner);
1563
1564         glEnable(GL_BLEND);
1565         glEnable(GL_LINE_SMOOTH);
1566         imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32);
1567         glDisable(GL_BLEND);
1568         glDisable(GL_LINE_SMOOTH);
1569
1570         /* matrix after circle */
1571         gpuPopMatrix();
1572
1573         immUnbindProgram();
1574 }
1575
1576 static void ui_draw_but_curve_grid(unsigned int pos, const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
1577 {
1578         float dx = step * zoomx;
1579         float fx = rect->xmin + zoomx * (-offsx);
1580         if (fx > rect->xmin) fx -= dx * (floorf(fx - rect->xmin));
1581
1582         float dy = step * zoomy;
1583         float fy = rect->ymin + zoomy * (-offsy);
1584         if (fy > rect->ymin) fy -= dy * (floorf(fy - rect->ymin));
1585
1586         float line_count = floorf((rect->xmax - fx) / dx) + 1.0f +
1587                            floorf((rect->ymax - fy) / dy) + 1.0f;
1588
1589         immBegin(GWN_PRIM_LINES, (int)line_count * 2);
1590         while (fx < rect->xmax) {
1591                 immVertex2f(pos, fx, rect->ymin);
1592                 immVertex2f(pos, fx, rect->ymax);
1593                 fx += dx;
1594         }
1595         while (fy < rect->ymax) {
1596                 immVertex2f(pos, rect->xmin, fy);
1597                 immVertex2f(pos, rect->xmax, fy);
1598                 fy += dy;
1599         }
1600         immEnd();
1601
1602 }
1603
1604 static void gl_shaded_color(unsigned char *col, int shade)
1605 {
1606         immUniformColor3ub(col[0] - shade > 0 ? col[0] - shade : 0,
1607                            col[1] - shade > 0 ? col[1] - shade : 0,
1608                            col[2] - shade > 0 ? col[2] - shade : 0);
1609 }
1610
1611 void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti *rect)
1612 {
1613         CurveMapping *cumap;
1614
1615         if (but->editcumap) {
1616                 cumap = but->editcumap;
1617         }
1618         else {
1619                 cumap = (CurveMapping *)but->poin;
1620         }
1621
1622         CurveMap *cuma = &cumap->cm[cumap->cur];
1623
1624         /* need scissor test, curve can draw outside of boundary */
1625         GLint scissor[4];
1626         glGetIntegerv(GL_SCISSOR_BOX, scissor);
1627         rcti scissor_new = {
1628                 .xmin = rect->xmin,
1629                 .ymin = rect->ymin,
1630                 .xmax = rect->xmax,
1631                 .ymax = rect->ymax
1632         };
1633         rcti scissor_region = {0, ar->winx, 0, ar->winy};
1634         BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
1635         glScissor(scissor_new.xmin,
1636                   scissor_new.ymin,
1637                   BLI_rcti_size_x(&scissor_new),
1638                   BLI_rcti_size_y(&scissor_new));
1639
1640         /* calculate offset and zoom */
1641         float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&cumap->curr);
1642         float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&cumap->curr);
1643         float offsx = cumap->curr.xmin - (1.0f / zoomx);
1644         float offsy = cumap->curr.ymin - (1.0f / zoomy);
1645
1646         /* Do this first to not mess imm context */
1647         if (but->a1 == UI_GRAD_H) {
1648                 /* magic trigger for curve backgrounds */
1649                 float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */
1650
1651                 rcti grid = {
1652                         .xmin = rect->xmin + zoomx * (-offsx),
1653                         .xmax = grid.xmin + zoomx,
1654                         .ymin = rect->ymin + zoomy * (-offsy),
1655                         .ymax = grid.ymin + zoomy
1656                 };
1657
1658                 ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);
1659         }
1660
1661         glLineWidth(1.0f);
1662
1663         Gwn_VertFormat *format = immVertexFormat();
1664         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1665         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1666
1667         /* backdrop */
1668         if (but->a1 == UI_GRAD_H) {
1669                 /* grid, hsv uses different grid */
1670                 glEnable(GL_BLEND);
1671                 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1672                 immUniformColor4ub(0, 0, 0, 48);
1673                 ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
1674                 glDisable(GL_BLEND);
1675         }
1676         else {
1677                 if (cumap->flag & CUMA_DO_CLIP) {
1678                         gl_shaded_color((unsigned char *)wcol->inner, -20);
1679                         immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1680                         immUniformColor3ubv((unsigned char *)wcol->inner);
1681                         immRectf(pos, rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
1682                                       rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
1683                                       rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
1684                                       rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
1685                 }
1686                 else {
1687                         immUniformColor3ubv((unsigned char *)wcol->inner);
1688                         immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1689                 }
1690
1691                 /* grid, every 0.25 step */
1692                 gl_shaded_color((unsigned char *)wcol->inner, -16);
1693                 ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f);
1694                 /* grid, every 1.0 step */
1695                 gl_shaded_color((unsigned char *)wcol->inner, -24);
1696                 ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
1697                 /* axes */
1698                 gl_shaded_color((unsigned char *)wcol->inner, -50);
1699                 immBegin(GWN_PRIM_LINES, 4);
1700                 immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy));
1701                 immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy));
1702                 immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin);
1703                 immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax);
1704                 immEnd();
1705         }
1706
1707         /* cfra option */
1708         /* XXX 2.48 */
1709 #if 0
1710         if (cumap->flag & CUMA_DRAW_CFRA) {
1711                 immUniformColor3ub(0x60, 0xc0, 0x40);
1712                 immBegin(GWN_PRIM_LINES, 2);
1713                 immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
1714                 immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
1715                 immEnd();
1716         }
1717 #endif
1718         /* sample option */
1719
1720         if (cumap->flag & CUMA_DRAW_SAMPLE) {
1721                 immBegin(GWN_PRIM_LINES, 2); /* will draw one of the following 3 lines */
1722                 if (but->a1 == UI_GRAD_H) {
1723                         float tsample[3];
1724                         float hsv[3];
1725                         linearrgb_to_srgb_v3_v3(tsample, cumap->sample);
1726                         rgb_to_hsv_v(tsample, hsv);
1727                         immUniformColor3ub(240, 240, 240);
1728
1729                         immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
1730                         immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
1731                 }
1732                 else if (cumap->cur == 3) {
1733                         float lum = IMB_colormanagement_get_luminance(cumap->sample);
1734                         immUniformColor3ub(240, 240, 240);
1735
1736                         immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin);
1737                         immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax);
1738                 }
1739                 else {
1740                         if (cumap->cur == 0)
1741                                 immUniformColor3ub(240, 100, 100);
1742                         else if (cumap->cur == 1)
1743                                 immUniformColor3ub(100, 240, 100);
1744                         else
1745                                 immUniformColor3ub(100, 100, 240);
1746
1747                         immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
1748                         immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
1749                 }
1750                 immEnd();
1751         }
1752
1753         /* the curve */
1754         immUniformColor3ubv((unsigned char *)wcol->item);
1755         glEnable(GL_LINE_SMOOTH);
1756         glEnable(GL_BLEND);
1757         immBegin(GWN_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
1758
1759         if (cuma->table == NULL)
1760                 curvemapping_changed(cumap, false);
1761
1762         CurveMapPoint *cmp = cuma->table;
1763
1764         /* first point */
1765         if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
1766                 immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (cmp[0].y - offsy));
1767         }
1768         else {
1769                 float fx = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]);
1770                 float fy = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]);
1771                 immVertex2f(pos, fx, fy);
1772         }
1773         for (int a = 0; a <= CM_TABLE; a++) {
1774                 float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
1775                 float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
1776                 immVertex2f(pos, fx, fy);
1777         }
1778         /* last point */
1779         if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
1780                 immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy));
1781         }
1782         else {
1783                 float fx = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]);
1784                 float fy = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]);
1785                 immVertex2f(pos, fx, fy);
1786         }
1787         immEnd();
1788         glDisable(GL_LINE_SMOOTH);
1789         glDisable(GL_BLEND);
1790         immUnbindProgram();
1791
1792         /* the points, use aspect to make them visible on edges */
1793         format = immVertexFormat();
1794         pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1795         unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
1796         immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
1797
1798         cmp = cuma->curve;
1799         glPointSize(3.0f);
1800         immBegin(GWN_PRIM_POINTS, cuma->totpoint);
1801         for (int a = 0; a < cuma->totpoint; a++) {
1802                 float color[4];
1803                 if (cmp[a].flag & CUMA_SELECT)
1804                         UI_GetThemeColor4fv(TH_TEXT_HI, color);
1805                 else
1806                         UI_GetThemeColor4fv(TH_TEXT, color);
1807                 float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
1808                 float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
1809                 immAttrib4fv(col, color);
1810                 immVertex2f(pos, fx, fy);
1811         }
1812         immEnd();
1813         immUnbindProgram();
1814
1815         /* restore scissortest */
1816         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
1817
1818         /* outline */
1819         format = immVertexFormat();
1820         pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1821         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1822
1823         immUniformColor3ubv((unsigned char *)wcol->outline);
1824         imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1825
1826         immUnbindProgram();
1827 }
1828
1829 void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
1830 {
1831         bool ok = false;
1832         MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
1833
1834         rctf rect = {
1835                 .xmin = (float)recti->xmin + 1,
1836                 .xmax = (float)recti->xmax - 1,
1837                 .ymin = (float)recti->ymin + 1,
1838                 .ymax = (float)recti->ymax - 1
1839         };
1840
1841         int width  = BLI_rctf_size_x(&rect) + 1;
1842         int height = BLI_rctf_size_y(&rect);
1843
1844         glEnable(GL_BLEND);
1845         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1846
1847         /* need scissor test, preview image can draw outside of boundary */
1848         GLint scissor[4];
1849         glGetIntegerv(GL_SCISSOR_BOX, scissor);
1850         glScissor((rect.xmin - 1),
1851                   (rect.ymin - 1),
1852                   (rect.xmax + 1) - (rect.xmin - 1),
1853                   (rect.ymax + 1) - (rect.ymin - 1));
1854
1855         if (scopes->track_disabled) {
1856                 float color[4] = {0.7f, 0.3f, 0.3f, 0.3f};
1857                 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1858                 UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
1859
1860                 ok = true;
1861         }
1862         else if ((scopes->track_search) &&
1863                  ((!scopes->track_preview) ||
1864                   (scopes->track_preview->x != width || scopes->track_preview->y != height)))
1865         {
1866                 if (scopes->track_preview)
1867                         IMB_freeImBuf(scopes->track_preview);
1868
1869                 ImBuf *tmpibuf = BKE_tracking_sample_pattern(scopes->frame_width, scopes->frame_height,
1870                                                              scopes->track_search, scopes->track,
1871                                                              &scopes->undist_marker, true, scopes->use_track_mask,
1872                                                              width, height, scopes->track_pos);
1873                 if (tmpibuf) {
1874                         if (tmpibuf->rect_float)
1875                                 IMB_rect_from_float(tmpibuf);
1876
1877                         if (tmpibuf->rect)
1878                                 scopes->track_preview = tmpibuf;
1879                         else
1880                                 IMB_freeImBuf(tmpibuf);
1881                 }
1882         }
1883
1884         if (!ok && scopes->track_preview) {
1885                 gpuPushMatrix();
1886
1887                 /* draw content of pattern area */
1888                 glScissor(rect.xmin, rect.ymin, scissor[2], scissor[3]);
1889
1890                 if (width > 0 && height > 0) {
1891                         ImBuf *drawibuf = scopes->track_preview;
1892                         float col_sel[4], col_outline[4];
1893
1894                         if (scopes->use_track_mask) {
1895                                 float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
1896                                 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1897                                 UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
1898                         }
1899
1900                         IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
1901                         immDrawPixelsTex(&state, rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, NULL);
1902
1903                         /* draw cross for pixel position */
1904                         gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
1905                         glScissor(rect.xmin,
1906                                   rect.ymin,
1907                                   BLI_rctf_size_x(&rect),
1908                                   BLI_rctf_size_y(&rect));
1909
1910                         Gwn_VertFormat *format = immVertexFormat();
1911                         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
1912                         unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
1913                         immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
1914
1915                         UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel);
1916                         UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline);
1917
1918                         /* Do stipple cross with geometry */
1919                         immBegin(GWN_PRIM_LINES, 7 * 2 * 2);
1920                         float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f};
1921                         for (int axe = 0; axe < 2; ++axe) {
1922                                 for (int i = 0; i < 7; ++i) {
1923                                         float x1 = pos_sel[i] * (1 - axe);
1924                                         float y1 = pos_sel[i] * axe;
1925                                         float x2 = pos_sel[i + 1] * (1 - axe);
1926                                         float y2 = pos_sel[i + 1] * axe;
1927
1928                                         if (i % 2 == 1)
1929                                                 immAttrib4fv(col, col_sel);
1930                                         else
1931                                                 immAttrib4fv(col, col_outline);
1932
1933                                         immVertex2f(pos, x1, y1);
1934                                         immVertex2f(pos, x2, y2);
1935                                 }
1936                         }
1937                         immEnd();
1938
1939                         immUnbindProgram();
1940                 }
1941
1942                 gpuPopMatrix();
1943
1944                 ok = true;
1945         }
1946
1947         if (!ok) {
1948                 float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
1949                 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1950                 UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
1951         }
1952
1953         /* outline */
1954         draw_scope_end(&rect, scissor);
1955
1956         glDisable(GL_BLEND);
1957 }
1958
1959 void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
1960 {
1961         static const float size = 5.0f;
1962
1963         /* 16 values of sin function */
1964         const float si[16] = {
1965             0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
1966             0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
1967             -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
1968             -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
1969         };
1970         /* 16 values of cos function */
1971         const float co[16] = {
1972             1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
1973             -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
1974             -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
1975             0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
1976         };
1977
1978         GLint scissor[4];
1979
1980         /* need scissor test, can draw outside of boundary */
1981         glGetIntegerv(GL_SCISSOR_BOX, scissor);
1982
1983         rcti scissor_new = {
1984                 .xmin = recti->xmin,
1985                 .ymin = recti->ymin,
1986                 .xmax = recti->xmax,
1987                 .ymax = recti->ymax
1988         };
1989
1990         rcti scissor_region = {0, ar->winx, 0, ar->winy};
1991
1992         BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
1993         glScissor(scissor_new.xmin,
1994                   scissor_new.ymin,
1995                   BLI_rcti_size_x(&scissor_new),
1996                   BLI_rcti_size_y(&scissor_new));
1997
1998         float x = 0.5f * (recti->xmin + recti->xmax);
1999         float y = 0.5f * (recti->ymin + recti->ymax);
2000
2001         Gwn_VertFormat *format = immVertexFormat();
2002         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
2003         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
2004         immUniformColor4ubv(but->col);
2005
2006         glEnable(GL_BLEND);
2007         immBegin(GWN_PRIM_TRI_FAN, 16);
2008         for (int a = 0; a < 16; a++)
2009                 immVertex2f(pos, x + size * si[a], y + size * co[a]);
2010         immEnd();
2011
2012         immUniformColor4ub(0, 0, 0, 150);
2013         glLineWidth(1);
2014         glEnable(GL_LINE_SMOOTH);
2015         immBegin(GWN_PRIM_LINE_LOOP, 16);
2016         for (int a = 0; a < 16; a++)
2017                 immVertex2f(pos, x + size * si[a], y + size * co[a]);
2018         immEnd();
2019         glDisable(GL_LINE_SMOOTH);
2020         glDisable(GL_BLEND);
2021
2022         immUnbindProgram();
2023
2024         /* restore scissortest */
2025         glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
2026 }
2027
2028 /* ****************************************************** */
2029
2030 /* TODO: high quality UI drop shadows using GLSL shader and single draw call
2031  * would replace / modify the following 3 functions  - merwin
2032  */
2033
2034 static void ui_shadowbox(unsigned pos, unsigned color, float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
2035 {
2036         /*          v1-_
2037          *          |   -_v2
2038          *          |     |
2039          *          |     |
2040          *          |     |
2041          * v7_______v3____v4
2042          * \        |     /
2043          *  \       |   _v5
2044          *  v8______v6_-
2045          */
2046         const float v1[2] = {maxx,                   maxy - 0.3f * shadsize};
2047         const float v2[2] = {maxx + shadsize,        maxy - 0.75f * shadsize};
2048         const float v3[2] = {maxx,                   miny};
2049         const float v4[2] = {maxx + shadsize,        miny};
2050
2051         const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize};
2052
2053         const float v6[2] = {maxx,                   miny - shadsize};
2054         const float v7[2] = {minx + 0.3f * shadsize, miny};
2055         const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize};
2056
2057         /* right quad */
2058         immAttrib4ub(color, 0, 0, 0, alpha);
2059         immVertex2fv(pos, v3);
2060         immVertex2fv(pos, v1);
2061         immAttrib4ub(color, 0, 0, 0, 0);
2062         immVertex2fv(pos, v2);
2063
2064         immVertex2fv(pos, v2);
2065         immVertex2fv(pos, v4);
2066         immAttrib4ub(color, 0, 0, 0, alpha);
2067         immVertex2fv(pos, v3);
2068
2069         /* corner shape */
2070         /* immAttrib4ub(color, 0, 0, 0, alpha); */  /* Not needed, done above in previous tri */
2071         immVertex2fv(pos, v3);
2072         immAttrib4ub(color, 0, 0, 0, 0);
2073         immVertex2fv(pos, v4);
2074         immVertex2fv(pos, v5);
2075
2076         immVertex2fv(pos, v5);
2077         immVertex2fv(pos, v6);
2078         immAttrib4ub(color, 0, 0, 0, alpha);
2079         immVertex2fv(pos, v3);
2080
2081         /* bottom quad */
2082         /* immAttrib4ub(color, 0, 0, 0, alpha); */  /* Not needed, done above in previous tri */
2083         immVertex2fv(pos, v3);
2084         immAttrib4ub(color, 0, 0, 0, 0);
2085         immVertex2fv(pos, v6);
2086         immVertex2fv(pos, v8);
2087
2088         immVertex2fv(pos, v8);
2089         immAttrib4ub(color, 0, 0, 0, alpha);
2090         immVertex2fv(pos, v7);
2091         immVertex2fv(pos, v3);
2092 }
2093
2094 void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
2095 {
2096         glEnable(GL_BLEND);
2097
2098         Gwn_VertFormat *format = immVertexFormat();
2099         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
2100         unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
2101
2102         immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
2103
2104         immBegin(GWN_PRIM_TRIS, 54);
2105
2106         /* accumulated outline boxes to make shade not linear, is more pleasant */
2107         ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
2108         ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
2109         ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
2110
2111         immEnd();
2112
2113         immUnbindProgram();
2114
2115         glDisable(GL_BLEND);
2116 }
2117
2118
2119 void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
2120 {
2121         float rad;
2122
2123         if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f)
2124                 rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f;
2125         else
2126                 rad = radius;
2127
2128         int a, i = 12;
2129 #if 0
2130         if (select) {
2131                 a = i * aspect; /* same as below */
2132         }
2133         else
2134 #endif
2135         {
2136                 a = i * aspect;
2137         }
2138
2139         glEnable(GL_BLEND);
2140         const float dalpha = alpha * 2.0f / 255.0f;
2141         float calpha = dalpha;
2142         float visibility = 1.0f;
2143         for (; i--;) {
2144                 /* alpha ranges from 2 to 20 or so */
2145 #if 0 /* Old Method (pre 2.8) */
2146                 float color[4] = {0.0f, 0.0f, 0.0f, calpha};
2147                 UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
2148 #endif
2149                 /* Compute final visibility to match old method result. */
2150                 /* TODO we could just find a better fit function inside the shader instead of this. */
2151                 visibility = visibility * (1.0f - calpha);
2152                 calpha += dalpha;
2153         }
2154
2155         uiWidgetBaseParameters widget_params = {
2156                 .recti.xmin = rct->xmin, .recti.ymin = rct->ymin,
2157                 .recti.xmax = rct->xmax, .recti.ymax = rct->ymax - 10.0f,
2158                 .rect.xmin = rct->xmin - a, .rect.ymin = rct->ymin - a,
2159                 .rect.xmax = rct->xmax + a, .rect.ymax = rct->ymax - 10.0f + a,
2160                 .radi = rad,
2161                 .rad = rad + a,
2162                 .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
2163                 .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
2164                 .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
2165                 .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
2166                 .alpha_discard = 1.0f,
2167         };
2168
2169         Gwn_Batch *batch = ui_batch_roundbox_shadow_get();
2170         GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
2171         GWN_batch_uniform_4fv_array(batch, "parameters", 4, (float *)&widget_params);
2172         GWN_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
2173         GWN_batch_draw(batch);
2174
2175         /* outline emphasis */
2176         glEnable(GL_LINE_SMOOTH);
2177         float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
2178         UI_draw_roundbox_4fv(false, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f, color);
2179         glDisable(GL_LINE_SMOOTH);
2180
2181         glDisable(GL_BLEND);
2182 }