1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup edinterface
22 */
23
24 #include <math.h>
25 #include <string.h>
26
27 #include "DNA_color_types.h"
28 #include "DNA_curve_types.h"
29 #include "DNA_curveprofile_types.h"
30 #include "DNA_movieclip_types.h"
31 #include "DNA_screen_types.h"
32
33 #include "BLI_math.h"
34 #include "BLI_polyfill_2d.h"
35 #include "BLI_rect.h"
36 #include "BLI_string.h"
37 #include "BLI_utildefines.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BKE_colorband.h"
42 #include "BKE_colortools.h"
43 #include "BKE_curveprofile.h"
44 #include "BKE_node.h"
45 #include "BKE_tracking.h"
46
47 #include "IMB_colormanagement.h"
48 #include "IMB_imbuf.h"
49 #include "IMB_imbuf_types.h"
50
51 #include "BIF_glutil.h"
52
53 #include "BLF_api.h"
54
55 #include "GPU_batch.h"
56 #include "GPU_batch_presets.h"
57 #include "GPU_immediate.h"
58 #include "GPU_immediate_util.h"
59 #include "GPU_matrix.h"
60 #include "GPU_state.h"
61
62 #include "UI_interface.h"
63
64 /* own include */
65 #include "interface_intern.h"
66
67 static int roundboxtype = UI_CNR_ALL;
68
UI_draw_roundbox_corner_set(int type)69 void UI_draw_roundbox_corner_set(int type)
70 {
71 /* Not sure the roundbox function is the best place to change this
72 * if this is undone, it's not that big a deal, only makes curves edges
73 * square for the */
74 roundboxtype = type;
75 }
76
77 #if 0 /* unused */
78 int UI_draw_roundbox_corner_get(void)
79 {
80 return roundboxtype;
81 }
82 #endif
83
UI_draw_roundbox_3ub_alpha(bool filled,float minx,float miny,float maxx,float maxy,float rad,const uchar col[3],uchar alpha)84 void UI_draw_roundbox_3ub_alpha(bool filled,
85 float minx,
86 float miny,
87 float maxx,
88 float maxy,
89 float rad,
90 const uchar col[3],
91 uchar alpha)
92 {
93 float colv[4];
94 colv[0] = ((float)col[0]) / 255;
95 colv[1] = ((float)col[1]) / 255;
96 colv[2] = ((float)col[2]) / 255;
97 colv[3] = ((float)alpha) / 255;
98 UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
99 }
100
UI_draw_roundbox_3fv_alpha(bool filled,float minx,float miny,float maxx,float maxy,float rad,const float col[3],float alpha)101 void UI_draw_roundbox_3fv_alpha(bool filled,
102 float minx,
103 float miny,
104 float maxx,
105 float maxy,
106 float rad,
107 const float col[3],
108 float alpha)
109 {
110 float colv[4];
111 colv[0] = col[0];
112 colv[1] = col[1];
113 colv[2] = col[2];
114 colv[3] = alpha;
115 UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
116 }
117
UI_draw_roundbox_aa(bool filled,float minx,float miny,float maxx,float maxy,float rad,const float color[4])118 void UI_draw_roundbox_aa(
119 bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4])
120 {
121 uiWidgetBaseParameters widget_params = {
122 .recti.xmin = minx + U.pixelsize,
123 .recti.ymin = miny + U.pixelsize,
124 .recti.xmax = maxx - U.pixelsize,
125 .recti.ymax = maxy - U.pixelsize,
126 .rect.xmin = minx,
127 .rect.ymin = miny,
128 .rect.xmax = maxx,
129 .rect.ymax = maxy,
130 .radi = rad,
131 .rad = rad,
132 .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
133 .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
134 .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
135 .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
136 .color_inner1[0] = filled ? color[0] : 0.0f,
137 .color_inner1[1] = filled ? color[1] : 0.0f,
138 .color_inner1[2] = filled ? color[2] : 0.0f,
139 .color_inner1[3] = filled ? color[3] : 0.0f,
140 .color_inner2[0] = filled ? color[0] : 0.0f,
141 .color_inner2[1] = filled ? color[1] : 0.0f,
142 .color_inner2[2] = filled ? color[2] : 0.0f,
143 .color_inner2[3] = filled ? color[3] : 0.0f,
144 .color_outline[0] = color[0],
145 .color_outline[1] = color[1],
146 .color_outline[2] = color[2],
147 .color_outline[3] = color[3],
148 .alpha_discard = 1.0f,
149 };
150
151 /* XXX this is to emulate previous behavior of semitransparent fills but that's was a side effect
152 * of the previous AA method. Better fix the callers. */
153 if (filled) {
154 widget_params.color_inner1[3] *= 0.65f;
155 widget_params.color_inner2[3] *= 0.65f;
156 widget_params.color_outline[3] *= 0.65f;
157 }
158
159 /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
160 * If it has been scaled, then it's no longer valid. */
161
162 GPUBatch *batch = ui_batch_roundbox_widget_get();
163 GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
164 GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params);
165
166 GPU_blend(GPU_BLEND_ALPHA);
167
168 GPU_batch_draw(batch);
169
170 GPU_blend(GPU_BLEND_NONE);
171 }
172
UI_draw_roundbox_4fv(bool filled,float minx,float miny,float maxx,float maxy,float rad,const float col[4])173 void UI_draw_roundbox_4fv(
174 bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4])
175 {
176 #if 0
177 float vec[7][2] = {
178 {0.195, 0.02},
179 {0.383, 0.067},
180 {0.55, 0.169},
181 {0.707, 0.293},
182 {0.831, 0.45},
183 {0.924, 0.617},
184 {0.98, 0.805},
185 };
186 int a;
187
188 GPUVertFormat *format = immVertexFormat();
189 uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
190
191 /* mult */
192 for (a = 0; a < 7; a++) {
193 mul_v2_fl(vec[a], rad);
194 }
195
196 uint vert_len = 0;
197 vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
198 vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
199 vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
200 vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
201
202 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
203 immUniformColor4fv(col);
204
205 immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_len);
206 /* start with corner right-bottom */
207 if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
208 immVertex2f(pos, maxx - rad, miny);
209 for (a = 0; a < 7; a++) {
210 immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
211 }
212 immVertex2f(pos, maxx, miny + rad);
213 }
214 else {
215 immVertex2f(pos, maxx, miny);
216 }
217
218 /* corner right-top */
219 if (roundboxtype & UI_CNR_TOP_RIGHT) {
220 immVertex2f(pos, maxx, maxy - rad);
221 for (a = 0; a < 7; a++) {
222 immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
223 }
224 immVertex2f(pos, maxx - rad, maxy);
225 }
226 else {
227 immVertex2f(pos, maxx, maxy);
228 }
229
230 /* corner left-top */
231 if (roundboxtype & UI_CNR_TOP_LEFT) {
232 immVertex2f(pos, minx + rad, maxy);
233 for (a = 0; a < 7; a++) {
234 immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
235 }
236 immVertex2f(pos, minx, maxy - rad);
237 }
238 else {
239 immVertex2f(pos, minx, maxy);
240 }
241
242 /* corner left-bottom */
243 if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
244 immVertex2f(pos, minx, miny + rad);
245 for (a = 0; a < 7; a++) {
246 immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
247 }
248 immVertex2f(pos, minx + rad, miny);
249 }
250 else {
251 immVertex2f(pos, minx, miny);
252 }
253
254 immEnd();
255 immUnbindProgram();
256 #endif
257 uiWidgetBaseParameters widget_params = {
258 .recti.xmin = minx + U.pixelsize,
259 .recti.ymin = miny + U.pixelsize,
260 .recti.xmax = maxx - U.pixelsize,
261 .recti.ymax = maxy - U.pixelsize,
262 .rect.xmin = minx,
263 .rect.ymin = miny,
264 .rect.xmax = maxx,
265 .rect.ymax = maxy,
266 .radi = rad,
267 .rad = rad,
268 .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
269 .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
270 .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
271 .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
272 .color_inner1[0] = filled ? col[0] : 0.0f,
273 .color_inner1[1] = filled ? col[1] : 0.0f,
274 .color_inner1[2] = filled ? col[2] : 0.0f,
275 .color_inner1[3] = filled ? col[3] : 0.0f,
276 .color_inner2[0] = filled ? col[0] : 0.0f,
277 .color_inner2[1] = filled ? col[1] : 0.0f,
278 .color_inner2[2] = filled ? col[2] : 0.0f,
279 .color_inner2[3] = filled ? col[3] : 0.0f,
280 .color_outline[0] = col[0],
281 .color_outline[1] = col[1],
282 .color_outline[2] = col[2],
283 .color_outline[3] = col[3],
284 .alpha_discard = 1.0f,
285 };
286 /* Exactly the same as UI_draw_roundbox_aa but does not do the legacy transparency. */
287
288 /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
289 * If it has been scaled, then it's no longer valid. */
290
291 GPUBatch *batch = ui_batch_roundbox_widget_get();
292 GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
293 GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params);
294
295 GPU_blend(GPU_BLEND_ALPHA);
296
297 GPU_batch_draw(batch);
298
299 GPU_blend(GPU_BLEND_NONE);
300 }
301
302 #if 0
303 static void round_box_shade_col(uint attr,
304 const float col1[3],
305 float const col2[3],
306 const float fac)
307 {
308 float col[4] = {
309 fac * col1[0] + (1.0f - fac) * col2[0],
310 fac * col1[1] + (1.0f - fac) * col2[1],
311 fac * col1[2] + (1.0f - fac) * col2[2],
312 1.0f,
313 };
314 immAttr4fv(attr, col);
315 }
316 #endif
317
318 /* linear horizontal shade within button or in outline */
319 /* view2d scrollers use it */
UI_draw_roundbox_shade_x(bool filled,float minx,float miny,float maxx,float maxy,float rad,float shadetop,float shadedown,const float col[4])320 void UI_draw_roundbox_shade_x(bool filled,
321 float minx,
322 float miny,
323 float maxx,
324 float maxy,
325 float rad,
326 float shadetop,
327 float shadedown,
328 const float col[4])
329 {
330 #if 0
331 float vec[7][2] = {
332 {0.195, 0.02},
333 {0.383, 0.067},
334 {0.55, 0.169},
335 {0.707, 0.293},
336 {0.831, 0.45},
337 {0.924, 0.617},
338 {0.98, 0.805},
339 };
340 const float div = maxy - miny;
341 const float idiv = 1.0f / div;
342 float coltop[3], coldown[3];
343 int vert_count = 0;
344 int a;
345
346 GPUVertFormat *format = immVertexFormat();
347 uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
348 uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
349
350 immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
351
352 /* mult */
353 for (a = 0; a < 7; a++) {
354 mul_v2_fl(vec[a], rad);
355 }
356
357 /* 'shade' defines strength of shading */
358 coltop[0] = min_ff(1.0f, col[0] + shadetop);
359 coltop[1] = min_ff(1.0f, col[1] + shadetop);
360 coltop[2] = min_ff(1.0f, col[2] + shadetop);
361 coldown[0] = max_ff(0.0f, col[0] + shadedown);
362 coldown[1] = max_ff(0.0f, col[1] + shadedown);
363 coldown[2] = max_ff(0.0f, col[2] + shadedown);
364
365 vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
366 vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
367 vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
368 vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
369
370 immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count);
371
372 /* start with corner right-bottom */
373 if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
374
375 round_box_shade_col(color, coltop, coldown, 0.0);
376 immVertex2f(pos, maxx - rad, miny);
377
378 for (a = 0; a < 7; a++) {
379 round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv);
380 immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
381 }
382
383 round_box_shade_col(color, coltop, coldown, rad * idiv);
384 immVertex2f(pos, maxx, miny + rad);
385 }
386 else {
387 round_box_shade_col(color, coltop, coldown, 0.0);
388 immVertex2f(pos, maxx, miny);
389 }
390
391 /* corner right-top */
392 if (roundboxtype & UI_CNR_TOP_RIGHT) {
393
394 round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
395 immVertex2f(pos, maxx, maxy - rad);
396
397 for (a = 0; a < 7; a++) {
398 round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv);
399 immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
400 }
401 round_box_shade_col(color, coltop, coldown, 1.0);
402 immVertex2f(pos, maxx - rad, maxy);
403 }
404 else {
405 round_box_shade_col(color, coltop, coldown, 1.0);
406 immVertex2f(pos, maxx, maxy);
407 }
408
409 /* corner left-top */
410 if (roundboxtype & UI_CNR_TOP_LEFT) {
411
412 round_box_shade_col(color, coltop, coldown, 1.0);
413 immVertex2f(pos, minx + rad, maxy);
414
415 for (a = 0; a < 7; a++) {
416 round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv);
417 immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
418 }
419
420 round_box_shade_col(color, coltop, coldown, (div - rad) * idiv);
421 immVertex2f(pos, minx, maxy - rad);
422 }
423 else {
424 round_box_shade_col(color, coltop, coldown, 1.0);
425 immVertex2f(pos, minx, maxy);
426 }
427
428 /* corner left-bottom */
429 if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
430
431 round_box_shade_col(color, coltop, coldown, rad * idiv);
432 immVertex2f(pos, minx, miny + rad);
433
434 for (a = 0; a < 7; a++) {
435 round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv);
436 immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
437 }
438
439 round_box_shade_col(color, coltop, coldown, 0.0);
440 immVertex2f(pos, minx + rad, miny);
441 }
442 else {
443 round_box_shade_col(color, coltop, coldown, 0.0);
444 immVertex2f(pos, minx, miny);
445 }
446
447 immEnd();
448 immUnbindProgram();
449 #endif
450 uiWidgetBaseParameters widget_params = {
451 .recti.xmin = minx + U.pixelsize,
452 .recti.ymin = miny + U.pixelsize,
453 .recti.xmax = maxx - U.pixelsize,
454 .recti.ymax = maxy - U.pixelsize,
455 .rect.xmin = minx,
456 .rect.ymin = miny,
457 .rect.xmax = maxx,
458 .rect.ymax = maxy,
459 .radi = rad,
460 .rad = rad,
461 .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
462 .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
463 .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
464 .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
465 .color_inner1[0] = !filled ? 0.0f : min_ff(1.0f, col[0] + shadetop),
466 .color_inner1[1] = !filled ? 0.0f : min_ff(1.0f, col[1] + shadetop),
467 .color_inner1[2] = !filled ? 0.0f : min_ff(1.0f, col[2] + shadetop),
468 .color_inner1[3] = !filled ? 0.0f : 1.0f,
469 .color_inner2[0] = !filled ? 0.0f : max_ff(0.0f, col[0] + shadedown),
470 .color_inner2[1] = !filled ? 0.0f : max_ff(0.0f, col[1] + shadedown),
471 .color_inner2[2] = !filled ? 0.0f : max_ff(0.0f, col[2] + shadedown),
472 .color_inner2[3] = !filled ? 0.0f : 1.0f,
473 /* TODO: non-filled box don't have gradients. Just use middle color. */
474 .color_outline[0] = clamp_f(col[0] + shadetop + shadedown, 0.0f, 1.0f),
475 .color_outline[1] = clamp_f(col[1] + shadetop + shadedown, 0.0f, 1.0f),
476 .color_outline[2] = clamp_f(col[2] + shadetop + shadedown, 0.0f, 1.0f),
477 .color_outline[3] = clamp_f(col[3] + shadetop + shadedown, 0.0f, 1.0f),
478 .shade_dir = 1.0f,
479 .alpha_discard = 1.0f,
480 };
481
482 GPU_blend(GPU_BLEND_ALPHA);
483
484 GPUBatch *batch = ui_batch_roundbox_widget_get();
485 GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
486 GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params);
487 GPU_batch_draw(batch);
488
489 GPU_blend(GPU_BLEND_NONE);
490 }
491
492 #if 0 /* unused */
493 /* linear vertical shade within button or in outline */
494 /* view2d scrollers use it */
495 void UI_draw_roundbox_shade_y(bool filled,
496 float minx,
497 float miny,
498 float maxx,
499 float maxy,
500 float rad,
501 float shadeleft,
502 float shaderight,
503 const float col[4])
504 {
505 float vec[7][2] = {
506 {0.195, 0.02},
507 {0.383, 0.067},
508 {0.55, 0.169},
509 {0.707, 0.293},
510 {0.831, 0.45},
511 {0.924, 0.617},
512 {0.98, 0.805},
513 };
514 const float div = maxx - minx;
515 const float idiv = 1.0f / div;
516 float colLeft[3], colRight[3];
517 int vert_count = 0;
518 int a;
519
520 /* mult */
521 for (a = 0; a < 7; a++) {
522 mul_v2_fl(vec[a], rad);
523 }
524
525 GPUVertFormat *format = immVertexFormat();
526 uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
527 uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
528
529 immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
530
531 /* 'shade' defines strength of shading */
532 colLeft[0] = min_ff(1.0f, col[0] + shadeleft);
533 colLeft[1] = min_ff(1.0f, col[1] + shadeleft);
534 colLeft[2] = min_ff(1.0f, col[2] + shadeleft);
535 colRight[0] = max_ff(0.0f, col[0] + shaderight);
536 colRight[1] = max_ff(0.0f, col[1] + shaderight);
537 colRight[2] = max_ff(0.0f, col[2] + shaderight);
538
539 vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
540 vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
541 vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
542 vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
543
544 immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count);
545
546 /* start with corner right-bottom */
547 if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
548 round_box_shade_col(color, colLeft, colRight, 0.0);
549 immVertex2f(pos, maxx - rad, miny);
550
551 for (a = 0; a < 7; a++) {
552 round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv);
553 immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
554 }
555
556 round_box_shade_col(color, colLeft, colRight, rad * idiv);
557 immVertex2f(pos, maxx, miny + rad);
558 }
559 else {
560 round_box_shade_col(color, colLeft, colRight, 0.0);
561 immVertex2f(pos, maxx, miny);
562 }
563
564 /* corner right-top */
565 if (roundboxtype & UI_CNR_TOP_RIGHT) {
566 round_box_shade_col(color, colLeft, colRight, 0.0);
567 immVertex2f(pos, maxx, maxy - rad);
568
569 for (a = 0; a < 7; a++) {
570
571 round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv);
572 immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
573 }
574 round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
575 immVertex2f(pos, maxx - rad, maxy);
576 }
577 else {
578 round_box_shade_col(color, colLeft, colRight, 0.0);
579 immVertex2f(pos, maxx, maxy);
580 }
581
582 /* corner left-top */
583 if (roundboxtype & UI_CNR_TOP_LEFT) {
584 round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv);
585 immVertex2f(pos, minx + rad, maxy);
586
587 for (a = 0; a < 7; a++) {
588 round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv);
589 immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
590 }
591
592 round_box_shade_col(color, colLeft, colRight, 1.0);
593 immVertex2f(pos, minx, maxy - rad);
594 }
595 else {
596 round_box_shade_col(color, colLeft, colRight, 1.0);
597 immVertex2f(pos, minx, maxy);
598 }
599
600 /* corner left-bottom */
601 if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
602 round_box_shade_col(color, colLeft, colRight, 1.0);
603 immVertex2f(pos, minx, miny + rad);
604
605 for (a = 0; a < 7; a++) {
606 round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv);
607 immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
608 }
609
610 round_box_shade_col(color, colLeft, colRight, 1.0);
611 immVertex2f(pos, minx + rad, miny);
612 }
613 else {
614 round_box_shade_col(color, colLeft, colRight, 1.0);
615 immVertex2f(pos, minx, miny);
616 }
617
618 immEnd();
619 immUnbindProgram();
620 }
621 #endif /* unused */
622
UI_draw_text_underline(int pos_x,int pos_y,int len,int height,const float color[4])623 void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4])
624 {
625 const int ofs_y = 4 * U.pixelsize;
626
627 GPUVertFormat *format = immVertexFormat();
628 const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
629
630 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
631 immUniformColor4fv(color);
632
633 immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
634 immUnbindProgram();
635 }
636
637 /* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
638
639 /* based on UI_draw_roundbox_gl_mode,
640 * check on making a version which allows us to skip some sides */
ui_draw_but_TAB_outline(const rcti * rect,float rad,uchar highlight[3],uchar highlight_fade[3])641 void ui_draw_but_TAB_outline(const rcti *rect,
642 float rad,
643 uchar highlight[3],
644 uchar highlight_fade[3])
645 {
646 GPUVertFormat *format = immVertexFormat();
647 const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
648 const uint col = GPU_vertformat_attr_add(
649 format, "color", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
650 /* add a 1px offset, looks nicer */
651 const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize;
652 const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize;
653 int a;
654 float vec[4][2] = {
655 {0.195, 0.02},
656 {0.55, 0.169},
657 {0.831, 0.45},
658 {0.98, 0.805},
659 };
660
661 /* mult */
662 for (a = 0; a < 4; a++) {
663 mul_v2_fl(vec[a], rad);
664 }
665
666 immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
667 immBeginAtMost(GPU_PRIM_LINE_STRIP, 25);
668
669 immAttr3ubv(col, highlight);
670
671 /* start with corner left-top */
672 if (roundboxtype & UI_CNR_TOP_LEFT) {
673 immVertex2f(pos, minx, maxy - rad);
674 for (a = 0; a < 4; a++) {
675 immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]);
676 }
677 immVertex2f(pos, minx + rad, maxy);
678 }
679 else {
680 immVertex2f(pos, minx, maxy);
681 }
682
683 /* corner right-top */
684 if (roundboxtype & UI_CNR_TOP_RIGHT) {
685 immVertex2f(pos, maxx - rad, maxy);
686 for (a = 0; a < 4; a++) {
687 immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]);
688 }
689 immVertex2f(pos, maxx, maxy - rad);
690 }
691 else {
692 immVertex2f(pos, maxx, maxy);
693 }
694
695 immAttr3ubv(col, highlight_fade);
696
697 /* corner right-bottom */
698 if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
699 immVertex2f(pos, maxx, miny + rad);
700 for (a = 0; a < 4; a++) {
701 immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]);
702 }
703 immVertex2f(pos, maxx - rad, miny);
704 }
705 else {
706 immVertex2f(pos, maxx, miny);
707 }
708
709 /* corner left-bottom */
710 if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
711 immVertex2f(pos, minx + rad, miny);
712 for (a = 0; a < 4; a++) {
713 immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]);
714 }
715 immVertex2f(pos, minx, miny + rad);
716 }
717 else {
718 immVertex2f(pos, minx, miny);
719 }
720
721 immAttr3ubv(col, highlight);
722
723 /* back to corner left-top */
724 immVertex2f(pos, minx, (roundboxtype & UI_CNR_TOP_LEFT) ? (maxy - rad) : maxy);
725
726 immEnd();
727 immUnbindProgram();
728 }
729
ui_draw_but_IMAGE(ARegion * UNUSED (region),uiBut * but,const uiWidgetColors * UNUSED (wcol),const rcti * rect)730 void ui_draw_but_IMAGE(ARegion *UNUSED(region),
731 uiBut *but,
732 const uiWidgetColors *UNUSED(wcol),
733 const rcti *rect)
734 {
735 #ifdef WITH_HEADLESS
736 (void)rect;
737 (void)but;
738 #else
739 ImBuf *ibuf = (ImBuf *)but->poin;
740
741 if (!ibuf) {
742 return;
743 }
744
745 const int w = BLI_rcti_size_x(rect);
746 const int h = BLI_rcti_size_y(rect);
747
748 /* scissor doesn't seem to be doing the right thing...? */
749 # if 0
750 /* prevent drawing outside widget area */
751 int scissor[4];
752 GPU_scissor_get(scissor);
753 GPU_scissor(rect->xmin, rect->ymin, w, h);
754 # endif
755
756 /* Combine with premultiplied alpha. */
757 GPU_blend(GPU_BLEND_ALPHA_PREMULT);
758
759 if (w != ibuf->x || h != ibuf->y) {
760 /* We scale the bitmap, rather than have OGL do a worse job. */
761 IMB_scaleImBuf(ibuf, w, h);
762 }
763
764 float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
765 if (but->col[3] != 0) {
766 /* Optionally use uiBut's col to recolor the image. */
767 rgba_uchar_to_float(col, but->col);
768 }
769
770 IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
771 immDrawPixelsTex(&state,
772 (float)rect->xmin,
773 (float)rect->ymin,
774 ibuf->x,
775 ibuf->y,
776 GPU_RGBA8,
777 false,
778 ibuf->rect,
779 1.0f,
780 1.0f,
781 col);
782
783 GPU_blend(GPU_BLEND_NONE);
784
785 # if 0
786 /* restore scissortest */
787 GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
788 # endif
789
790 #endif
791 }
792
793 /**
794 * Draw title and text safe areas.
795 *
796 * \note This function is to be used with the 2D dashed shader enabled.
797 *
798 * \param pos: is a #PRIM_FLOAT, 2, #GPU_FETCH_FLOAT vertex attribute.
799 * \param x1, x2, y1, y2: The offsets for the view, not the zones.
800 */
UI_draw_safe_areas(uint pos,float x1,float x2,float y1,float y2,const float title_aspect[2],const float action_aspect[2])801 void UI_draw_safe_areas(uint pos,
802 float x1,
803 float x2,
804 float y1,
805 float y2,
806 const float title_aspect[2],
807 const float action_aspect[2])
808 {
809 const float size_x_half = (x2 - x1) * 0.5f;
810 const float size_y_half = (y2 - y1) * 0.5f;
811
812 const float *safe_areas[] = {title_aspect, action_aspect};
813 const int safe_len = ARRAY_SIZE(safe_areas);
814
815 for (int i = 0; i < safe_len; i++) {
816 if (safe_areas[i][0] || safe_areas[i][1]) {
817 const float margin_x = safe_areas[i][0] * size_x_half;
818 const float margin_y = safe_areas[i][1] * size_y_half;
819
820 const float minx = x1 + margin_x;
821 const float miny = y1 + margin_y;
822 const float maxx = x2 - margin_x;
823 const float maxy = y2 - margin_y;
824
825 imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
826 }
827 }
828 }
829
draw_scope_end(const rctf * rect)830 static void draw_scope_end(const rctf *rect)
831 {
832 GPU_blend(GPU_BLEND_ALPHA);
833
834 /* outline */
835 UI_draw_roundbox_corner_set(UI_CNR_ALL);
836 const float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
837 UI_draw_roundbox_4fv(
838 false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color);
839 }
840
histogram_draw_one(float r,float g,float b,float alpha,float x,float y,float w,float h,const float * data,int res,const bool is_line,uint pos_attr)841 static void histogram_draw_one(float r,
842 float g,
843 float b,
844 float alpha,
845 float x,
846 float y,
847 float w,
848 float h,
849 const float *data,
850 int res,
851 const bool is_line,
852 uint pos_attr)
853 {
854 const float color[4] = {r, g, b, alpha};
855
856 /* that can happen */
857 if (res == 0) {
858 return;
859 }
860
861 GPU_line_smooth(true);
862 GPU_blend(GPU_BLEND_ADDITIVE);
863
864 immUniformColor4fv(color);
865
866 if (is_line) {
867 /* curve outline */
868 GPU_line_width(1.5);
869
870 immBegin(GPU_PRIM_LINE_STRIP, res);
871 for (int i = 0; i < res; i++) {
872 const float x2 = x + i * (w / (float)res);
873 immVertex2f(pos_attr, x2, y + (data[i] * h));
874 }
875 immEnd();
876 }
877 else {
878 /* under the curve */
879 immBegin(GPU_PRIM_TRI_STRIP, res * 2);
880 immVertex2f(pos_attr, x, y);
881 immVertex2f(pos_attr, x, y + (data[0] * h));
882 for (int i = 1; i < res; i++) {
883 const float x2 = x + i * (w / (float)res);
884 immVertex2f(pos_attr, x2, y + (data[i] * h));
885 immVertex2f(pos_attr, x2, y);
886 }
887 immEnd();
888
889 /* curve outline */
890 immUniformColor4f(0.0f, 0.0f, 0.0f, 0.25f);
891
892 GPU_blend(GPU_BLEND_ALPHA);
893 immBegin(GPU_PRIM_LINE_STRIP, res);
894 for (int i = 0; i < res; i++) {
895 const float x2 = x + i * (w / (float)res);
896 immVertex2f(pos_attr, x2, y + (data[i] * h));
897 }
898 immEnd();
899 }
900
901 GPU_line_smooth(false);
902 }
903
904 #define HISTOGRAM_TOT_GRID_LINES 4
905
ui_draw_but_HISTOGRAM(ARegion * UNUSED (region),uiBut * but,const uiWidgetColors * UNUSED (wcol),const rcti * recti)906 void ui_draw_but_HISTOGRAM(ARegion *UNUSED(region),
907 uiBut *but,
908 const uiWidgetColors *UNUSED(wcol),
909 const rcti *recti)
910 {
911 Histogram *hist = (Histogram *)but->poin;
912 const int res = hist->x_resolution;
913 const bool is_line = (hist->flag & HISTO_FLAG_LINE) != 0;
914
915 rctf rect = {
916 .xmin = (float)recti->xmin + 1,
917 .xmax = (float)recti->xmax - 1,
918 .ymin = (float)recti->ymin + 1,
919 .ymax = (float)recti->ymax - 1,
920 };
921
922 const float w = BLI_rctf_size_x(&rect);
923 const float h = BLI_rctf_size_y(&rect) * hist->ymax;
924
925 GPU_blend(GPU_BLEND_ALPHA);
926
927 float color[4];
928 UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
929 UI_draw_roundbox_corner_set(UI_CNR_ALL);
930 UI_draw_roundbox_4fv(
931 true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
932
933 /* need scissor test, histogram can draw outside of boundary */
934 int scissor[4];
935 GPU_scissor_get(scissor);
936 GPU_scissor((rect.xmin - 1),
937 (rect.ymin - 1),
938 (rect.xmax + 1) - (rect.xmin - 1),
939 (rect.ymax + 1) - (rect.ymin - 1));
940
941 GPUVertFormat *format = immVertexFormat();
942 const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
943
944 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
945
946 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
947 /* draw grid lines here */
948 for (int i = 1; i <= HISTOGRAM_TOT_GRID_LINES; i++) {
949 const float fac = (float)i / (float)HISTOGRAM_TOT_GRID_LINES;
950
951 /* so we can tell the 1.0 color point */
952 if (i == HISTOGRAM_TOT_GRID_LINES) {
953 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
954 }
955
956 immBegin(GPU_PRIM_LINES, 4);
957
958 immVertex2f(pos, rect.xmin, rect.ymin + fac * h);
959 immVertex2f(pos, rect.xmax, rect.ymin + fac * h);
960
961 immVertex2f(pos, rect.xmin + fac * w, rect.ymin);
962 immVertex2f(pos, rect.xmin + fac * w, rect.ymax);
963
964 immEnd();
965 }
966
967 if (hist->mode == HISTO_MODE_LUMA) {
968 histogram_draw_one(
969 1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line, pos);
970 }
971 else if (hist->mode == HISTO_MODE_ALPHA) {
972 histogram_draw_one(
973 1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line, pos);
974 }
975 else {
976 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) {
977 histogram_draw_one(
978 1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line, pos);
979 }
980 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G) {
981 histogram_draw_one(
982 0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line, pos);
983 }
984 if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B) {
985 histogram_draw_one(
986 0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line, pos);
987 }
988 }
989
990 immUnbindProgram();
991
992 /* Restore scissor test. */
993 GPU_scissor(UNPACK4(scissor));
994
995 /* outline */
996 draw_scope_end(&rect);
997 }
998
999 #undef HISTOGRAM_TOT_GRID_LINES
1000
waveform_draw_one(float * waveform,int nbr,const float col[3])1001 static void waveform_draw_one(float *waveform, int nbr, const float col[3])
1002 {
1003 GPUVertFormat format = {0};
1004 const uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1005
1006 GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1007 GPU_vertbuf_data_alloc(vbo, nbr);
1008
1009 GPU_vertbuf_attr_fill(vbo, pos_id, waveform);
1010
1011 /* TODO store the GPUBatch inside the scope */
1012 GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
1013 GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
1014 GPU_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
1015 GPU_batch_draw(batch);
1016
1017 GPU_batch_discard(batch);
1018 }
1019
ui_draw_but_WAVEFORM(ARegion * UNUSED (region),uiBut * but,const uiWidgetColors * UNUSED (wcol),const rcti * recti)1020 void ui_draw_but_WAVEFORM(ARegion *UNUSED(region),
1021 uiBut *but,
1022 const uiWidgetColors *UNUSED(wcol),
1023 const rcti *recti)
1024 {
1025 Scopes *scopes = (Scopes *)but->poin;
1026 int scissor[4];
1027 float colors[3][3];
1028 const float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}};
1029 /* colors pre multiplied by alpha for speed up */
1030 float colors_alpha[3][3], colorsycc_alpha[3][3];
1031 float min, max;
1032
1033 if (scopes == NULL) {
1034 return;
1035 }
1036
1037 rctf rect = {
1038 .xmin = (float)recti->xmin + 1,
1039 .xmax = (float)recti->xmax - 1,
1040 .ymin = (float)recti->ymin + 1,
1041 .ymax = (float)recti->ymax - 1,
1042 };
1043
1044 if (scopes->wavefrm_yfac < 0.5f) {
1045 scopes->wavefrm_yfac = 0.98f;
1046 }
1047 const float w = BLI_rctf_size_x(&rect) - 7;
1048 const float h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac;
1049 const float yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) * 0.5f;
1050 const float w3 = w / 3.0f;
1051
1052 /* log scale for alpha */
1053 const float alpha = scopes->wavefrm_alpha * scopes->wavefrm_alpha;
1054
1055 unit_m3(colors);
1056
1057 for (int c = 0; c < 3; c++) {
1058 for (int i = 0; i < 3; i++) {
1059 colors_alpha[c][i] = colors[c][i] * alpha;
1060 colorsycc_alpha[c][i] = colorsycc[c][i] * alpha;
1061 }
1062 }
1063
1064 /* Flush text cache before changing scissors. */
1065 BLF_batch_draw_flush();
1066
1067 GPU_blend(GPU_BLEND_ALPHA);
1068
1069 float color[4];
1070 UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
1071 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1072 UI_draw_roundbox_4fv(
1073 true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
1074
1075 /* need scissor test, waveform can draw outside of boundary */
1076 GPU_scissor_get(scissor);
1077 GPU_scissor((rect.xmin - 1),
1078 (rect.ymin - 1),
1079 (rect.xmax + 1) - (rect.xmin - 1),
1080 (rect.ymax + 1) - (rect.ymin - 1));
1081
1082 /* draw scale numbers first before binding any shader */
1083 for (int i = 0; i < 6; i++) {
1084 char str[4];
1085 BLI_snprintf(str, sizeof(str), "%-3d", i * 20);
1086 str[3] = '\0';
1087 BLF_color4f(BLF_default(), 1.0f, 1.0f, 1.0f, 0.08f);
1088 BLF_draw_default(rect.xmin + 1, yofs - 5 + (i * 0.2f) * h, 0, str, sizeof(str) - 1);
1089 }
1090
1091 /* Flush text cache before drawing things on top. */
1092 BLF_batch_draw_flush();
1093
1094 GPU_blend(GPU_BLEND_ALPHA);
1095
1096 GPUVertFormat *format = immVertexFormat();
1097 const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1098
1099 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1100
1101 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
1102
1103 /* draw grid lines here */
1104 immBegin(GPU_PRIM_LINES, 12);
1105
1106 for (int i = 0; i < 6; i++) {
1107 immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h);
1108 immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h);
1109 }
1110
1111 immEnd();
1112
1113 /* 3 vertical separation */
1114 if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
1115 immBegin(GPU_PRIM_LINES, 4);
1116
1117 for (int i = 1; i < 3; i++) {
1118 immVertex2f(pos, rect.xmin + i * w3, rect.ymin);
1119 immVertex2f(pos, rect.xmin + i * w3, rect.ymax);
1120 }
1121
1122 immEnd();
1123 }
1124
1125 /* separate min max zone on the right */
1126 immBegin(GPU_PRIM_LINES, 2);
1127 immVertex2f(pos, rect.xmin + w, rect.ymin);
1128 immVertex2f(pos, rect.xmin + w, rect.ymax);
1129 immEnd();
1130
1131 /* 16-235-240 level in case of ITU-R BT601/709 */
1132 immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
1133 if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
1134 immBegin(GPU_PRIM_LINES, 8);
1135
1136 immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f);
1137 immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
1138
1139 immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f);
1140 immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
1141
1142 immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f);
1143 immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
1144
1145 immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f);
1146 immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
1147
1148 immEnd();
1149 }
1150 /* 7.5 IRE black point level for NTSC */
1151 if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
1152 immBegin(GPU_PRIM_LINES, 2);
1153 immVertex2f(pos, rect.xmin, yofs + h * 0.075f);
1154 immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f);
1155 immEnd();
1156 }
1157
1158 if (scopes->ok && scopes->waveform_1 != NULL) {
1159 GPU_blend(GPU_BLEND_ADDITIVE);
1160 GPU_point_size(1.0);
1161
1162 /* LUMA (1 channel) */
1163 if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
1164 const float col[3] = {alpha, alpha, alpha};
1165
1166 GPU_matrix_push();
1167 GPU_matrix_translate_2f(rect.xmin, yofs);
1168 GPU_matrix_scale_2f(w, h);
1169
1170 waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
1171
1172 GPU_matrix_pop();
1173
1174 /* min max */
1175 immUniformColor3f(0.5f, 0.5f, 0.5f);
1176 min = yofs + scopes->minmax[0][0] * h;
1177 max = yofs + scopes->minmax[0][1] * h;
1178 CLAMP(min, rect.ymin, rect.ymax);
1179 CLAMP(max, rect.ymin, rect.ymax);
1180
1181 immBegin(GPU_PRIM_LINES, 2);
1182 immVertex2f(pos, rect.xmax - 3, min);
1183 immVertex2f(pos, rect.xmax - 3, max);
1184 immEnd();
1185 }
1186 /* RGB (3 channel) */
1187 else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
1188 GPU_matrix_push();
1189 GPU_matrix_translate_2f(rect.xmin, yofs);
1190 GPU_matrix_scale_2f(w, h);
1191
1192 waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]);
1193 waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]);
1194 waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]);
1195
1196 GPU_matrix_pop();
1197 }
1198 /* PARADE / YCC (3 channels) */
1199 else if (ELEM(scopes->wavefrm_mode,
1200 SCOPES_WAVEFRM_RGB_PARADE,
1201 SCOPES_WAVEFRM_YCC_601,
1202 SCOPES_WAVEFRM_YCC_709,
1203 SCOPES_WAVEFRM_YCC_JPEG)) {
1204 const int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
1205
1206 GPU_matrix_push();
1207 GPU_matrix_translate_2f(rect.xmin, yofs);
1208 GPU_matrix_scale_2f(w3, h);
1209
1210 waveform_draw_one(
1211 scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
1212
1213 GPU_matrix_translate_2f(1.0f, 0.0f);
1214 waveform_draw_one(
1215 scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
1216
1217 GPU_matrix_translate_2f(1.0f, 0.0f);
1218 waveform_draw_one(
1219 scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
1220
1221 GPU_matrix_pop();
1222 }
1223
1224 /* min max */
1225 if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
1226 for (int c = 0; c < 3; c++) {
1227 if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB)) {
1228 immUniformColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f);
1229 }
1230 else {
1231 immUniformColor3f(
1232 colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f);
1233 }
1234 min = yofs + scopes->minmax[c][0] * h;
1235 max = yofs + scopes->minmax[c][1] * h;
1236 CLAMP(min, rect.ymin, rect.ymax);
1237 CLAMP(max, rect.ymin, rect.ymax);
1238
1239 immBegin(GPU_PRIM_LINES, 2);
1240 immVertex2f(pos, rect.xmin + w + 2 + c * 2, min);
1241 immVertex2f(pos, rect.xmin + w + 2 + c * 2, max);
1242 immEnd();
1243 }
1244 }
1245 }
1246
1247 immUnbindProgram();
1248
1249 /* Restore scissor test. */
1250 GPU_scissor(UNPACK4(scissor));
1251
1252 /* outline */
1253 draw_scope_end(&rect);
1254
1255 GPU_blend(GPU_BLEND_NONE);
1256 }
1257
polar_to_x(float center,float diam,float ampli,float angle)1258 static float polar_to_x(float center, float diam, float ampli, float angle)
1259 {
1260 return center + diam * ampli * cosf(angle);
1261 }
1262
polar_to_y(float center,float diam,float ampli,float angle)1263 static float polar_to_y(float center, float diam, float ampli, float angle)
1264 {
1265 return center + diam * ampli * sinf(angle);
1266 }
1267
vectorscope_draw_target(uint pos,float centerx,float centery,float diam,const float colf[3])1268 static void vectorscope_draw_target(
1269 uint pos, float centerx, float centery, float diam, const float colf[3])
1270 {
1271 float y, u, v;
1272 float tangle = 0.0f, tampli;
1273 float dangle, dampli, dangle2, dampli2;
1274
1275 rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v, BLI_YUV_ITU_BT709);
1276
1277 if (u > 0 && v >= 0) {
1278 tangle = atanf(v / u);
1279 }
1280 else if (u > 0 && v < 0) {
1281 tangle = atanf(v / u) + 2.0f * (float)M_PI;
1282 }
1283 else if (u < 0) {
1284 tangle = atanf(v / u) + (float)M_PI;
1285 }
1286 else if (u == 0 && v > 0.0f) {
1287 tangle = M_PI_2;
1288 }
1289 else if (u == 0 && v < 0.0f) {
1290 tangle = -M_PI_2;
1291 }
1292 tampli = sqrtf(u * u + v * v);
1293
1294 /* small target vary by 2.5 degree and 2.5 IRE unit */
1295 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
1296 dangle = DEG2RADF(2.5f);
1297 dampli = 2.5f / 200.0f;
1298 immBegin(GPU_PRIM_LINE_LOOP, 4);
1299 immVertex2f(pos,
1300 polar_to_x(centerx, diam, tampli + dampli, tangle + dangle),
1301 polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
1302 immVertex2f(pos,
1303 polar_to_x(centerx, diam, tampli - dampli, tangle + dangle),
1304 polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
1305 immVertex2f(pos,
1306 polar_to_x(centerx, diam, tampli - dampli, tangle - dangle),
1307 polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
1308 immVertex2f(pos,
1309 polar_to_x(centerx, diam, tampli + dampli, tangle - dangle),
1310 polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
1311 immEnd();
1312 /* big target vary by 10 degree and 20% amplitude */
1313 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.12f);
1314 dangle = DEG2RADF(10.0f);
1315 dampli = 0.2f * tampli;
1316 dangle2 = DEG2RADF(5.0f);
1317 dampli2 = 0.5f * dampli;
1318 immBegin(GPU_PRIM_LINE_STRIP, 3);
1319 immVertex2f(pos,
1320 polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle + dangle),
1321 polar_to_y(centery, diam, tampli + dampli - dampli2, tangle + dangle));
1322 immVertex2f(pos,
1323 polar_to_x(centerx, diam, tampli + dampli, tangle + dangle),
1324 polar_to_y(centery, diam, tampli + dampli, tangle + dangle));
1325 immVertex2f(pos,
1326 polar_to_x(centerx, diam, tampli + dampli, tangle + dangle - dangle2),
1327 polar_to_y(centery, diam, tampli + dampli, tangle + dangle - dangle2));
1328 immEnd();
1329 immBegin(GPU_PRIM_LINE_STRIP, 3);
1330 immVertex2f(pos,
1331 polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle + dangle),
1332 polar_to_y(centery, diam, tampli - dampli + dampli2, tangle + dangle));
1333 immVertex2f(pos,
1334 polar_to_x(centerx, diam, tampli - dampli, tangle + dangle),
1335 polar_to_y(centery, diam, tampli - dampli, tangle + dangle));
1336 immVertex2f(pos,
1337 polar_to_x(centerx, diam, tampli - dampli, tangle + dangle - dangle2),
1338 polar_to_y(centery, diam, tampli - dampli, tangle + dangle - dangle2));
1339 immEnd();
1340 immBegin(GPU_PRIM_LINE_STRIP, 3);
1341 immVertex2f(pos,
1342 polar_to_x(centerx, diam, tampli - dampli + dampli2, tangle - dangle),
1343 polar_to_y(centery, diam, tampli - dampli + dampli2, tangle - dangle));
1344 immVertex2f(pos,
1345 polar_to_x(centerx, diam, tampli - dampli, tangle - dangle),
1346 polar_to_y(centery, diam, tampli - dampli, tangle - dangle));
1347 immVertex2f(pos,
1348 polar_to_x(centerx, diam, tampli - dampli, tangle - dangle + dangle2),
1349 polar_to_y(centery, diam, tampli - dampli, tangle - dangle + dangle2));
1350 immEnd();
1351 immBegin(GPU_PRIM_LINE_STRIP, 3);
1352 immVertex2f(pos,
1353 polar_to_x(centerx, diam, tampli + dampli - dampli2, tangle - dangle),
1354 polar_to_y(centery, diam, tampli + dampli - dampli2, tangle - dangle));
1355 immVertex2f(pos,
1356 polar_to_x(centerx, diam, tampli + dampli, tangle - dangle),
1357 polar_to_y(centery, diam, tampli + dampli, tangle - dangle));
1358 immVertex2f(pos,
1359 polar_to_x(centerx, diam, tampli + dampli, tangle - dangle + dangle2),
1360 polar_to_y(centery, diam, tampli + dampli, tangle - dangle + dangle2));
1361 immEnd();
1362 }
1363
ui_draw_but_VECTORSCOPE(ARegion * UNUSED (region),uiBut * but,const uiWidgetColors * UNUSED (wcol),const rcti * recti)1364 void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(region),
1365 uiBut *but,
1366 const uiWidgetColors *UNUSED(wcol),
1367 const rcti *recti)
1368 {
1369 const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
1370 Scopes *scopes = (Scopes *)but->poin;
1371
1372 const float colors[6][3] = {
1373 {0.75, 0.0, 0.0},
1374 {0.75, 0.75, 0.0},
1375 {0.0, 0.75, 0.0},
1376 {0.0, 0.75, 0.75},
1377 {0.0, 0.0, 0.75},
1378 {0.75, 0.0, 0.75},
1379 };
1380
1381 rctf rect = {
1382 .xmin = (float)recti->xmin + 1,
1383 .xmax = (float)recti->xmax - 1,
1384 .ymin = (float)recti->ymin + 1,
1385 .ymax = (float)recti->ymax - 1,
1386 };
1387
1388 const float w = BLI_rctf_size_x(&rect);
1389 const float h = BLI_rctf_size_y(&rect);
1390 const float centerx = rect.xmin + w * 0.5f;
1391 const float centery = rect.ymin + h * 0.5f;
1392 const float diam = (w < h) ? w : h;
1393
1394 const float alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha;
1395
1396 GPU_blend(GPU_BLEND_ALPHA);
1397
1398 float color[4];
1399 UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
1400 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1401 UI_draw_roundbox_4fv(
1402 true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
1403
1404 /* need scissor test, hvectorscope can draw outside of boundary */
1405 int scissor[4];
1406 GPU_scissor_get(scissor);
1407 GPU_scissor((rect.xmin - 1),
1408 (rect.ymin - 1),
1409 (rect.xmax + 1) - (rect.xmin - 1),
1410 (rect.ymax + 1) - (rect.ymin - 1));
1411
1412 GPUVertFormat *format = immVertexFormat();
1413 const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1414
1415 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1416
1417 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
1418 /* draw grid elements */
1419 /* cross */
1420 immBegin(GPU_PRIM_LINES, 4);
1421
1422 immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery);
1423 immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery);
1424
1425 immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5);
1426 immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5);
1427
1428 immEnd();
1429
1430 /* circles */
1431 for (int j = 0; j < 5; j++) {
1432 const int increment = 15;
1433 immBegin(GPU_PRIM_LINE_LOOP, (int)(360 / increment));
1434 for (int i = 0; i <= 360 - increment; i += increment) {
1435 const float a = DEG2RADF((float)i);
1436 const float r = (j + 1) * 0.1f;
1437 immVertex2f(pos, polar_to_x(centerx, diam, r, a), polar_to_y(centery, diam, r, a));
1438 }
1439 immEnd();
1440 }
1441 /* skin tone line */
1442 immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
1443
1444 immBegin(GPU_PRIM_LINES, 2);
1445 immVertex2f(
1446 pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad));
1447 immVertex2f(
1448 pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
1449 immEnd();
1450
1451 /* saturation points */
1452 for (int i = 0; i < 6; i++) {
1453 vectorscope_draw_target(pos, centerx, centery, diam, colors[i]);
1454 }
1455
1456 if (scopes->ok && scopes->vecscope != NULL) {
1457 /* pixel point cloud */
1458 const float col[3] = {alpha, alpha, alpha};
1459
1460 GPU_blend(GPU_BLEND_ADDITIVE);
1461 GPU_point_size(1.0);
1462
1463 GPU_matrix_push();
1464 GPU_matrix_translate_2f(centerx, centery);
1465 GPU_matrix_scale_1f(diam);
1466
1467 waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col);
1468
1469 GPU_matrix_pop();
1470 }
1471
1472 immUnbindProgram();
1473
1474 /* Restore scissor test. */
1475 GPU_scissor(UNPACK4(scissor));
1476 /* outline */
1477 draw_scope_end(&rect);
1478
1479 GPU_blend(GPU_BLEND_NONE);
1480 }
1481
ui_draw_colorband_handle_tri_hlight(uint pos,float x1,float y1,float halfwidth,float height)1482 static void ui_draw_colorband_handle_tri_hlight(
1483 uint pos, float x1, float y1, float halfwidth, float height)
1484 {
1485 GPU_line_smooth(true);
1486
1487 immBegin(GPU_PRIM_LINE_STRIP, 3);
1488 immVertex2f(pos, x1 + halfwidth, y1);
1489 immVertex2f(pos, x1, y1 + height);
1490 immVertex2f(pos, x1 - halfwidth, y1);
1491 immEnd();
1492
1493 GPU_line_smooth(false);
1494 }
1495
ui_draw_colorband_handle_tri(uint pos,float x1,float y1,float halfwidth,float height,bool fill)1496 static void ui_draw_colorband_handle_tri(
1497 uint pos, float x1, float y1, float halfwidth, float height, bool fill)
1498 {
1499 if (fill) {
1500 GPU_polygon_smooth(true);
1501 }
1502 else {
1503 GPU_line_smooth(true);
1504 }
1505
1506 immBegin(fill ? GPU_PRIM_TRIS : GPU_PRIM_LINE_LOOP, 3);
1507 immVertex2f(pos, x1 + halfwidth, y1);
1508 immVertex2f(pos, x1, y1 + height);
1509 immVertex2f(pos, x1 - halfwidth, y1);
1510 immEnd();
1511
1512 if (fill) {
1513 GPU_polygon_smooth(false);
1514 }
1515 else {
1516 GPU_line_smooth(false);
1517 }
1518 }
1519
ui_draw_colorband_handle_box(uint pos,float x1,float y1,float x2,float y2,bool fill)1520 static void ui_draw_colorband_handle_box(
1521 uint pos, float x1, float y1, float x2, float y2, bool fill)
1522 {
1523 immBegin(fill ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
1524 immVertex2f(pos, x1, y1);
1525 immVertex2f(pos, x1, y2);
1526 immVertex2f(pos, x2, y2);
1527 immVertex2f(pos, x2, y1);
1528 immEnd();
1529 }
1530
ui_draw_colorband_handle(uint shdr_pos,const rcti * rect,float x,const float rgb[3],struct ColorManagedDisplay * display,bool active)1531 static void ui_draw_colorband_handle(uint shdr_pos,
1532 const rcti *rect,
1533 float x,
1534 const float rgb[3],
1535 struct ColorManagedDisplay *display,
1536 bool active)
1537 {
1538 const float sizey = BLI_rcti_size_y(rect);
1539 const float min_width = 3.0f;
1540 float colf[3] = {UNPACK3(rgb)};
1541
1542 const float half_width = floorf(sizey / 3.5f);
1543 const float height = half_width * 1.4f;
1544
1545 float y1 = rect->ymin + (sizey * 0.16f);
1546 const float y2 = rect->ymax;
1547
1548 /* align to pixels */
1549 x = floorf(x + 0.5f);
1550 y1 = floorf(y1 + 0.5f);
1551
1552 if (active || half_width < min_width) {
1553 immUnbindProgram();
1554
1555 immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
1556
1557 float viewport_size[4];
1558 GPU_viewport_size_get_f(viewport_size);
1559 immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
1560
1561 immUniform1i("colors_len", 2); /* "advanced" mode */
1562 immUniformArray4fv(
1563 "colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
1564 immUniform1f("dash_width", active ? 4.0f : 2.0f);
1565 immUniform1f("dash_factor", 0.5f);
1566
1567 immBegin(GPU_PRIM_LINES, 2);
1568 immVertex2f(shdr_pos, x, y1);
1569 immVertex2f(shdr_pos, x, y2);
1570 immEnd();
1571
1572 immUnbindProgram();
1573
1574 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1575
1576 /* hide handles when zoomed out too far */
1577 if (half_width < min_width) {
1578 return;
1579 }
1580 }
1581
1582 /* shift handle down */
1583 y1 -= half_width;
1584
1585 immUniformColor3ub(0, 0, 0);
1586 ui_draw_colorband_handle_box(
1587 shdr_pos, x - half_width, y1 - 1, x + half_width, y1 + height, false);
1588
1589 /* draw all triangles blended */
1590 GPU_blend(GPU_BLEND_ALPHA);
1591
1592 ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
1593
1594 if (active) {
1595 immUniformColor3ub(196, 196, 196);
1596 }
1597 else {
1598 immUniformColor3ub(96, 96, 96);
1599 }
1600 ui_draw_colorband_handle_tri(shdr_pos, x, y1 + height, half_width, half_width, true);
1601
1602 if (active) {
1603 immUniformColor3ub(255, 255, 255);
1604 }
1605 else {
1606 immUniformColor3ub(128, 128, 128);
1607 }
1608 ui_draw_colorband_handle_tri_hlight(
1609 shdr_pos, x, y1 + height - 1, (half_width - 1), (half_width - 1));
1610
1611 immUniformColor3ub(0, 0, 0);
1612 ui_draw_colorband_handle_tri_hlight(shdr_pos, x, y1 + height, half_width, half_width);
1613
1614 GPU_blend(GPU_BLEND_NONE);
1615
1616 immUniformColor3ub(128, 128, 128);
1617 ui_draw_colorband_handle_box(
1618 shdr_pos, x - (half_width - 1), y1, x + (half_width - 1), y1 + height, true);
1619
1620 if (display) {
1621 IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1622 }
1623
1624 immUniformColor3fv(colf);
1625 ui_draw_colorband_handle_box(
1626 shdr_pos, x - (half_width - 2), y1 + 1, x + (half_width - 2), y1 + height - 2, true);
1627 }
1628
ui_draw_but_COLORBAND(uiBut * but,const uiWidgetColors * UNUSED (wcol),const rcti * rect)1629 void ui_draw_but_COLORBAND(uiBut *but, const uiWidgetColors *UNUSED(wcol), const rcti *rect)
1630 {
1631 struct ColorManagedDisplay *display = ui_block_cm_display_get(but->block);
1632 uint pos_id, col_id;
1633
1634 uiButColorBand *but_coba = (uiButColorBand *)but;
1635 ColorBand *coba = (but_coba->edit_coba == NULL) ? (ColorBand *)but->poin : but_coba->edit_coba;
1636
1637 if (coba == NULL) {
1638 return;
1639 }
1640
1641 const float x1 = rect->xmin;
1642 const float sizex = rect->xmax - x1;
1643 const float sizey = BLI_rcti_size_y(rect);
1644 const float sizey_solid = sizey * 0.25f;
1645 const float y1 = rect->ymin;
1646
1647 /* exit early if too narrow */
1648 if (sizex <= 0) {
1649 return;
1650 }
1651
1652 GPUVertFormat *format = immVertexFormat();
1653 pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1654 immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
1655
1656 /* Drawing the checkerboard. */
1657 const float checker_dark = UI_ALPHA_CHECKER_DARK / 255.0f;
1658 const float checker_light = UI_ALPHA_CHECKER_LIGHT / 255.0f;
1659 immUniform4f("color1", checker_dark, checker_dark, checker_dark, 1.0f);
1660 immUniform4f("color2", checker_light, checker_light, checker_light, 1.0f);
1661 immUniform1i("size", 8);
1662 immRectf(pos_id, x1, y1, x1 + sizex, rect->ymax);
1663 immUnbindProgram();
1664
1665 /* New format */
1666 format = immVertexFormat();
1667 pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1668 col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1669 immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
1670
1671 /* layer: color ramp */
1672 GPU_blend(GPU_BLEND_ALPHA);
1673
1674 CBData *cbd = coba->data;
1675
1676 float v1[2], v2[2];
1677 float colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */
1678
1679 v1[1] = y1 + sizey_solid;
1680 v2[1] = rect->ymax;
1681
1682 immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
1683 for (int a = 0; a <= sizex; a++) {
1684 const float pos = ((float)a) / sizex;
1685 BKE_colorband_evaluate(coba, pos, colf);
1686 if (display) {
1687 IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1688 }
1689
1690 v1[0] = v2[0] = x1 + a;
1691
1692 immAttr4fv(col_id, colf);
1693 immVertex2fv(pos_id, v1);
1694 immVertex2fv(pos_id, v2);
1695 }
1696 immEnd();
1697
1698 /* layer: color ramp without alpha for reference when manipulating ramp properties */
1699 v1[1] = y1;
1700 v2[1] = y1 + sizey_solid;
1701
1702 immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
1703 for (int a = 0; a <= sizex; a++) {
1704 const float pos = ((float)a) / sizex;
1705 BKE_colorband_evaluate(coba, pos, colf);
1706 if (display) {
1707 IMB_colormanagement_scene_linear_to_display_v3(colf, display);
1708 }
1709
1710 v1[0] = v2[0] = x1 + a;
1711
1712 immAttr4f(col_id, colf[0], colf[1], colf[2], 1.0f);
1713 immVertex2fv(pos_id, v1);
1714 immVertex2fv(pos_id, v2);
1715 }
1716 immEnd();
1717
1718 immUnbindProgram();
1719
1720 GPU_blend(GPU_BLEND_NONE);
1721
1722 /* New format */
1723 format = immVertexFormat();
1724 pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1725 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1726
1727 /* layer: box outline */
1728 immUniformColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1729 imm_draw_box_wire_2d(pos_id, x1, y1, x1 + sizex, rect->ymax);
1730
1731 /* layer: box outline */
1732 GPU_blend(GPU_BLEND_ALPHA);
1733 immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
1734
1735 immBegin(GPU_PRIM_LINES, 2);
1736 immVertex2f(pos_id, x1, y1);
1737 immVertex2f(pos_id, x1 + sizex, y1);
1738 immEnd();
1739
1740 immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
1741
1742 immBegin(GPU_PRIM_LINES, 2);
1743 immVertex2f(pos_id, x1, y1 - 1);
1744 immVertex2f(pos_id, x1 + sizex, y1 - 1);
1745 immEnd();
1746
1747 GPU_blend(GPU_BLEND_NONE);
1748
1749 /* layer: draw handles */
1750 for (int a = 0; a < coba->tot; a++, cbd++) {
1751 if (a != coba->cur) {
1752 const float pos = x1 + cbd->pos * (sizex - 1) + 1;
1753 ui_draw_colorband_handle(pos_id, rect, pos, &cbd->r, display, false);
1754 }
1755 }
1756
1757 /* layer: active handle */
1758 if (coba->tot != 0) {
1759 cbd = &coba->data[coba->cur];
1760 const float pos = x1 + cbd->pos * (sizex - 1) + 1;
1761 ui_draw_colorband_handle(pos_id, rect, pos, &cbd->r, display, true);
1762 }
1763
1764 immUnbindProgram();
1765 }
1766
ui_draw_but_UNITVEC(uiBut * but,const uiWidgetColors * wcol,const rcti * rect)1767 void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
1768 {
1769 /* sphere color */
1770 const float diffuse[3] = {1.0f, 1.0f, 1.0f};
1771 float light[3];
1772 const float size = 0.5f * min_ff(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
1773
1774 /* backdrop */
1775 UI_draw_roundbox_corner_set(UI_CNR_ALL);
1776 UI_draw_roundbox_3ub_alpha(
1777 true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, wcol->inner, 255);
1778
1779 GPU_face_culling(GPU_CULL_BACK);
1780
1781 /* setup lights */
1782 ui_but_v3_get(but, light);
1783
1784 /* transform to button */
1785 GPU_matrix_push();
1786
1787 const bool use_project_matrix = (size >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT);
1788 if (use_project_matrix) {
1789 GPU_matrix_push_projection();
1790 GPU_matrix_ortho_set_z(-size, size);
1791 }
1792
1793 GPU_matrix_translate_2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect),
1794 rect->ymin + 0.5f * BLI_rcti_size_y(rect));
1795 GPU_matrix_scale_1f(size);
1796
1797 GPUBatch *sphere = GPU_batch_preset_sphere(2);
1798 GPU_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
1799 GPU_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
1800 GPU_batch_uniform_3fv(sphere, "light", light);
1801 GPU_batch_draw(sphere);
1802
1803 /* restore */
1804 GPU_face_culling(GPU_CULL_NONE);
1805
1806 /* AA circle */
1807 GPUVertFormat *format = immVertexFormat();
1808 const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1809 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1810 immUniformColor3ubv(wcol->inner);
1811
1812 GPU_blend(GPU_BLEND_ALPHA);
1813 GPU_line_smooth(true);
1814 imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32);
1815 GPU_blend(GPU_BLEND_NONE);
1816 GPU_line_smooth(false);
1817
1818 if (use_project_matrix) {
1819 GPU_matrix_pop_projection();
1820 }
1821
1822 /* matrix after circle */
1823 GPU_matrix_pop();
1824
1825 immUnbindProgram();
1826 }
1827
ui_draw_but_curve_grid(const uint pos,const rcti * rect,const float zoom_x,const float zoom_y,const float offset_x,const float offset_y,const float step)1828 static void ui_draw_but_curve_grid(const uint pos,
1829 const rcti *rect,
1830 const float zoom_x,
1831 const float zoom_y,
1832 const float offset_x,
1833 const float offset_y,
1834 const float step)
1835 {
1836 const float start_x = (ceilf(offset_x / step) * step - offset_x) * zoom_x + rect->xmin;
1837 const float start_y = (ceilf(offset_y / step) * step - offset_y) * zoom_y + rect->ymin;
1838
1839 const int line_count_x = ceilf((rect->xmax - start_x) / (step * zoom_x));
1840 const int line_count_y = ceilf((rect->ymax - start_y) / (step * zoom_y));
1841
1842 if (line_count_x + line_count_y == 0) {
1843 return;
1844 }
1845
1846 immBegin(GPU_PRIM_LINES, (line_count_x + line_count_y) * 2);
1847 for (int i = 0; i < line_count_x; i++) {
1848 const float x = start_x + i * step * zoom_x;
1849 immVertex2f(pos, x, rect->ymin);
1850 immVertex2f(pos, x, rect->ymax);
1851 }
1852 for (int i = 0; i < line_count_y; i++) {
1853 const float y = start_y + i * step * zoom_y;
1854 immVertex2f(pos, rect->xmin, y);
1855 immVertex2f(pos, rect->xmax, y);
1856 }
1857 immEnd();
1858 }
1859
gl_shaded_color_get(const uchar color[3],int shade,uchar r_color[3])1860 static void gl_shaded_color_get(const uchar color[3], int shade, uchar r_color[3])
1861 {
1862 r_color[0] = color[0] - shade > 0 ? color[0] - shade : 0;
1863 r_color[1] = color[1] - shade > 0 ? color[1] - shade : 0;
1864 r_color[2] = color[2] - shade > 0 ? color[2] - shade : 0;
1865 }
1866
gl_shaded_color_get_fl(const uchar * color,int shade,float r_color[3])1867 static void gl_shaded_color_get_fl(const uchar *color, int shade, float r_color[3])
1868 {
1869 uchar color_shaded[3];
1870 gl_shaded_color_get(color, shade, color_shaded);
1871 rgb_uchar_to_float(r_color, color_shaded);
1872 }
1873
gl_shaded_color(const uchar * color,int shade)1874 static void gl_shaded_color(const uchar *color, int shade)
1875 {
1876 uchar color_shaded[3];
1877 gl_shaded_color_get(color, shade, color_shaded);
1878 immUniformColor3ubv(color_shaded);
1879 }
1880
ui_draw_but_CURVE(ARegion * region,uiBut * but,const uiWidgetColors * wcol,const rcti * rect)1881 void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, const rcti *rect)
1882 {
1883 uiButCurveMapping *but_cumap = (uiButCurveMapping *)but;
1884 CurveMapping *cumap = (but_cumap->edit_cumap == NULL) ? (CurveMapping *)but->poin :
1885 but_cumap->edit_cumap;
1886
1887 const float clip_size_x = BLI_rctf_size_x(&cumap->curr);
1888 const float clip_size_y = BLI_rctf_size_y(&cumap->curr);
1889
1890 /* zero-sized curve */
1891 if (clip_size_x == 0.0f || clip_size_y == 0.0f) {
1892 return;
1893 }
1894
1895 /* calculate offset and zoom */
1896 const float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / clip_size_x;
1897 const float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / clip_size_y;
1898 const float offsx = cumap->curr.xmin - (1.0f / zoomx);
1899 const float offsy = cumap->curr.ymin - (1.0f / zoomy);
1900
1901 /* exit early if too narrow */
1902 if (zoomx == 0.0f) {
1903 return;
1904 }
1905
1906 CurveMap *cuma = &cumap->cm[cumap->cur];
1907
1908 /* need scissor test, curve can draw outside of boundary */
1909 int scissor[4];
1910 GPU_scissor_get(scissor);
1911 rcti scissor_new = {
1912 .xmin = rect->xmin,
1913 .ymin = rect->ymin,
1914 .xmax = rect->xmax,
1915 .ymax = rect->ymax,
1916 };
1917 const rcti scissor_region = {0, region->winx, 0, region->winy};
1918 BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
1919 GPU_scissor(scissor_new.xmin,
1920 scissor_new.ymin,
1921 BLI_rcti_size_x(&scissor_new),
1922 BLI_rcti_size_y(&scissor_new));
1923
1924 /* Do this first to not mess imm context */
1925 if (but_cumap->gradient_type == UI_GRAD_H) {
1926 /* magic trigger for curve backgrounds */
1927 const float col[3] = {0.0f, 0.0f, 0.0f}; /* dummy arg */
1928
1929 rcti grid = {
1930 .xmin = rect->xmin + zoomx * (-offsx),
1931 .xmax = grid.xmin + zoomx,
1932 .ymin = rect->ymin + zoomy * (-offsy),
1933 .ymax = grid.ymin + zoomy,
1934 };
1935
1936 ui_draw_gradient(&grid, col, UI_GRAD_H, 1.0f);
1937 }
1938
1939 GPU_line_width(1.0f);
1940
1941 GPUVertFormat *format = immVertexFormat();
1942 uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1943 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1944
1945 /* backdrop */
1946 float color_backdrop[4] = {0, 0, 0, 1};
1947
1948 if (but_cumap->gradient_type == UI_GRAD_H) {
1949 /* grid, hsv uses different grid */
1950 GPU_blend(GPU_BLEND_ALPHA);
1951 ARRAY_SET_ITEMS(color_backdrop, 0, 0, 0, 48.0 / 255.0);
1952 immUniformColor4fv(color_backdrop);
1953 ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f);
1954 GPU_blend(GPU_BLEND_NONE);
1955 }
1956 else {
1957 if (cumap->flag & CUMA_DO_CLIP) {
1958 gl_shaded_color_get_fl(wcol->inner, -20, color_backdrop);
1959 immUniformColor3fv(color_backdrop);
1960 immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1961 immUniformColor3ubv(wcol->inner);
1962 immRectf(pos,
1963 rect->xmin + zoomx * (cumap->clipr.xmin - offsx),
1964 rect->ymin + zoomy * (cumap->clipr.ymin - offsy),
1965 rect->xmin + zoomx * (cumap->clipr.xmax - offsx),
1966 rect->ymin + zoomy * (cumap->clipr.ymax - offsy));
1967 }
1968 else {
1969 rgb_uchar_to_float(color_backdrop, wcol->inner);
1970 immUniformColor3fv(color_backdrop);
1971 immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1972 }
1973
1974 /* grid, every 0.25 step */
1975 gl_shaded_color(wcol->inner, -16);
1976 ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f);
1977 /* grid, every 1.0 step */
1978 gl_shaded_color(wcol->inner, -24);
1979 ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
1980 /* axes */
1981 gl_shaded_color(wcol->inner, -50);
1982 immBegin(GPU_PRIM_LINES, 4);
1983 immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy));
1984 immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy));
1985 immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymin);
1986 immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax);
1987 immEnd();
1988 }
1989
1990 /* cfra option */
1991 /* XXX 2.48 */
1992 #if 0
1993 if (cumap->flag & CUMA_DRAW_CFRA) {
1994 immUniformColor3ub(0x60, 0xc0, 0x40);
1995 immBegin(GPU_PRIM_LINES, 2);
1996 immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymin);
1997 immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[0] - offsx), rect->ymax);
1998 immEnd();
1999 }
2000 #endif
2001 /* sample option */
2002
2003 if (cumap->flag & CUMA_DRAW_SAMPLE) {
2004 immBegin(GPU_PRIM_LINES, 2); /* will draw one of the following 3 lines */
2005 if (but_cumap->gradient_type == UI_GRAD_H) {
2006 float tsample[3];
2007 float hsv[3];
2008 linearrgb_to_srgb_v3_v3(tsample, cumap->sample);
2009 rgb_to_hsv_v(tsample, hsv);
2010 immUniformColor3ub(240, 240, 240);
2011
2012 immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymin);
2013 immVertex2f(pos, rect->xmin + zoomx * (hsv[0] - offsx), rect->ymax);
2014 }
2015 else if (cumap->cur == 3) {
2016 const float lum = IMB_colormanagement_get_luminance(cumap->sample);
2017 immUniformColor3ub(240, 240, 240);
2018
2019 immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymin);
2020 immVertex2f(pos, rect->xmin + zoomx * (lum - offsx), rect->ymax);
2021 }
2022 else {
2023 if (cumap->cur == 0) {
2024 immUniformColor3ub(240, 100, 100);
2025 }
2026 else if (cumap->cur == 1) {
2027 immUniformColor3ub(100, 240, 100);
2028 }
2029 else {
2030 immUniformColor3ub(100, 100, 240);
2031 }
2032
2033 immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymin);
2034 immVertex2f(pos, rect->xmin + zoomx * (cumap->sample[cumap->cur] - offsx), rect->ymax);
2035 }
2036 immEnd();
2037 }
2038 immUnbindProgram();
2039
2040 if (cuma->table == NULL) {
2041 BKE_curvemapping_changed(cumap, false);
2042 }
2043
2044 CurveMapPoint *cmp = cuma->table;
2045 rctf line_range;
2046
2047 /* First curve point. */
2048 if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
2049 line_range.xmin = rect->xmin;
2050 line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy);
2051 }
2052 else {
2053 line_range.xmin = rect->xmin + zoomx * (cmp[0].x - offsx + cuma->ext_in[0]);
2054 line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]);
2055 }
2056 /* Last curve point. */
2057 if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
2058 line_range.xmax = rect->xmax;
2059 line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy);
2060 }
2061 else {
2062 line_range.xmax = rect->xmin + zoomx * (cmp[CM_TABLE].x - offsx - cuma->ext_out[0]);
2063 line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]);
2064 }
2065
2066 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
2067 GPU_blend(GPU_BLEND_ALPHA);
2068
2069 /* Curve filled. */
2070 immUniformColor3ubvAlpha(wcol->item, 128);
2071 immBegin(GPU_PRIM_TRI_STRIP, (CM_TABLE * 2 + 2) + 4);
2072 immVertex2f(pos, line_range.xmin, rect->ymin);
2073 immVertex2f(pos, line_range.xmin, line_range.ymin);
2074 for (int a = 0; a <= CM_TABLE; a++) {
2075 const float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
2076 const float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
2077 immVertex2f(pos, fx, rect->ymin);
2078 immVertex2f(pos, fx, fy);
2079 }
2080 immVertex2f(pos, line_range.xmax, rect->ymin);
2081 immVertex2f(pos, line_range.xmax, line_range.ymax);
2082 immEnd();
2083
2084 /* Curve line. */
2085 GPU_line_width(1.0f);
2086 immUniformColor3ubvAlpha(wcol->item, 255);
2087 GPU_line_smooth(true);
2088 immBegin(GPU_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
2089 immVertex2f(pos, line_range.xmin, line_range.ymin);
2090 for (int a = 0; a <= CM_TABLE; a++) {
2091 const float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
2092 const float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
2093 immVertex2f(pos, fx, fy);
2094 }
2095 immVertex2f(pos, line_range.xmax, line_range.ymax);
2096 immEnd();
2097
2098 /* Reset state for fill & line. */
2099 GPU_line_smooth(false);
2100 GPU_blend(GPU_BLEND_NONE);
2101 immUnbindProgram();
2102
2103 /* The points, use aspect to make them visible on edges. */
2104 format = immVertexFormat();
2105 pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2106 const uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
2107 immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
2108
2109 /* Calculate vertex colors based on text theme. */
2110 float color_vert[4], color_vert_select[4];
2111 UI_GetThemeColor4fv(TH_TEXT_HI, color_vert);
2112 UI_GetThemeColor4fv(TH_TEXT, color_vert_select);
2113 if (len_squared_v3v3(color_vert, color_vert_select) < 0.1f) {
2114 interp_v3_v3v3(color_vert, color_vert_select, color_backdrop, 0.75f);
2115 }
2116 if (len_squared_v3(color_vert) > len_squared_v3(color_vert_select)) {
2117 /* Ensure brightest text color is used for selection. */
2118 swap_v3_v3(color_vert, color_vert_select);
2119 }
2120
2121 cmp = cuma->curve;
2122 GPU_point_size(max_ff(1.0f, min_ff(UI_DPI_FAC / but->block->aspect * 4.0f, 4.0f)));
2123 immBegin(GPU_PRIM_POINTS, cuma->totpoint);
2124 for (int a = 0; a < cuma->totpoint; a++) {
2125 const float fx = rect->xmin + zoomx * (cmp[a].x - offsx);
2126 const float fy = rect->ymin + zoomy * (cmp[a].y - offsy);
2127 immAttr4fv(col, (cmp[a].flag & CUMA_SELECT) ? color_vert_select : color_vert);
2128 immVertex2f(pos, fx, fy);
2129 }
2130 immEnd();
2131 immUnbindProgram();
2132
2133 /* restore scissortest */
2134 GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
2135
2136 /* outline */
2137 format = immVertexFormat();
2138 pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2139 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
2140
2141 immUniformColor3ubv(wcol->outline);
2142 imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
2143
2144 immUnbindProgram();
2145 }
2146
2147 /**
2148 * Helper for #ui_draw_but_CURVEPROFILE. Used to tell whether to draw a control point's handles.
2149 */
point_draw_handles(CurveProfilePoint * point)2150 static bool point_draw_handles(CurveProfilePoint *point)
2151 {
2152 return (point->flag & PROF_SELECT &&
2153 (ELEM(point->h1, HD_FREE, HD_ALIGN) || ELEM(point->h2, HD_FREE, HD_ALIGN))) ||
2154 ELEM(point->flag, PROF_H1_SELECT, PROF_H2_SELECT);
2155 }
2156
2157 /**
2158 * Draws the curve profile widget. Somewhat similar to ui_draw_but_CURVE.
2159 */
ui_draw_but_CURVEPROFILE(ARegion * region,uiBut * but,const uiWidgetColors * wcol,const rcti * rect)2160 void ui_draw_but_CURVEPROFILE(ARegion *region,
2161 uiBut *but,
2162 const uiWidgetColors *wcol,
2163 const rcti *rect)
2164 {
2165 float fx, fy;
2166
2167 uiButCurveProfile *but_profile = (uiButCurveProfile *)but;
2168 CurveProfile *profile = (but_profile->edit_profile == NULL) ? (CurveProfile *)but->poin :
2169 but_profile->edit_profile;
2170
2171 /* Calculate offset and zoom. */
2172 const float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&profile->view_rect);
2173 const float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&profile->view_rect);
2174 const float offsx = profile->view_rect.xmin - (1.0f / zoomx);
2175 const float offsy = profile->view_rect.ymin - (1.0f / zoomy);
2176
2177 /* Exit early if too narrow. */
2178 if (zoomx == 0.0f) {
2179 return;
2180 }
2181
2182 /* Test needed because path can draw outside of boundary. */
2183 int scissor[4];
2184 GPU_scissor_get(scissor);
2185 rcti scissor_new = {
2186 .xmin = rect->xmin,
2187 .ymin = rect->ymin,
2188 .xmax = rect->xmax,
2189 .ymax = rect->ymax,
2190 };
2191 const rcti scissor_region = {0, region->winx, 0, region->winy};
2192 BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new);
2193 GPU_scissor(scissor_new.xmin,
2194 scissor_new.ymin,
2195 BLI_rcti_size_x(&scissor_new),
2196 BLI_rcti_size_y(&scissor_new));
2197
2198 GPU_line_width(1.0f);
2199
2200 GPUVertFormat *format = immVertexFormat();
2201 uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2202 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
2203
2204 /* Draw the backdrop. */
2205 float color_backdrop[4] = {0, 0, 0, 1};
2206 if (profile->flag & PROF_USE_CLIP) {
2207 gl_shaded_color_get_fl((uchar *)wcol->inner, -20, color_backdrop);
2208 immUniformColor3fv(color_backdrop);
2209 immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
2210 immUniformColor3ubv((uchar *)wcol->inner);
2211 immRectf(pos,
2212 rect->xmin + zoomx * (profile->clip_rect.xmin - offsx),
2213 rect->ymin + zoomy * (profile->clip_rect.ymin - offsy),
2214 rect->xmin + zoomx * (profile->clip_rect.xmax - offsx),
2215 rect->ymin + zoomy * (profile->clip_rect.ymax - offsy));
2216 }
2217 else {
2218 rgb_uchar_to_float(color_backdrop, (uchar *)wcol->inner);
2219 immUniformColor3fv(color_backdrop);
2220 immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
2221 }
2222
2223 /* 0.25 step grid. */
2224 gl_shaded_color((uchar *)wcol->inner, -16);
2225 ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f);
2226 /* 1.0 step grid. */
2227 gl_shaded_color((uchar *)wcol->inner, -24);
2228 ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f);
2229
2230 /* Draw the path's fill. */
2231 if (profile->table == NULL) {
2232 BKE_curveprofile_update(profile, PROF_UPDATE_NONE);
2233 }
2234 CurveProfilePoint *pts = profile->table;
2235 /* Also add the last points on the right and bottom edges to close off the fill polygon. */
2236 const bool add_left_tri = profile->view_rect.xmin < 0.0f;
2237 const bool add_bottom_tri = profile->view_rect.ymin < 0.0f;
2238 uint tot_points = (uint)PROF_TABLE_LEN(profile->path_len) + 1 + add_left_tri + add_bottom_tri;
2239 const uint tot_triangles = tot_points - 2;
2240
2241 /* Create array of the positions of the table's points. */
2242 float(*table_coords)[2] = MEM_mallocN(sizeof(*table_coords) * tot_points, "table x coords");
2243 for (uint i = 0; i < (uint)PROF_TABLE_LEN(profile->path_len);
2244 i++) { /* Only add the points from the table here. */
2245 table_coords[i][0] = pts[i].x;
2246 table_coords[i][1] = pts[i].y;
2247 }
2248 if (add_left_tri && add_bottom_tri) {
2249 /* Add left side, bottom left corner, and bottom side points. */
2250 table_coords[tot_points - 3][0] = profile->view_rect.xmin;
2251 table_coords[tot_points - 3][1] = 1.0f;
2252 table_coords[tot_points - 2][0] = profile->view_rect.xmin;
2253 table_coords[tot_points - 2][1] = profile->view_rect.ymin;
2254 table_coords[tot_points - 1][0] = 1.0f;
2255 table_coords[tot_points - 1][1] = profile->view_rect.ymin;
2256 }
2257 else if (add_left_tri) {
2258 /* Add the left side and bottom left corner points. */
2259 table_coords[tot_points - 2][0] = profile->view_rect.xmin;
2260 table_coords[tot_points - 2][1] = 1.0f;
2261 table_coords[tot_points - 1][0] = profile->view_rect.xmin;
2262 table_coords[tot_points - 1][1] = 0.0f;
2263 }
2264 else if (add_bottom_tri) {
2265 /* Add the bottom side and bottom left corner points. */
2266 table_coords[tot_points - 2][0] = 0.0f;
2267 table_coords[tot_points - 2][1] = profile->view_rect.ymin;
2268 table_coords[tot_points - 1][0] = 1.0f;
2269 table_coords[tot_points - 1][1] = profile->view_rect.ymin;
2270 }
2271 else {
2272 /* Just add the bottom corner point. Side points would be redundant anyway. */
2273 table_coords[tot_points - 1][0] = 0.0f;
2274 table_coords[tot_points - 1][1] = 0.0f;
2275 }
2276
2277 /* Calculate the table point indices of the triangles for the profile's fill. */
2278 uint(*tri_indices)[3] = MEM_mallocN(sizeof(*tri_indices) * tot_triangles, "return tri indices");
2279 BLI_polyfill_calc(table_coords, tot_points, -1, tri_indices);
2280
2281 /* Draw the triangles for the profile fill. */
2282 immUniformColor3ubvAlpha((const uchar *)wcol->item, 128);
2283 GPU_blend(GPU_BLEND_ALPHA);
2284 GPU_polygon_smooth(false);
2285 immBegin(GPU_PRIM_TRIS, 3 * tot_triangles);
2286 for (uint i = 0; i < tot_triangles; i++) {
2287 for (uint j = 0; j < 3; j++) {
2288 uint *tri = tri_indices[i];
2289 fx = rect->xmin + zoomx * (table_coords[tri[j]][0] - offsx);
2290 fy = rect->ymin + zoomy * (table_coords[tri[j]][1] - offsy);
2291 immVertex2f(pos, fx, fy);
2292 }
2293 }
2294 immEnd();
2295 MEM_freeN(tri_indices);
2296
2297 /* Draw the profile's path so the edge stands out a bit. */
2298 tot_points -= (add_left_tri + add_left_tri);
2299 GPU_line_width(1.0f);
2300 immUniformColor3ubvAlpha((const uchar *)wcol->item, 255);
2301 GPU_line_smooth(true);
2302 immBegin(GPU_PRIM_LINE_STRIP, tot_points - 1);
2303 for (uint i = 0; i < tot_points - 1; i++) {
2304 fx = rect->xmin + zoomx * (table_coords[i][0] - offsx);
2305 fy = rect->ymin + zoomy * (table_coords[i][1] - offsy);
2306 immVertex2f(pos, fx, fy);
2307 }
2308 immEnd();
2309 MEM_freeN(table_coords);
2310
2311 /* Draw the handles for the selected control points. */
2312 pts = profile->path;
2313 tot_points = (uint)profile->path_len;
2314 int selected_free_points = 0;
2315 for (uint i = 0; i < tot_points; i++) {
2316 if (point_draw_handles(&pts[i])) {
2317 selected_free_points++;
2318 }
2319 }
2320 /* Draw the lines to the handles from the points. */
2321 if (selected_free_points > 0) {
2322 GPU_line_width(1.0f);
2323 gl_shaded_color((uchar *)wcol->inner, -24);
2324 GPU_line_smooth(true);
2325 immBegin(GPU_PRIM_LINES, selected_free_points * 4);
2326 float ptx, pty;
2327 for (uint i = 0; i < tot_points; i++) {
2328 if (point_draw_handles(&pts[i])) {
2329 ptx = rect->xmin + zoomx * (pts[i].x - offsx);
2330 pty = rect->ymin + zoomy * (pts[i].y - offsy);
2331
2332 fx = rect->xmin + zoomx * (pts[i].h1_loc[0] - offsx);
2333 fy = rect->ymin + zoomy * (pts[i].h1_loc[1] - offsy);
2334 immVertex2f(pos, ptx, pty);
2335 immVertex2f(pos, fx, fy);
2336
2337 fx = rect->xmin + zoomx * (pts[i].h2_loc[0] - offsx);
2338 fy = rect->ymin + zoomy * (pts[i].h2_loc[1] - offsy);
2339 immVertex2f(pos, ptx, pty);
2340 immVertex2f(pos, fx, fy);
2341 }
2342 }
2343 immEnd();
2344 }
2345 immUnbindProgram();
2346
2347 /* New GPU instructions for control points and sampled points. */
2348 format = immVertexFormat();
2349 pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2350 const uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
2351 immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
2352
2353 /* Calculate vertex colors based on text theme. */
2354 float color_vert[4], color_vert_select[4], color_sample[4];
2355 UI_GetThemeColor4fv(TH_TEXT_HI, color_vert);
2356 UI_GetThemeColor4fv(TH_TEXT, color_vert_select);
2357 color_sample[0] = (float)wcol->item[0] / 255.0f;
2358 color_sample[1] = (float)wcol->item[1] / 255.0f;
2359 color_sample[2] = (float)wcol->item[2] / 255.0f;
2360 color_sample[3] = (float)wcol->item[3] / 255.0f;
2361 if (len_squared_v3v3(color_vert, color_vert_select) < 0.1f) {
2362 interp_v3_v3v3(color_vert, color_vert_select, color_backdrop, 0.75f);
2363 }
2364 if (len_squared_v3(color_vert) > len_squared_v3(color_vert_select)) {
2365 /* Ensure brightest text color is used for selection. */
2366 swap_v3_v3(color_vert, color_vert_select);
2367 }
2368
2369 /* Draw the control points. */
2370 GPU_line_smooth(false);
2371 GPU_blend(GPU_BLEND_NONE);
2372 GPU_point_size(max_ff(3.0f, min_ff(UI_DPI_FAC / but->block->aspect * 5.0f, 5.0f)));
2373 immBegin(GPU_PRIM_POINTS, tot_points);
2374 for (uint i = 0; i < tot_points; i++) {
2375 fx = rect->xmin + zoomx * (pts[i].x - offsx);
2376 fy = rect->ymin + zoomy * (pts[i].y - offsy);
2377 immAttr4fv(col, (pts[i].flag & PROF_SELECT) ? color_vert_select : color_vert);
2378 immVertex2f(pos, fx, fy);
2379 }
2380 immEnd();
2381
2382 /* Draw the handle points. */
2383 if (selected_free_points > 0) {
2384 GPU_line_smooth(false);
2385 GPU_blend(GPU_BLEND_NONE);
2386 GPU_point_size(max_ff(2.0f, min_ff(UI_DPI_FAC / but->block->aspect * 4.0f, 4.0f)));
2387 immBegin(GPU_PRIM_POINTS, selected_free_points * 2);
2388 for (uint i = 0; i < tot_points; i++) {
2389 if (point_draw_handles(&pts[i])) {
2390 fx = rect->xmin + zoomx * (pts[i].h1_loc[0] - offsx);
2391 fy = rect->ymin + zoomy * (pts[i].h1_loc[1] - offsy);
2392 immAttr4fv(col, (pts[i].flag & PROF_H1_SELECT) ? color_vert_select : color_vert);
2393 immVertex2f(pos, fx, fy);
2394
2395 fx = rect->xmin + zoomx * (pts[i].h2_loc[0] - offsx);
2396 fy = rect->ymin + zoomy * (pts[i].h2_loc[1] - offsy);
2397 immAttr4fv(col, (pts[i].flag & PROF_H2_SELECT) ? color_vert_select : color_vert);
2398 immVertex2f(pos, fx, fy);
2399 }
2400 }
2401 immEnd();
2402 }
2403
2404 /* Draw the sampled points in addition to the control points if they have been created */
2405 pts = profile->segments;
2406 tot_points = (uint)profile->segments_len;
2407 if (tot_points > 0 && pts) {
2408 GPU_point_size(max_ff(2.0f, min_ff(UI_DPI_FAC / but->block->aspect * 3.0f, 3.0f)));
2409 immBegin(GPU_PRIM_POINTS, tot_points);
2410 for (uint i = 0; i < tot_points; i++) {
2411 fx = rect->xmin + zoomx * (pts[i].x - offsx);
2412 fy = rect->ymin + zoomy * (pts[i].y - offsy);
2413 immAttr4fv(col, color_sample);
2414 immVertex2f(pos, fx, fy);
2415 }
2416 immEnd();
2417 }
2418 immUnbindProgram();
2419
2420 /* restore scissortest */
2421 GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]);
2422
2423 /* Outline */
2424 format = immVertexFormat();
2425 pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2426 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
2427
2428 immUniformColor3ubv((const uchar *)wcol->outline);
2429 imm_draw_box_wire_2d(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
2430
2431 immUnbindProgram();
2432 }
2433
ui_draw_but_TRACKPREVIEW(ARegion * UNUSED (region),uiBut * but,const uiWidgetColors * UNUSED (wcol),const rcti * recti)2434 void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region),
2435 uiBut *but,
2436 const uiWidgetColors *UNUSED(wcol),
2437 const rcti *recti)
2438 {
2439 bool ok = false;
2440 MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
2441
2442 rctf rect = {
2443 .xmin = (float)recti->xmin + 1,
2444 .xmax = (float)recti->xmax - 1,
2445 .ymin = (float)recti->ymin + 1,
2446 .ymax = (float)recti->ymax - 1,
2447 };
2448
2449 const int width = BLI_rctf_size_x(&rect) + 1;
2450 const int height = BLI_rctf_size_y(&rect);
2451
2452 GPU_blend(GPU_BLEND_ALPHA);
2453
2454 /* need scissor test, preview image can draw outside of boundary */
2455 int scissor[4];
2456 GPU_scissor_get(scissor);
2457 GPU_scissor((rect.xmin - 1),
2458 (rect.ymin - 1),
2459 (rect.xmax + 1) - (rect.xmin - 1),
2460 (rect.ymax + 1) - (rect.ymin - 1));
2461
2462 if (scopes->track_disabled) {
2463 const float color[4] = {0.7f, 0.3f, 0.3f, 0.3f};
2464 UI_draw_roundbox_corner_set(UI_CNR_ALL);
2465 UI_draw_roundbox_4fv(
2466 true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
2467
2468 ok = true;
2469 }
2470 else if ((scopes->track_search) &&
2471 ((!scopes->track_preview) ||
2472 (scopes->track_preview->x != width || scopes->track_preview->y != height))) {
2473 if (scopes->track_preview) {
2474 IMB_freeImBuf(scopes->track_preview);
2475 }
2476
2477 ImBuf *tmpibuf = BKE_tracking_sample_pattern(scopes->frame_width,
2478 scopes->frame_height,
2479 scopes->track_search,
2480 scopes->track,
2481 &scopes->undist_marker,
2482 true,
2483 scopes->use_track_mask,
2484 width,
2485 height,
2486 scopes->track_pos);
2487 if (tmpibuf) {
2488 if (tmpibuf->rect_float) {
2489 IMB_rect_from_float(tmpibuf);
2490 }
2491
2492 if (tmpibuf->rect) {
2493 scopes->track_preview = tmpibuf;
2494 }
2495 else {
2496 IMB_freeImBuf(tmpibuf);
2497 }
2498 }
2499 }
2500
2501 if (!ok && scopes->track_preview) {
2502 GPU_matrix_push();
2503
2504 /* draw content of pattern area */
2505 GPU_scissor(rect.xmin, rect.ymin, scissor[2], scissor[3]);
2506
2507 if (width > 0 && height > 0) {
2508 ImBuf *drawibuf = scopes->track_preview;
2509 float col_sel[4], col_outline[4];
2510
2511 if (scopes->use_track_mask) {
2512 const float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
2513 UI_draw_roundbox_corner_set(UI_CNR_ALL);
2514 UI_draw_roundbox_4fv(
2515 true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
2516 }
2517
2518 IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
2519 immDrawPixelsTex(&state,
2520 rect.xmin,
2521 rect.ymin + 1,
2522 drawibuf->x,
2523 drawibuf->y,
2524 GPU_RGBA8,
2525 true,
2526 drawibuf->rect,
2527 1.0f,
2528 1.0f,
2529 NULL);
2530
2531 /* draw cross for pixel position */
2532 GPU_matrix_translate_2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
2533 GPU_scissor(rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect));
2534
2535 GPUVertFormat *format = immVertexFormat();
2536 const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2537 const uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
2538 immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
2539
2540 UI_GetThemeColor4fv(TH_SEL_MARKER, col_sel);
2541 UI_GetThemeColor4fv(TH_MARKER_OUTLINE, col_outline);
2542
2543 /* Do stipple cross with geometry */
2544 immBegin(GPU_PRIM_LINES, 7 * 2 * 2);
2545 const float pos_sel[8] = {-10.0f, -7.0f, -4.0f, -1.0f, 2.0f, 5.0f, 8.0f, 11.0f};
2546 for (int axe = 0; axe < 2; axe++) {
2547 for (int i = 0; i < 7; i++) {
2548 const float x1 = pos_sel[i] * (1 - axe);
2549 const float y1 = pos_sel[i] * axe;
2550 const float x2 = pos_sel[i + 1] * (1 - axe);
2551 const float y2 = pos_sel[i + 1] * axe;
2552
2553 if (i % 2 == 1) {
2554 immAttr4fv(col, col_sel);
2555 }
2556 else {
2557 immAttr4fv(col, col_outline);
2558 }
2559
2560 immVertex2f(pos, x1, y1);
2561 immVertex2f(pos, x2, y2);
2562 }
2563 }
2564 immEnd();
2565
2566 immUnbindProgram();
2567 }
2568
2569 GPU_matrix_pop();
2570
2571 ok = true;
2572 }
2573
2574 if (!ok) {
2575 const float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
2576 UI_draw_roundbox_corner_set(UI_CNR_ALL);
2577 UI_draw_roundbox_4fv(
2578 true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
2579 }
2580
2581 /* Restore scissor test. */
2582 GPU_scissor(UNPACK4(scissor));
2583 /* outline */
2584 draw_scope_end(&rect);
2585
2586 GPU_blend(GPU_BLEND_NONE);
2587 }
2588
2589 /* ****************************************************** */
2590
2591 /* TODO: high quality UI drop shadows using GLSL shader and single draw call
2592 * would replace / modify the following 3 functions - merwin
2593 */
2594
ui_shadowbox(uint pos,uint color,float minx,float miny,float maxx,float maxy,float shadsize,uchar alpha)2595 static void ui_shadowbox(uint pos,
2596 uint color,
2597 float minx,
2598 float miny,
2599 float maxx,
2600 float maxy,
2601 float shadsize,
2602 uchar alpha)
2603 {
2604 /**
2605 * <pre>
2606 * v1-_
2607 * | -_v2
2608 * | |
2609 * | |
2610 * | |
2611 * v7_______v3____v4
2612 * \ | /
2613 * \ | _v5
2614 * v8______v6_-
2615 * </pre>
2616 */
2617 const float v1[2] = {maxx, maxy - 0.3f * shadsize};
2618 const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize};
2619 const float v3[2] = {maxx, miny};
2620 const float v4[2] = {maxx + shadsize, miny};
2621
2622 const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize};
2623
2624 const float v6[2] = {maxx, miny - shadsize};
2625 const float v7[2] = {minx + 0.3f * shadsize, miny};
2626 const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize};
2627
2628 /* right quad */
2629 immAttr4ub(color, 0, 0, 0, alpha);
2630 immVertex2fv(pos, v3);
2631 immVertex2fv(pos, v1);
2632 immAttr4ub(color, 0, 0, 0, 0);
2633 immVertex2fv(pos, v2);
2634
2635 immVertex2fv(pos, v2);
2636 immVertex2fv(pos, v4);
2637 immAttr4ub(color, 0, 0, 0, alpha);
2638 immVertex2fv(pos, v3);
2639
2640 /* corner shape */
2641 /* immAttr4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
2642 immVertex2fv(pos, v3);
2643 immAttr4ub(color, 0, 0, 0, 0);
2644 immVertex2fv(pos, v4);
2645 immVertex2fv(pos, v5);
2646
2647 immVertex2fv(pos, v5);
2648 immVertex2fv(pos, v6);
2649 immAttr4ub(color, 0, 0, 0, alpha);
2650 immVertex2fv(pos, v3);
2651
2652 /* bottom quad */
2653 /* immAttr4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
2654 immVertex2fv(pos, v3);
2655 immAttr4ub(color, 0, 0, 0, 0);
2656 immVertex2fv(pos, v6);
2657 immVertex2fv(pos, v8);
2658
2659 immVertex2fv(pos, v8);
2660 immAttr4ub(color, 0, 0, 0, alpha);
2661 immVertex2fv(pos, v7);
2662 immVertex2fv(pos, v3);
2663 }
2664
UI_draw_box_shadow(uchar alpha,float minx,float miny,float maxx,float maxy)2665 void UI_draw_box_shadow(uchar alpha, float minx, float miny, float maxx, float maxy)
2666 {
2667 GPU_blend(GPU_BLEND_ALPHA);
2668
2669 GPUVertFormat *format = immVertexFormat();
2670 const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2671 uint color = GPU_vertformat_attr_add(
2672 format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
2673
2674 immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
2675
2676 immBegin(GPU_PRIM_TRIS, 54);
2677
2678 /* accumulated outline boxes to make shade not linear, is more pleasant */
2679 ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
2680 ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
2681 ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
2682
2683 immEnd();
2684
2685 immUnbindProgram();
2686
2687 GPU_blend(GPU_BLEND_NONE);
2688 }
2689
ui_draw_dropshadow(const rctf * rct,float radius,float aspect,float alpha,int UNUSED (select))2690 void ui_draw_dropshadow(
2691 const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select))
2692 {
2693 float rad;
2694
2695 if (radius > (BLI_rctf_size_y(rct) - 10.0f) * 0.5f) {
2696 rad = (BLI_rctf_size_y(rct) - 10.0f) * 0.5f;
2697 }
2698 else {
2699 rad = radius;
2700 }
2701
2702 int a, i = 12;
2703 #if 0
2704 if (select) {
2705 a = i * aspect; /* same as below */
2706 }
2707 else
2708 #endif
2709 {
2710 a = i * aspect;
2711 }
2712
2713 GPU_blend(GPU_BLEND_ALPHA);
2714 const float dalpha = alpha * 2.0f / 255.0f;
2715 float calpha = dalpha;
2716 float visibility = 1.0f;
2717 for (; i--;) {
2718 /* alpha ranges from 2 to 20 or so */
2719 #if 0 /* Old Method (pre 2.8) */
2720 float color[4] = {0.0f, 0.0f, 0.0f, calpha};
2721 UI_draw_roundbox_4fv(
2722 true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
2723 #endif
2724 /* Compute final visibility to match old method result. */
2725 /* TODO we could just find a better fit function inside the shader instead of this. */
2726 visibility = visibility * (1.0f - calpha);
2727 calpha += dalpha;
2728 }
2729
2730 uiWidgetBaseParameters widget_params = {
2731 .recti.xmin = rct->xmin,
2732 .recti.ymin = rct->ymin,
2733 .recti.xmax = rct->xmax,
2734 .recti.ymax = rct->ymax - 10.0f,
2735 .rect.xmin = rct->xmin - a,
2736 .rect.ymin = rct->ymin - a,
2737 .rect.xmax = rct->xmax + a,
2738 .rect.ymax = rct->ymax - 10.0f + a,
2739 .radi = rad,
2740 .rad = rad + a,
2741 .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
2742 .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
2743 .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
2744 .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
2745 .alpha_discard = 1.0f,
2746 };
2747
2748 GPUBatch *batch = ui_batch_roundbox_shadow_get();
2749 GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW);
2750 GPU_batch_uniform_4fv_array(batch, "parameters", 4, (float(*)[4]) & widget_params);
2751 GPU_batch_uniform_1f(batch, "alpha", 1.0f - visibility);
2752 GPU_batch_draw(batch);
2753
2754 /* outline emphasis */
2755 const float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
2756 UI_draw_roundbox_4fv(false,
2757 rct->xmin - 0.5f,
2758 rct->ymin - 0.5f,
2759 rct->xmax + 0.5f,
2760 rct->ymax + 0.5f,
2761 radius + 0.5f,
2762 color);
2763
2764 GPU_blend(GPU_BLEND_NONE);
2765 }
2766