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;
379 for (
const std::unique_ptr<uiBut> &but : block->
buttons) {
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;
409 memset(butal_array, 0,
sizeof(*butal_array) *
size_t(num_buttons));
413 for (
const std::unique_ptr<uiBut> &but : block->
buttons) {
414 if (but->alignnr != 0) {
415 butal->
but = but.get();
434 for (
i = 0, butal = butal_array;
i < num_buttons;
i++, butal++) {
438 for (j =
i + 1, butal_other = &butal_array[
i + 1]; j < num_buttons; j++, butal_other++) {
463 for (
i = 0;
i < num_buttons;
i++) {
464 butal = &butal_array[
i];
466 for (side = 0; side <
TOTSIDES; side++) {
470 const int side_opp =
OPPOSITE(side);
471 const int side_s1 =
SIDE1(side);
472 const int side_s2 =
SIDE2(side);
474 const int align = sides_to_ui_but_align_flags[side];
475 const int align_opp = sides_to_ui_but_align_flags[side_opp];
482 float *delta = &butal->
dists[side];
490 co = (*butal->
borders[side] += *delta);
494 *butal_other->
borders[side_opp] = co;
495 butal_other->
dists[side_opp] = 0.0f;
504 butal, side, side_opp, side_s1, side_s2, align, align_opp, co);
506 butal, side, side_opp, side_s2, side_s1, align, align_opp, co);
510 if (butal_array_buf != butal_array) {
515# undef SIDE_TO_UI_BUT_ALIGN
536static bool buts_are_horiz(
uiBut *but1,
uiBut *but2)
552static void ui_block_align_calc_but(
uiBut *first,
short nr)
555 int flag = 0, cols = 0, rows = 0;
559 for (but = first; but && but->
alignnr == nr; but = but->next) {
560 if (but->next && but->next->
alignnr == nr) {
561 if (buts_are_horiz(but, but->next)) {
574 for (but = first, prev =
nullptr; but && but->
alignnr == nr;
prev = but, but = but->next) {
585 if (buts_are_horiz(but,
next)) {
598 else if (
next ==
nullptr) {
600 if (buts_are_horiz(prev, but)) {
613 else if (buts_are_horiz(but,
next)) {
615 if (prev && buts_are_horiz(prev, but) == 0) {
621 while (bt && bt->
alignnr == nr) {
622 if (bt->next && bt->next->
alignnr == nr && buts_are_horiz(bt, bt->next) == 0) {
627 if (bt ==
nullptr || bt->
alignnr != nr) {
642 if (prev && buts_are_horiz(prev, but)) {
652 if (
next && buts_are_horiz(but,
next)) {
670 but->drawflag |=
flag;
676 but->rect.xmin = (
prev->rect.xmax + but->rect.xmin) / 2.0f;
677 prev->rect.xmax = but->rect.xmin;
679 else if (cols == 0) {
680 but->rect.ymax = (
prev->rect.ymin + but->rect.ymax) / 2.0f;
681 prev->rect.ymin = but->rect.ymax;
684 if (buts_are_horiz(prev, but)) {
685 but->rect.xmin = (
prev->rect.xmax + but->rect.xmin) / 2.0f;
686 prev->rect.xmax = but->rect.xmin;
688 but->rect.ymax =
prev->rect.ymax;
690 else if (
prev->prev && buts_are_horiz(
prev->prev, prev) == 0) {
692 but->rect.ymax = (
prev->rect.ymin + but->rect.ymax) / 2.0f;
693 prev->rect.ymin = but->rect.ymax;
695 but->rect.xmin =
prev->rect.xmin;
696 if (
next && buts_are_horiz(but,
next) == 0) {
697 but->rect.xmax =
prev->rect.xmax;
702 but->rect.ymax =
prev->rect.ymin;
717 ui_block_align_calc_but(but, nr);
720 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
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_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
SymEdge< T > * prev(const SymEdge< T > *se)
blender::Vector< std::unique_ptr< uiBut > > buttons