Blender V4.5
screen_draw.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "ED_screen.hh"
10#include "ED_screen_types.hh"
11
12#include "GPU_batch_presets.hh"
13#include "GPU_immediate.hh"
14#include "GPU_platform.hh"
15#include "GPU_state.hh"
16
17#include "BKE_global.hh"
18#include "BKE_screen.hh"
19
20#include "BLF_api.hh"
21
22#include "BLI_listbase.h"
23#include "BLI_math_vector.h"
24#include "BLI_rect.h"
25
26#include "BLT_translation.hh"
27
28#include "WM_api.hh"
29
30#include "UI_interface.hh"
31#include "UI_resources.hh"
32
33#include "screen_intern.hh"
34
35#define CORNER_RESOLUTION 3
36
37static void do_vert_pair(blender::gpu::VertBuf *vbo, uint pos, uint *vidx, int corner, int i)
38{
39 float inter[2];
40 inter[0] = cosf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
41 inter[1] = sinf(corner * M_PI_2 + (i * M_PI_2 / (CORNER_RESOLUTION - 1.0f)));
42
43 /* Snap point to edge */
44 float div = 1.0f / max_ff(fabsf(inter[0]), fabsf(inter[1]));
45 float exter[2];
46 mul_v2_v2fl(exter, inter, div);
47 exter[0] = roundf(exter[0]);
48 exter[1] = roundf(exter[1]);
49
50 if (i == 0 || i == (CORNER_RESOLUTION - 1)) {
51 copy_v2_v2(inter, exter);
52 }
53
54 /* Small offset to be able to tell inner and outer vertex apart inside the shader.
55 * Edge width is specified in the shader. */
56 mul_v2_fl(inter, 1.0f - 0.0001f);
57 mul_v2_fl(exter, 1.0f);
58
59 GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, inter);
60 GPU_vertbuf_attr_set(vbo, pos, (*vidx)++, exter);
61}
62
63static blender::gpu::Batch *batch_screen_edges_get(int *corner_len)
64{
65 static blender::gpu::Batch *screen_edges_batch = nullptr;
66
67 if (screen_edges_batch == nullptr) {
70
73
74 uint vidx = 0;
75 for (int corner = 0; corner < 4; corner++) {
76 for (int c = 0; c < CORNER_RESOLUTION; c++) {
77 do_vert_pair(vbo, pos, &vidx, corner, c);
78 }
79 }
80 /* close the loop */
81 do_vert_pair(vbo, pos, &vidx, 0, 0);
82
83 screen_edges_batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
84 gpu_batch_presets_register(screen_edges_batch);
85 }
86
87 if (corner_len) {
88 *corner_len = CORNER_RESOLUTION * 2;
89 }
90 return screen_edges_batch;
91}
92
93#undef CORNER_RESOLUTION
94
98static void drawscredge_area(const ScrArea &area, float edge_thickness)
99{
100 rctf rect;
101 BLI_rctf_rcti_copy(&rect, &area.totrct);
102 BLI_rctf_pad(&rect, edge_thickness, edge_thickness);
103
104 blender::gpu::Batch *batch = batch_screen_edges_get(nullptr);
106 GPU_batch_uniform_4fv(batch, "rect", (float *)&rect);
108}
109
111{
113 screen->do_draw = false;
114
115 if (screen->state != SCREENNORMAL) {
116 return;
117 }
118
119 if (BLI_listbase_is_single(&screen->areabase) && win->global_areas.areabase.first == nullptr) {
120 /* Do not show edges on windows without global areas and with only one editor. */
121 return;
122 }
123
124 ARegion *region = screen->active_region;
125 ScrArea *active_area = nullptr;
126
127 if (region) {
128 /* Find active area from active region. */
129 const int pos[2] = {BLI_rcti_cent_x(&region->winrct), BLI_rcti_cent_y(&region->winrct)};
130 active_area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, pos);
131 }
132
133 if (!active_area) {
134 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
135 AZone *zone = ED_area_actionzone_find_xy(area, win->eventstate->xy);
136 /* Get area from action zone, if not scroll-bar. */
137 if (zone && zone->type != AZONE_REGION_SCROLL) {
138 active_area = area;
139 break;
140 }
141 }
142 }
143
144 if (G.moving & G_TRANSFORM_WM) {
145 active_area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, win->eventstate->xy);
146 /* We don't want an active area when resizing, otherwise outline for active area flickers, see:
147 * #136314. */
148 if (active_area && !BLI_listbase_is_empty(&win->drawcalls)) {
149 active_area = nullptr;
150 }
151 }
152
153 rcti scissor_rect;
154 BLI_rcti_init_minmax(&scissor_rect);
155 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
156 BLI_rcti_do_minmax_v(&scissor_rect, blender::int2{area->v1->vec.x, area->v1->vec.y});
157 BLI_rcti_do_minmax_v(&scissor_rect, blender::int2{area->v3->vec.x, area->v3->vec.y});
158 }
159
161 /* For some reason, on linux + Intel UHD Graphics 620 the driver
162 * hangs if we don't flush before this. (See #57455) */
163 GPU_flush();
164 }
165
166 GPU_scissor(scissor_rect.xmin,
167 scissor_rect.ymin,
168 BLI_rcti_size_x(&scissor_rect) + 1,
169 BLI_rcti_size_y(&scissor_rect) + 1);
170 GPU_scissor_test(true);
171
172 float col[4];
174
175 const float edge_thickness = float(U.border_width) * UI_SCALE_FAC;
176
177 /* Entire width of the evaluated outline as far as the shader is concerned. */
178 const float shader_scale = edge_thickness + EDITORRADIUS;
179 const float corner_coverage[10] = {
180 0.144f, 0.25f, 0.334f, 0.40f, 0.455, 0.5, 0.538, 0.571, 0.6, 0.625f};
181 const float shader_width = corner_coverage[U.border_width - 1];
182
184
185 int verts_per_corner = 0;
186 blender::gpu::Batch *batch = batch_screen_edges_get(&verts_per_corner);
187
189 GPU_batch_uniform_1i(batch, "cornerLen", verts_per_corner);
190 GPU_batch_uniform_1f(batch, "scale", shader_scale);
191 GPU_batch_uniform_1f(batch, "width", shader_width);
193
194 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
195 drawscredge_area(*area, edge_thickness);
196 }
197
198 float outline1[4];
199 float outline2[4];
200 rctf bounds;
204 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
205 BLI_rctf_rcti_copy(&bounds, &area->totrct);
207 nullptr,
208 nullptr,
209 1.0f,
210 (area == active_area) ? outline2 : outline1,
211 U.pixelsize,
213 }
214
216 GPU_scissor_test(false);
217}
218
219void screen_draw_move_highlight(const wmWindow *win, bScreen *screen, eScreenAxis dir_axis)
220{
221 rctf rect = {SHRT_MAX, SHRT_MIN, SHRT_MAX, SHRT_MIN};
222
223 LISTBASE_FOREACH (const ScrEdge *, edge, &screen->edgebase) {
224 if (edge->v1->editflag && edge->v2->editflag) {
225 if (dir_axis == SCREEN_AXIS_H) {
226 rect.xmin = std::min({rect.xmin, float(edge->v1->vec.x), float(edge->v2->vec.x)});
227 rect.xmax = std::max({rect.xmax, float(edge->v1->vec.x), float(edge->v2->vec.x)});
228 rect.ymin = rect.ymax = float(edge->v1->vec.y);
229 }
230 else {
231 rect.ymin = std::min({rect.ymin, float(edge->v1->vec.y), float(edge->v2->vec.y)});
232 rect.ymax = std::max({rect.ymax, float(edge->v1->vec.y), float(edge->v2->vec.y)});
233 rect.xmin = rect.xmax = float(edge->v1->vec.x);
234 }
235 };
236 }
237
238 /* Pull in ends not at window edges. */
239 rcti window_rect;
240 WM_window_screen_rect_calc(win, &window_rect);
241 const float offset = U.border_width * UI_SCALE_FAC;
242 if (dir_axis == SCREEN_AXIS_H) {
243 if (rect.xmin > (window_rect.xmin + 2)) {
244 rect.xmin += offset;
245 }
246 if (rect.xmax < (window_rect.xmax - 2)) {
247 rect.xmax -= offset;
248 }
249 }
250 else {
251 if (rect.ymin > (window_rect.ymin + 2)) {
252 rect.ymin += offset;
253 }
254 if (rect.ymax < (window_rect.ymax - 2)) {
255 rect.ymax -= offset;
256 }
257 }
258
259 const float width = std::min(2.0f * U.border_width * UI_SCALE_FAC, 5.0f * UI_SCALE_FAC);
260
261 if (dir_axis == SCREEN_AXIS_H) {
262 BLI_rctf_pad(&rect, 0.0f, width);
263 }
264 else {
265 BLI_rctf_pad(&rect, width, 0.0f);
266 }
267
268 float inner[4] = {1.0f, 1.0f, 1.0f, 0.4f};
269 float outline[4];
271
274 &rect, inner, nullptr, 1.0f, outline, width - U.pixelsize, 2.5f * UI_SCALE_FAC);
275}
276
278{
279 rctf rect;
280 BLI_rctf_rcti_copy(&rect, &region->winrct);
282
283 switch (region->alignment) {
284 case RGN_ALIGN_RIGHT:
285 rect.xmax = rect.xmin - U.pixelsize;
286 rect.xmin = rect.xmax - (4.0f * U.pixelsize);
287 rect.ymax -= EDITORRADIUS;
288 rect.ymin += EDITORRADIUS;
289 break;
290 case RGN_ALIGN_LEFT:
291 rect.xmin = rect.xmax + U.pixelsize;
292 rect.xmax = rect.xmin + (4.0f * U.pixelsize);
293 rect.ymax -= EDITORRADIUS;
294 rect.ymin += EDITORRADIUS;
295 break;
296 case RGN_ALIGN_TOP:
297 rect.ymax = rect.ymin - U.pixelsize;
298 rect.ymin = rect.ymax - (4.0f * U.pixelsize);
299 rect.xmax -= EDITORRADIUS;
300 rect.xmin += EDITORRADIUS;
301 break;
302 case RGN_ALIGN_BOTTOM:
303 rect.ymin = rect.ymax + U.pixelsize;
304 rect.ymax = rect.ymin + (4.0f * U.pixelsize);
305 rect.xmax -= EDITORRADIUS;
306 rect.xmin += EDITORRADIUS;
307 break;
308 default:
309 return;
310 }
311
312 float inner[4] = {1.0f, 1.0f, 1.0f, 0.4f};
313 float outline[4] = {0.0f, 0.0f, 0.0f, 0.3f};
315 &rect, inner, nullptr, 1.0f, outline, 1.0f * U.pixelsize, 2.5f * UI_SCALE_FAC);
316}
317
319 const wmWindow *win, int x, int y, const ScrArea *source, const std::string &hint)
320{
321 const char *area_name = IFACE_(ED_area_name(source).c_str());
322 const uiFontStyle *fstyle = UI_FSTYLE_TOOLTIP;
323 const bTheme *btheme = UI_GetTheme();
324 const uiWidgetColors *wcol = &btheme->tui.wcol_tooltip;
325 float col_fg[4], col_bg[4];
326 rgba_uchar_to_float(col_fg, wcol->text);
327 rgba_uchar_to_float(col_bg, wcol->inner);
328
329 float scale = fstyle->points * UI_SCALE_FAC / UI_DEFAULT_TOOLTIP_POINTS;
331
332 const float margin = scale * 4.0f;
333 const float icon_width = (scale * ICON_DEFAULT_WIDTH / 1.4f);
334 const float icon_gap = scale * 3.0f;
335 const float line_gap = scale * 5.0f;
336 const int lheight = BLF_height_max(fstyle->uifont_id);
337 const int descent = BLF_descender(fstyle->uifont_id);
338 const float line1_len = BLF_width(fstyle->uifont_id, hint.c_str(), hint.size());
339 const float line2_len = BLF_width(fstyle->uifont_id, area_name, BLF_DRAW_STR_DUMMY_MAX);
340 const float width = margin + std::max(line1_len, line2_len + icon_width + icon_gap) + margin;
341 const float height = margin + lheight + line_gap + lheight + margin;
342
343 /* Position of this hint relative to the mouse position. */
344 const int left = std::min(x + int(5.0f * UI_SCALE_FAC),
345 WM_window_native_pixel_x(win) - int(width));
346 const int top = std::max(y - int(7.0f * UI_SCALE_FAC), int(height));
347
348 rctf rect;
349 rect.xmin = left;
350 rect.xmax = left + width;
351 rect.ymax = top;
352 rect.ymin = top - height;
354 UI_draw_roundbox_4fv(&rect, true, wcol->roundness * U.widget_unit, col_bg);
355
356 UI_icon_draw_ex(left + margin,
357 top - height + margin + (1.0f * scale),
358 ED_area_icon(source),
359 1.4f / scale,
360 1.0f,
361 0.0f,
362 wcol->text,
363 true,
365
367 BLF_color4fv(fstyle->uifont_id, col_fg);
368
369 BLF_position(fstyle->uifont_id, left + margin, top - margin - lheight + (2.0f * scale), 0.0f);
370 BLF_draw(fstyle->uifont_id, hint.c_str(), hint.size());
371
372 BLF_position(fstyle->uifont_id,
373 left + margin + icon_width + icon_gap,
374 top - height + margin - descent,
375 0.0f);
376 BLF_draw(fstyle->uifont_id, area_name, BLF_DRAW_STR_DUMMY_MAX);
377}
378
379static void screen_draw_area_closed(int xmin, int xmax, int ymin, int ymax)
380{
381 /* Darken the area. */
382 rctf rect = {float(xmin), float(xmax), float(ymin), float(ymax)};
383 float darken[4] = {0.0f, 0.0f, 0.0f, 0.7f};
385 UI_draw_roundbox_4fv_ex(&rect, darken, nullptr, 1.0f, nullptr, U.pixelsize, EDITORRADIUS);
386}
387
389{
390 if (dir == SCREEN_DIR_NONE || !sa2) {
391 /* Darken source if docking. Done here because it might be a different window. */
393 sa1->totrct.xmin, sa1->totrct.xmax, sa1->totrct.ymin, sa1->totrct.ymax);
394 return;
395 }
396
397 /* Rect of the combined areas. */
398 const bool vertical = SCREEN_DIR_IS_VERTICAL(dir);
399 rctf combined{};
400 combined.xmin = vertical ? std::max(sa1->totrct.xmin, sa2->totrct.xmin) :
401 std::min(sa1->totrct.xmin, sa2->totrct.xmin);
402 combined.xmax = vertical ? std::min(sa1->totrct.xmax, sa2->totrct.xmax) :
403 std::max(sa1->totrct.xmax, sa2->totrct.xmax);
404 combined.ymin = vertical ? std::min(sa1->totrct.ymin, sa2->totrct.ymin) :
405 std::max(sa1->totrct.ymin, sa2->totrct.ymin);
406 combined.ymax = vertical ? std::max(sa1->totrct.ymax, sa2->totrct.ymax) :
407 std::min(sa1->totrct.ymax, sa2->totrct.ymax);
408
409 int offset1;
410 int offset2;
411 area_getoffsets(sa1, sa2, dir, &offset1, &offset2);
412 if (offset1 < 0 || offset2 > 0) {
413 /* Show partial areas that will be closed. */
414 if (vertical) {
415 if (sa1->totrct.xmin < combined.xmin) {
417 sa1->totrct.xmin, combined.xmin, sa1->totrct.ymin, sa1->totrct.ymax);
418 }
419 if (sa2->totrct.xmin < combined.xmin) {
421 sa2->totrct.xmin, combined.xmin, sa2->totrct.ymin, sa2->totrct.ymax);
422 }
423 if (sa1->totrct.xmax > combined.xmax) {
425 combined.xmax, sa1->totrct.xmax, sa1->totrct.ymin, sa1->totrct.ymax);
426 }
427 if (sa2->totrct.xmax > combined.xmax) {
429 combined.xmax, sa2->totrct.xmax, sa2->totrct.ymin, sa2->totrct.ymax);
430 }
431 }
432 else {
433 if (sa1->totrct.ymin < combined.ymin) {
435 sa1->totrct.xmin, sa1->totrct.xmax, sa1->totrct.ymin, combined.ymin);
436 }
437 if (sa2->totrct.ymin < combined.ymin) {
439 sa2->totrct.xmin, sa2->totrct.xmax, sa2->totrct.ymin, combined.ymin);
440 }
441 if (sa1->totrct.ymax > combined.ymax) {
443 sa1->totrct.xmin, sa1->totrct.xmax, combined.ymax, sa1->totrct.ymax);
444 }
445 if (sa2->totrct.ymax > combined.ymax) {
447 sa2->totrct.xmin, sa2->totrct.xmax, combined.ymax, sa2->totrct.ymax);
448 }
449 }
450 }
451
452 /* Outline the combined area. */
454 float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f};
455 float inner[4] = {1.0f, 1.0f, 1.0f, 0.10f};
456 UI_draw_roundbox_4fv_ex(&combined, inner, nullptr, 1.0f, outline, U.pixelsize, EDITORRADIUS);
457
459 win, win->eventstate->xy[0], win->eventstate->xy[1], sa1, IFACE_("Join Areas"));
460}
461
462static void rounded_corners(rctf rect, float color[4], int corners)
463{
466
467 const float rad = EDITORRADIUS;
468
469 float vec[4][2] = {
470 {0.195, 0.02},
471 {0.55, 0.169},
472 {0.831, 0.45},
473 {0.98, 0.805},
474 };
475 for (int a = 0; a < 4; a++) {
476 mul_v2_fl(vec[a], rad);
477 }
478
480 immUniformColor4fv(color);
481
482 if (corners & UI_CNR_TOP_LEFT) {
484 immVertex2f(pos, rect.xmin - 1, rect.ymax);
485 immVertex2f(pos, rect.xmin, rect.ymax - rad);
486 for (int a = 0; a < 4; a++) {
487 immVertex2f(pos, rect.xmin + vec[a][1], rect.ymax - rad + vec[a][0]);
488 }
489 immVertex2f(pos, rect.xmin + rad, rect.ymax);
490 immEnd();
491 }
492
493 if (corners & UI_CNR_TOP_RIGHT) {
495 immVertex2f(pos, rect.xmax + 1, rect.ymax);
496 immVertex2f(pos, rect.xmax - rad, rect.ymax);
497 for (int a = 0; a < 4; a++) {
498 immVertex2f(pos, rect.xmax - rad + vec[a][0], rect.ymax - vec[a][1]);
499 }
500 immVertex2f(pos, rect.xmax, rect.ymax - rad);
501 immEnd();
502 }
503
504 if (corners & UI_CNR_BOTTOM_RIGHT) {
506 immVertex2f(pos, rect.xmax + 1, rect.ymin);
507 immVertex2f(pos, rect.xmax, rect.ymin + rad);
508 for (int a = 0; a < 4; a++) {
509 immVertex2f(pos, rect.xmax - vec[a][1], rect.ymin + rad - vec[a][0]);
510 }
511 immVertex2f(pos, rect.xmax - rad, rect.ymin);
512 immEnd();
513 }
514
515 if (corners & UI_CNR_BOTTOM_LEFT) {
517 immVertex2f(pos, rect.xmin - 1, rect.ymin);
518 immVertex2f(pos, rect.xmin + rad, rect.ymin);
519 for (int a = 0; a < 4; a++) {
520 immVertex2f(pos, rect.xmin + rad - vec[a][0], rect.ymin + vec[a][1]);
521 }
522 immVertex2f(pos, rect.xmin, rect.ymin + rad);
523 immEnd();
524 }
525
527}
528
530 ScrArea *source,
531 ScrArea *target,
532 AreaDockTarget dock_target,
533 float factor,
534 int x,
535 int y)
536{
537 if (dock_target == AreaDockTarget::None) {
538 return;
539 }
540
541 float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f};
542 float inner[4] = {1.0f, 1.0f, 1.0f, 0.1f};
543 float border[4];
546 float half_line_width = float(U.border_width) * UI_SCALE_FAC;
547
548 rctf dest;
549 rctf remainder;
550 BLI_rctf_rcti_copy(&dest, &target->totrct);
551 BLI_rctf_rcti_copy(&remainder, &target->totrct);
552
553 float split;
554 int corners = UI_CNR_NONE;
555
556 if (dock_target == AreaDockTarget::Right) {
557 split = std::min(dest.xmin + target->winx * (1.0f - factor),
558 dest.xmax - AREAMINX * UI_SCALE_FAC);
559 dest.xmin = split + half_line_width;
560 remainder.xmax = split - half_line_width;
562 }
563 else if (dock_target == AreaDockTarget::Left) {
564 split = std::max(dest.xmax - target->winx * (1.0f - factor),
565 dest.xmin + AREAMINX * UI_SCALE_FAC);
566 dest.xmax = split - half_line_width;
567 remainder.xmin = split + half_line_width;
569 }
570 else if (dock_target == AreaDockTarget::Top) {
571 split = std::min(dest.ymin + target->winy * (1.0f - factor),
572 dest.ymax - HEADERY * UI_SCALE_FAC);
573 dest.ymin = split + half_line_width;
574 remainder.ymax = split - half_line_width;
576 }
577 else if (dock_target == AreaDockTarget::Bottom) {
578 split = std::max(dest.ymax - target->winy * (1.0f - factor),
579 dest.ymin + HEADERY * UI_SCALE_FAC);
580 dest.ymax = split - half_line_width;
581 remainder.ymin = split + half_line_width;
583 }
584
585 rounded_corners(dest, border, corners);
586 UI_draw_roundbox_4fv_ex(&dest, inner, nullptr, 1.0f, outline, U.pixelsize, EDITORRADIUS);
587
588 if (dock_target != AreaDockTarget::Center) {
589 /* Darken the split position itself. */
591 dest.xmin = split - half_line_width;
592 dest.xmax = split + half_line_width;
593 }
594 else {
595 dest.ymin = split - half_line_width;
596 dest.ymax = split + half_line_width;
597 }
598 UI_draw_roundbox_4fv(&dest, true, 0.0f, border);
599 }
600
602 x,
603 y,
604 source,
605 dock_target == AreaDockTarget::Center ? IFACE_("Replace this area") :
606 IFACE_("Move area here"));
607}
608
609void screen_draw_split_preview(ScrArea *area, const eScreenAxis dir_axis, const float factor)
610{
611 float outline[4] = {1.0f, 1.0f, 1.0f, 0.4f};
612 float inner[4] = {1.0f, 1.0f, 1.0f, 0.10f};
613 float border[4];
616
617 rctf rect;
618 BLI_rctf_rcti_copy(&rect, &area->totrct);
619
620 if (factor < 0.0001 || factor > 0.9999) {
621 /* Highlight the entire area. */
622 UI_draw_roundbox_4fv_ex(&rect, inner, nullptr, 1.0f, outline, U.pixelsize, EDITORRADIUS);
623 return;
624 }
625
626 float x = (1 - factor) * rect.xmin + factor * rect.xmax;
627 float y = (1 - factor) * rect.ymin + factor * rect.ymax;
628 x = std::clamp(x, rect.xmin, rect.xmax);
629 y = std::clamp(y, rect.ymin, rect.ymax);
630 float half_line_width = float(U.border_width) * UI_SCALE_FAC;
631
632 /* Outlined rectangle to left/above split position. */
633 rect.xmax = (dir_axis == SCREEN_AXIS_V) ? x - half_line_width : rect.xmax;
634 rect.ymax = (dir_axis == SCREEN_AXIS_H) ? y - half_line_width : rect.ymax;
635
636 rounded_corners(rect,
637 border,
640 UI_draw_roundbox_4fv_ex(&rect, inner, nullptr, 1.0f, outline, U.pixelsize, EDITORRADIUS);
641
642 /* Outlined rectangle to right/below split position. */
643 if (dir_axis == SCREEN_AXIS_H) {
644 rect.ymin = y + half_line_width;
645 rect.ymax = area->totrct.ymax;
646 }
647 else {
648 rect.xmin = x + half_line_width;
649 rect.xmax = area->totrct.xmax;
650 }
651
652 rounded_corners(rect,
653 border,
656 UI_draw_roundbox_4fv_ex(&rect, inner, nullptr, 1.0f, outline, U.pixelsize, EDITORRADIUS);
657
658 /* Darken the split position itself. */
659 if (dir_axis == SCREEN_AXIS_H) {
660 rect.ymin = y - half_line_width;
661 rect.ymax = y + half_line_width;
662 }
663 else {
664 rect.xmin = x - half_line_width;
665 rect.xmax = x + half_line_width;
666 }
667 UI_draw_roundbox_4fv(&rect, true, 0.0f, border);
668}
@ G_TRANSFORM_WM
ScrArea ScrArea * BKE_screen_find_area_xy(const bScreen *screen, int spacetype, const int xy[2]) ATTR_NONNULL(1
void BLF_size(int fontid, float size)
Definition blf.cc:440
int BLF_descender(int fontid) ATTR_WARN_UNUSED_RESULT
Definition blf.cc:875
void BLF_color4fv(int fontid, const float rgba[4])
Definition blf.cc:502
#define BLF_DRAW_STR_DUMMY_MAX
Definition BLF_api.hh:468
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:582
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:805
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT
Definition blf.cc:853
void BLF_position(int fontid, float x, float y, float z)
Definition blf.cc:385
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void void BLI_INLINE bool BLI_listbase_is_single(const ListBase *lb)
MINLINE float max_ff(float a, float b)
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
#define M_PI_2
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v2_v2fl(float r[2], const float a[2], float f)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
void BLI_rcti_init_minmax(struct rcti *rect)
Definition rct.cc:474
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
void BLI_rctf_pad(struct rctf *rect, float pad_x, float pad_y)
Definition rct.cc:637
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition BLI_rect.h:181
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
void BLI_rcti_do_minmax_v(struct rcti *rect, const int xy[2])
Definition rct.cc:486
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition BLI_rect.h:177
unsigned int uint
#define ELEM(...)
#define IFACE_(msgid)
#define HEADERY
#define AREAMINX
@ SCREENNORMAL
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
#define SPACE_TYPE_ANY
#define UI_SCALE_FAC
int ED_area_icon(const ScrArea *area)
blender::StringRefNull ED_area_name(const ScrArea *area)
@ AZONE_REGION_SCROLL
static void split(const char *text, const char *seps, char ***str, int *count)
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, eGPUBatchFlag owns_flag)
Definition gpu_batch.cc:51
#define GPU_batch_uniform_1f(batch, name, x)
Definition GPU_batch.hh:301
void GPU_batch_program_set_builtin(blender::gpu::Batch *batch, eGPUBuiltinShader shader_id)
void GPU_batch_draw(blender::gpu::Batch *batch)
#define GPU_batch_uniform_4fv(batch, name, val)
Definition GPU_batch.hh:309
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:41
#define GPU_batch_uniform_1i(batch, name, x)
Definition GPU_batch.hh:299
void gpu_batch_presets_register(blender::gpu::Batch *preset_batch)
void immEnd()
void immUnbindProgram()
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
GPUVertFormat * immVertexFormat()
void immUniformColor4fv(const float rgba[4])
void immBegin(GPUPrimType, uint vertex_len)
@ GPU_DRIVER_ANY
bool GPU_type_matches_ex(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver, eGPUBackendType backend)
@ GPU_OS_UNIX
@ GPU_DEVICE_INTEL_UHD
@ GPU_PRIM_TRI_FAN
@ GPU_PRIM_TRI_STRIP
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_2D_AREA_BORDERS
void GPU_flush()
Definition gpu_state.cc:305
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:188
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:193
#define GPU_vertbuf_create_with_format(format)
void GPU_vertbuf_attr_set(blender::gpu::VertBuf *, uint a_idx, uint v_idx, const void *data)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
void UI_draw_roundbox_4fv(const rctf *rect, bool filled, float rad, const float col[4])
@ UI_CNR_BOTTOM_LEFT
@ UI_CNR_BOTTOM_RIGHT
@ UI_CNR_ALL
@ UI_CNR_TOP_LEFT
@ UI_CNR_TOP_RIGHT
@ UI_CNR_NONE
void UI_draw_roundbox_4fv_ex(const rctf *rect, const float inner1[4], const float inner2[4], float shade_dir, const float outline[4], float outline_width, float rad)
#define UI_DEFAULT_TOOLTIP_POINTS
void UI_draw_roundbox_corner_set(int type)
#define UI_FSTYLE_TOOLTIP
#define UI_NO_ICON_OVERLAY_TEXT
void UI_icon_draw_ex(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const uchar mono_color[4], bool mono_border, const IconTextOverlay *text_overlay, const bool inverted=false)
#define ICON_DEFAULT_WIDTH
@ TH_EDITOR_BORDER
@ TH_EDITOR_OUTLINE_ACTIVE
@ TH_EDITOR_OUTLINE
void UI_GetThemeColor4fv(int colorid, float col[4])
bTheme * UI_GetTheme()
#define U
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
#define sinf(x)
#define cosf(x)
#define fabsf(x)
uint pos
struct @064345207361167251075330302113175271221317160336::@113254110077376341056327177062323111323010325277 batch
uint col
uint top
format
static int left
#define G(x, y, z)
VecBase< int32_t, 2 > int2
void screen_draw_region_scale_highlight(ARegion *region)
static void drawscredge_area(const ScrArea &area, float edge_thickness)
Screen edges drawing.
void screen_draw_move_highlight(const wmWindow *win, bScreen *screen, eScreenAxis dir_axis)
static void rounded_corners(rctf rect, float color[4], int corners)
void screen_draw_split_preview(ScrArea *area, const eScreenAxis dir_axis, const float factor)
void ED_screen_draw_edges(wmWindow *win)
#define CORNER_RESOLUTION
static void screen_draw_area_closed(int xmin, int xmax, int ymin, int ymax)
void screen_draw_join_highlight(const wmWindow *win, ScrArea *sa1, ScrArea *sa2, eScreenDir dir)
static void do_vert_pair(blender::gpu::VertBuf *vbo, uint pos, uint *vidx, int corner, int i)
void screen_draw_dock_preview(const wmWindow *win, ScrArea *source, ScrArea *target, AreaDockTarget dock_target, float factor, int x, int y)
static void screen_draw_area_drag_tip(const wmWindow *win, int x, int y, const ScrArea *source, const std::string &hint)
static blender::gpu::Batch * batch_screen_edges_get(int *corner_len)
void area_getoffsets(ScrArea *sa_a, ScrArea *sa_b, const eScreenDir dir, int *r_offset1, int *r_offset2)
AZone * ED_area_actionzone_find_xy(ScrArea *area, const int xy[2])
eScreenAxis
@ SCREEN_AXIS_V
@ SCREEN_AXIS_H
#define SCREEN_DIR_IS_VERTICAL(dir)
eScreenDir
@ SCREEN_DIR_NONE
#define EDITORRADIUS
AreaDockTarget
void * first
ListBase areabase
uiWidgetColors wcol_tooltip
ListBase edgebase
ListBase areabase
struct ARegion * active_region
ThemeUI tui
float xmax
float xmin
float ymax
float ymin
int ymin
int ymax
int xmin
int xmax
unsigned char inner[4]
unsigned char text[4]
int xy[2]
Definition WM_types.hh:758
struct wmEvent * eventstate
ScrAreaMap global_areas
i
Definition text_draw.cc:230
int WM_window_native_pixel_x(const wmWindow *win)
void WM_window_screen_rect_calc(const wmWindow *win, rcti *r_rect)
bScreen * WM_window_get_active_screen(const wmWindow *win)