37 #ifdef USE_UIBUT_SPATIAL_ALIGN
95 # define SIDE_TO_UI_BUT_ALIGN \
97 UI_BUT_ALIGN_LEFT, UI_BUT_ALIGN_TOP, UI_BUT_ALIGN_RIGHT, UI_BUT_ALIGN_DOWN \
101 # define SIDE1(_s) (((_s) + 1) % TOTSIDES)
102 # define OPPOSITE(_s) (((_s) + 2) % TOTSIDES)
103 # define SIDE2(_s) (((_s) + 3) % TOTSIDES)
106 # define IS_COLUMN(_s) ((_s) % 2)
109 # define STITCH(_s) (1 << (_s))
112 # define MAX_DELTA 0.45f * max_ii(UI_UNIT_Y, UI_UNIT_X)
139 float delta, delta_side_opp;
145 const bool buts_share[2] = {
155 if (!(buts_share[0] || buts_share[1]) || !(butal_can_align || butal_other_can_align)) {
159 for (side = 0; side <
RIGHT; side++) {
174 if (delta_side_opp < delta) {
175 SWAP(
int, side, side_opp);
176 delta = delta_side_opp;
179 if (delta < max_delta) {
182 if (delta <= butal->
dists[side]) {
195 if (butal_can_align && butal_other_can_align) {
197 butal_other->
neighbors[side_opp] = butal;
199 else if (butal_can_align && (delta < butal->
dists[side])) {
202 else if (butal_other_can_align && (delta < butal_other->
dists[side_opp])) {
205 butal->
dists[side] = butal_other->
dists[side_opp] = delta;
208 if (butal_can_align && butal_other_can_align) {
209 const int side_s1 =
SIDE1(side);
210 const int side_s2 =
SIDE2(side);
212 const int stitch =
STITCH(side);
213 const int stitch_opp =
STITCH(side_opp);
219 butal_other->
neighbors[side_opp] = butal;
229 if (delta < max_delta) {
230 butal->
flags[side_s1] |= stitch;
231 butal_other->
flags[side_s1] |= stitch_opp;
234 if (delta < max_delta) {
235 butal->
flags[side_s2] |= stitch;
236 butal_other->
flags[side_s2] |= stitch_opp;
280 const int stitch_s1 =
STITCH(side_s1);
281 const int stitch_s2 =
STITCH(side_s2);
288 while ((butal->
flags[side] & stitch_s1) && (butal = butal->
neighbors[side_s1]) &&
289 (butal->
flags[side] & stitch_s2)) {
294 if (butal_neighbor) {
297 *butal_neighbor->
borders[side_opp] = co;
298 butal_neighbor->
dists[side_opp] = 0.0f;
301 else if (side ==
LEFT) {
304 else if (side ==
TOP) {
308 butal->
dists[side] = 0.0f;
311 butal->
flags[side] &= ~stitch_s2;
355 const float outline_px =
U.pixelsize;
359 rect->
ymax = region->
winy + outline_px;
363 rect->
ymin = -outline_px;
364 rect->
ymax = rect->
ymin + but_height;
367 rect->
xmin = -outline_px;
368 rect->
xmax = rect->
xmin + but_width;
371 rect->
xmax = region->
winx + outline_px;
372 rect->
xmin = rect->
xmax - but_width;
415 if (num_buttons < 2) {
424 if (num_buttons <=
ARRAY_SIZE(butal_array_buf)) {
425 butal_array = butal_array_buf;
428 butal_array =
MEM_mallocN(
sizeof(*butal_array) * num_buttons, __func__);
430 memset(butal_array, 0,
sizeof(*butal_array) * (
size_t)num_buttons);
455 for (i = 0, butal = butal_array; i < num_buttons; i++, butal++) {
459 for (j = i + 1, butal_other = &butal_array[i + 1]; j < num_buttons; j++, butal_other++) {
484 for (i = 0; i < num_buttons; i++) {
485 butal = &butal_array[i];
487 for (side = 0; side <
TOTSIDES; side++) {
491 const int side_opp =
OPPOSITE(side);
492 const int side_s1 =
SIDE1(side);
493 const int side_s2 =
SIDE2(side);
495 const int align = sides_to_ui_but_align_flags[side];
496 const int align_opp = sides_to_ui_but_align_flags[side_opp];
503 float *delta = &butal->
dists[side];
511 co = (*butal->
borders[side] += *delta);
515 *butal_other->
borders[side_opp] = co;
516 butal_other->
dists[side_opp] = 0.0f;
525 butal, side, side_opp, side_s1, side_s2, align, align_opp, co);
527 butal, side, side_opp, side_s2, side_s1, align, align_opp, co);
531 if (butal_array_buf != butal_array) {
536 # undef SIDE_TO_UI_BUT_ALIGN
557 static bool buts_are_horiz(
uiBut *but1,
uiBut *but2)
573 static void ui_block_align_calc_but(
uiBut *first,
short nr)
576 int flag = 0, cols = 0, rows = 0;
605 if (buts_are_horiz(
but,
next)) {
620 if (buts_are_horiz(prev,
but)) {
633 else if (buts_are_horiz(
but,
next)) {
635 if (prev && buts_are_horiz(prev,
but) == 0) {
641 while (bt && bt->
alignnr == nr) {
662 if (prev && buts_are_horiz(prev,
but)) {
699 else if (cols == 0) {
704 if (buts_are_horiz(prev,
but)) {
710 else if (prev->
prev && buts_are_horiz(prev->
prev, prev) == 0) {
737 ui_block_align_calc_but(
but, nr);
#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_freeN)(void *vmemh)
void *(* MEM_mallocN)(size_t len, const char *str)
struct ButAlign * neighbors[4]