22#ifdef USE_UIBUT_SPATIAL_ALIGN
80# define SIDE_TO_UI_BUT_ALIGN \
82 UI_BUT_ALIGN_LEFT, UI_BUT_ALIGN_TOP, UI_BUT_ALIGN_RIGHT, UI_BUT_ALIGN_DOWN \
86# define SIDE1(_s) (((_s) + 1) % TOTSIDES)
87# define OPPOSITE(_s) (((_s) + 2) % TOTSIDES)
88# define SIDE2(_s) (((_s) + 3) % TOTSIDES)
91# define IS_COLUMN(_s) ((_s) % 2)
94# define STITCH(_s) (1 << (_s))
97# define MAX_DELTA 0.45f * max_ii(UI_UNIT_Y, UI_UNIT_X)
101 const bool btype_can_align = !
ELEM(but->
type,
124 float delta, delta_side_opp;
130 const bool buts_share[2] = {
140 if (!(buts_share[0] || buts_share[1]) || !(butal_can_align || butal_other_can_align)) {
144 for (side = 0; side <
RIGHT; side++) {
159 if (delta_side_opp < delta) {
160 std::swap(side, side_opp);
161 delta = delta_side_opp;
164 if (delta < max_delta) {
167 if (delta <= butal->dists[side]) {
180 if (butal_can_align && butal_other_can_align) {
182 butal_other->
neighbors[side_opp] = butal;
184 else if (butal_can_align && (delta < butal->dists[side])) {
187 else if (butal_other_can_align && (delta < butal_other->dists[side_opp])) {
188 butal_other->
neighbors[side_opp] =
nullptr;
190 butal->
dists[side] = butal_other->
dists[side_opp] = delta;
193 if (butal_can_align && butal_other_can_align) {
194 const int side_s1 =
SIDE1(side);
195 const int side_s2 =
SIDE2(side);
197 const int stitch =
STITCH(side);
198 const int stitch_opp =
STITCH(side_opp);
203 if (butal_other->
neighbors[side_opp] ==
nullptr) {
204 butal_other->
neighbors[side_opp] = butal;
214 if (delta < max_delta) {
215 butal->
flags[side_s1] |= stitch;
216 butal_other->
flags[side_s1] |= stitch_opp;
219 if (delta < max_delta) {
220 butal->
flags[side_s2] |= stitch;
221 butal_other->
flags[side_s2] |= stitch_opp;
265 const int stitch_s1 =
STITCH(side_s1);
266 const int stitch_s2 =
STITCH(side_s2);
273 while ((butal->
flags[side] & stitch_s1) && (butal = butal->
neighbors[side_s1]) &&
274 (butal->
flags[side] & stitch_s2))
280 if (butal_neighbor) {
283 *butal_neighbor->
borders[side_opp] = co;
284 butal_neighbor->
dists[side_opp] = 0.0f;
287 else if (side ==
LEFT) {
290 else if (side ==
TOP) {
294 butal->
dists[side] = 0.0f;
297 butal->
flags[side] &= ~stitch_s2;
341 const float outline_px =
U.pixelsize;
345 rect->
ymax = region->winy + outline_px;
349 rect->
ymin = -outline_px;
350 rect->
ymax = rect->
ymin + but_height;
353 rect->
xmin = -outline_px;
354 rect->
xmax = rect->
xmin + but_width;
357 rect->
xmax = region->winx + outline_px;
358 rect->
xmin = rect->
xmax - but_width;
386 but->drawflag &= ~UI_BUT_ALIGN_ALL;
389 if (but->alignnr != 0) {
394 if (num_buttons < 2) {
403 if (num_buttons <=
ARRAY_SIZE(butal_array_buf)) {
404 butal_array = butal_array_buf;
407 butal_array =
static_cast<ButAlign *
>(
408 MEM_mallocN(
sizeof(*butal_array) * num_buttons, __func__));
410 memset(butal_array, 0,
sizeof(*butal_array) *
size_t(num_buttons));
415 if (but->alignnr != 0) {
435 for (i = 0, butal = butal_array; i < num_buttons; i++, butal++) {
439 for (j = i + 1, butal_other = &butal_array[i + 1]; j < num_buttons; j++, butal_other++) {
464 for (i = 0; i < num_buttons; i++) {
465 butal = &butal_array[i];
467 for (side = 0; side <
TOTSIDES; side++) {
471 const int side_opp =
OPPOSITE(side);
472 const int side_s1 =
SIDE1(side);
473 const int side_s2 =
SIDE2(side);
475 const int align = sides_to_ui_but_align_flags[side];
476 const int align_opp = sides_to_ui_but_align_flags[side_opp];
483 float *delta = &butal->
dists[side];
491 co = (*butal->
borders[side] += *delta);
495 *butal_other->
borders[side_opp] = co;
496 butal_other->
dists[side_opp] = 0.0f;
505 butal, side, side_opp, side_s1, side_s2, align, align_opp, co);
507 butal, side, side_opp, side_s2, side_s1, align, align_opp, co);
511 if (butal_array_buf != butal_array) {
516# undef SIDE_TO_UI_BUT_ALIGN
537static bool buts_are_horiz(
uiBut *but1,
uiBut *but2)
553static void ui_block_align_calc_but(
uiBut *first,
short nr)
556 int flag = 0, cols = 0, rows = 0;
560 for (but = first; but && but->
alignnr == nr; but = but->
next) {
562 if (buts_are_horiz(but, but->
next)) {
575 for (but = first, prev =
nullptr; but && but->
alignnr == nr;
prev = but, but = but->
next) {
582 but->drawflag &= ~UI_BUT_ALIGN;
586 if (buts_are_horiz(but,
next)) {
599 else if (
next ==
nullptr) {
601 if (buts_are_horiz(prev, but)) {
614 else if (buts_are_horiz(but,
next)) {
616 if (prev && buts_are_horiz(prev, but) == 0) {
617 flag &= ~UI_BUT_ALIGN_LEFT;
622 while (bt && bt->
alignnr == nr) {
628 if (bt ==
nullptr || bt->
alignnr != nr) {
643 if (prev && buts_are_horiz(prev, but)) {
647 flag &= ~UI_BUT_ALIGN_LEFT;
653 if (
next && buts_are_horiz(but,
next)) {
677 but->rect.xmin = (
prev->rect.xmax + but->rect.xmin) / 2.0f;
678 prev->rect.xmax = but->rect.xmin;
680 else if (cols == 0) {
681 but->rect.ymax = (
prev->rect.ymin + but->rect.ymax) / 2.0f;
682 prev->rect.ymin = but->rect.ymax;
685 if (buts_are_horiz(prev, but)) {
686 but->rect.xmin = (
prev->rect.xmax + but->rect.xmin) / 2.0f;
687 prev->rect.xmax = but->rect.xmin;
689 but->rect.ymax =
prev->rect.ymax;
691 else if (
prev->prev && buts_are_horiz(
prev->prev, prev) == 0) {
693 but->rect.ymax = (
prev->rect.ymin + but->rect.ymax) / 2.0f;
694 prev->rect.ymin = but->rect.ymax;
696 but->rect.xmin =
prev->rect.xmin;
697 if (
next && buts_are_horiz(but,
next) == 0) {
698 but->rect.xmax =
prev->rect.xmax;
703 but->rect.ymax =
prev->rect.ymin;
718 ui_block_align_calc_but(but, nr);
721 for (; but && but->alignnr == nr; but = but->next) {
#define LISTBASE_FOREACH(type, var, list)
MINLINE float max_ff(float a, float b)
MINLINE void copy_v4_fl(float r[4], float f)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
#define RGN_ALIGN_ENUM_FROM_MASK(align)
Read Guarded memory(de)allocation.
@ UI_BUT_ALIGN_STITCH_TOP
@ UI_BUT_ALIGN_STITCH_LEFT
local_group_size(16, 16) .push_constant(Type b
bool ui_but_can_align(const uiBut *but)
static void block_align_stitch_neighbors(ButAlign *butal, const int side, const int side_opp, const int side_s1, const int side_s2, const int align, const int align_opp, const float co)
static void ui_block_align_but_to_region(uiBut *but, const ARegion *region)
int ui_but_align_opposite_to_area_align_get(const ARegion *region)
static void block_align_proximity_compute(ButAlign *butal, ButAlign *butal_other)
static int ui_block_align_butal_cmp(const void *a, const void *b)
#define SIDE_TO_UI_BUT_ALIGN
void ui_block_align_calc(uiBlock *block, const ARegion *region)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
SymEdge< T > * prev(const SymEdge< T > *se)