Changeset View
Standalone View
source/blender/editors/interface/interface.c
| Show All 28 Lines | |||||
| #include <float.h> | #include <float.h> | ||||
| #include <limits.h> | #include <limits.h> | ||||
| #include <math.h> | #include <math.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <ctype.h> | #include <ctype.h> | ||||
| #include <stddef.h> /* offsetof() */ | #include <stddef.h> /* offsetof() */ | ||||
campbellbarton: Note that `interface.c` is nearly 5k lines ~ mainly for interface access and defining new… | |||||
Not Done Inline ActionsAgree, will do for final commit. mont29: Agree, will do for final commit. | |||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_screen_types.h" | #include "DNA_screen_types.h" | ||||
| #include "DNA_userdef_types.h" | #include "DNA_userdef_types.h" | ||||
| #include "BLI_alloca.h" | |||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_string.h" | #include "BLI_string.h" | ||||
| #include "BLI_string_utf8.h" | #include "BLI_string_utf8.h" | ||||
| #include "BLI_rect.h" | #include "BLI_rect.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| ▲ Show 20 Lines • Show All 1,150 Lines • ▼ Show 20 Lines | void UI_block_update_from_old(const bContext *C, uiBlock *block) | ||||
| block->auto_open = block->oldblock->auto_open; | block->auto_open = block->oldblock->auto_open; | ||||
| block->auto_open_last = block->oldblock->auto_open_last; | block->auto_open_last = block->oldblock->auto_open_last; | ||||
| block->tooltipdisabled = block->oldblock->tooltipdisabled; | block->tooltipdisabled = block->oldblock->tooltipdisabled; | ||||
| BLI_movelisttolist(&block->color_pickers.list, &block->oldblock->color_pickers.list); | BLI_movelisttolist(&block->color_pickers.list, &block->oldblock->color_pickers.list); | ||||
| block->oldblock = NULL; | block->oldblock = NULL; | ||||
| } | } | ||||
| #include "PIL_time_utildefines.h" | |||||
| void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2]) | void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2]) | ||||
| { | { | ||||
| wmWindow *window = CTX_wm_window(C); | wmWindow *window = CTX_wm_window(C); | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| uiBut *but; | uiBut *but; | ||||
| BLI_assert(block->active); | BLI_assert(block->active); | ||||
| Show All 24 Lines | void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2]) | ||||
| } | } | ||||
| /* handle pending stuff */ | /* handle pending stuff */ | ||||
| if (block->layouts.first) { | if (block->layouts.first) { | ||||
| UI_block_layout_resolve(block, NULL, NULL); | UI_block_layout_resolve(block, NULL, NULL); | ||||
| } | } | ||||
| // TIMEIT_BENCH(ui_block_align_calc(block), ui_block_align_calc); | |||||
| ui_block_align_calc(block); | ui_block_align_calc(block); | ||||
| if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) { | if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) { | ||||
| ui_menu_block_set_keyaccels(block); /* could use a different flag to check */ | ui_menu_block_set_keyaccels(block); /* could use a different flag to check */ | ||||
| } | } | ||||
| if (block->flag & UI_BLOCK_LOOP) { | if (block->flag & UI_BLOCK_LOOP) { | ||||
| ui_menu_block_set_keymaps(C, block); | ui_menu_block_set_keymaps(C, block); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,662 Lines • ▼ Show 20 Lines | void UI_block_align_begin(uiBlock *block) | ||||
| if (block->flag & UI_BUT_ALIGN) UI_block_align_end(block); | if (block->flag & UI_BUT_ALIGN) UI_block_align_end(block); | ||||
| block->flag |= UI_BUT_ALIGN_DOWN; | block->flag |= UI_BUT_ALIGN_DOWN; | ||||
| block->alignnr++; | block->alignnr++; | ||||
| /* buttons declared after this call will get this align nr */ // XXX flag? | /* buttons declared after this call will get this align nr */ // XXX flag? | ||||
| } | } | ||||
| void UI_block_align_end(uiBlock *block) | |||||
| { | |||||
| block->flag &= ~UI_BUT_ALIGN; /* all 4 flags */ | |||||
| } | |||||
| #ifdef NEW_ALIGN_CODE | |||||
| /** | |||||
| * This struct stores a (simplified) 2D representation of all buttons of a same align group, with their | |||||
| * immediate neighbors (if found), and needed value to compute 'stitching' of aligned buttons. | |||||
| * | |||||
| * \note This simplistic struct cannot fully represent complex layouts where buttons share some 'align space' with | |||||
| * several others (see schema below), we'd need linked list and more complex code to handle that. | |||||
| * However, looks like we can do without that for now, wich is rather lucky! | |||||
| * +-----------+-----------+ | |||||
| * | BUT 1 | BUT 2 | BUT 3 has two 'top' neighbors... | |||||
| * |-----------------------| => In practice, we only store one of BUT 1 or 2 (which ones is not | |||||
| * | BUT 3 | really deterministic), and assume the other stores a ref to BUT 3. | |||||
| * +-----------------------+ | |||||
| * This will probably not work in all possible cases, but not sure we want to support such exotic cases anyway. | |||||
| */ | |||||
| typedef struct ButAlign { | |||||
| uiBut *but; | |||||
| /* Neighbor buttons */ | |||||
| struct ButAlign *neighbors[4]; | |||||
| /* Pointers to coordinates (rctf values) of the button. */ | |||||
| float *borders[4]; | |||||
| /* Distances to the neighbors. */ | |||||
| float dists[4]; | |||||
| /* Flags, used to mark whether we should 'stitch' the corners of this button with its neighbors' ones. */ | |||||
| char flags[4]; | |||||
| } ButAlign; | |||||
| /* Side-related enums and flags. */ | |||||
| enum { | |||||
| /* Sides (used as indices, order is **crucial**, this allows us to factorize code in a loop over the four sides). */ | |||||
| LEFT = 0, | |||||
| TOP = 1, | |||||
| RIGHT = 2, | |||||
| DOWN = 3, | |||||
| TOTSIDES = 4, | |||||
| /* Stict flags, built from sides values. */ | |||||
| STITCH_LEFT = 1 << LEFT, | |||||
| STITCH_TOP = 1 << TOP, | |||||
| STITCH_RIGHT = 1 << RIGHT, | |||||
| STITCH_DOWN = 1 << DOWN, | |||||
| }; | |||||
| /* Given one side, compute the three other ones */ | |||||
| #define SIDE1(_s) (((_s) + 1) % TOTSIDES) | |||||
| #define OPPOSITE(_s) (((_s) + 2) % TOTSIDES) | |||||
| #define SIDE2(_s) (((_s) + 3) % TOTSIDES) | |||||
| /* 0: LEFT/RIGHT sides; 1 = TOP/DOWN sides. */ | |||||
| #define IS_COLUMN(_s) ((_s) % 2) | |||||
| /* Stich flag from side value. */ | |||||
| #define STITCH(_s) (1 << (_s)) | |||||
| bool ui_but_can_align(uiBut *but) | |||||
| { | |||||
| return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE); | |||||
| } | |||||
| /** | |||||
| * This function chacks a pair of buttons (assumed in a same align group), and if they are neighbors, | |||||
Done Inline ActionsTypo: chacks->checks Severin: Typo: chacks->checks | |||||
| * set needed data accordingly. | |||||
| * | |||||
| * \note It is designed to be called in total random order of buttons. | |||||
| */ | |||||
| static void block_align_proximity_compute(ButAlign *butal, ButAlign *butal_other) | |||||
| { | |||||
| /* That's the biggest gap between two borders to consider them 'alignable'. */ | |||||
| const float max_delta = 0.45f * max_ii(UI_UNIT_Y, UI_UNIT_X); | |||||
| float delta; | |||||
| int side; | |||||
| const bool buts_share[2] = { | |||||
| /* Sharing same line? */ | |||||
| !((*butal->borders[DOWN] >= *butal_other->borders[TOP]) || | |||||
| (*butal->borders[TOP] <= *butal_other->borders[DOWN])), | |||||
| /* Sharing same column? */ | |||||
| !((*butal->borders[LEFT] >= *butal_other->borders[RIGHT]) || | |||||
| (*butal->borders[RIGHT] <= *butal_other->borders[LEFT])), | |||||
| }; | |||||
| for (side = 0; side < TOTSIDES; side++) { | |||||
| /* We are only interested in buttons which share a same line (LEFT/RIGHT sides) or column (TOP/DOWN sides). */ | |||||
| if (buts_share[IS_COLUMN(side)]) { | |||||
| const int side_opp = OPPOSITE(side); | |||||
| /* We rely on exact zero value here as an 'already processed' flag, so ensure we never actually | |||||
| * set a zero value at this stage. FLT_MIN is zero-enough for UI position computing. ;) */ | |||||
| delta = max_ff(fabsf(*butal->borders[side] - *butal_other->borders[side_opp]), FLT_MIN); | |||||
| if (delta < max_delta) { | |||||
| /* We are only interested in neighbors that are at least as close as already found ones. */ | |||||
| if (delta <= butal->dists[side]) { | |||||
| const bool butal_can_align = ui_but_can_align(butal->but); | |||||
| const bool butal_other_can_align = ui_but_can_align(butal_other->but); | |||||
| if (delta < butal->dists[side]) { | |||||
| /* We found a closer neighbor. | |||||
| * If both buttons are alignable, we set them as each other neighbors. | |||||
| * Else, we have an unalignable one, we need to reset the other's matching neighbor to NULL | |||||
| * if its 'proximity distance' is really lower with current one. */ | |||||
| if (butal_can_align && butal_other_can_align) { | |||||
| butal->neighbors[side] = butal_other; | |||||
| butal_other->neighbors[side_opp] = butal; | |||||
| } | |||||
| else if (butal_can_align && (delta < butal->dists[side])) { | |||||
| butal->neighbors[side] = NULL; | |||||
| } | |||||
| else if (butal_other_can_align && (delta < butal_other->dists[side_opp])) { | |||||
| butal_other->neighbors[side_opp] = NULL; | |||||
| } | |||||
| butal->dists[side] = butal_other->dists[side_opp] = delta; | |||||
| } | |||||
| if (butal_can_align && butal_other_can_align) { | |||||
| const int side_s1 = SIDE1(side); | |||||
| const int side_s2 = SIDE2(side); | |||||
| const int stitch = STITCH(side); | |||||
| const int stitch_opp = STITCH(side_opp); | |||||
| if (butal->neighbors[side] == NULL) { | |||||
| butal->neighbors[side] = butal_other; | |||||
| } | |||||
| if (butal_other->neighbors[side_opp] == NULL) { | |||||
| butal_other->neighbors[side_opp] = butal; | |||||
| } | |||||
| /* We have a pair of neighbors, we have to check whether we can stitch their matching corners. | |||||
| * E.g. if butal_other is on the left of butal (that is, side == LEFT), | |||||
| * if both TOP (side_s1) coordinates of buttons are close enough, we can stitch | |||||
| * their upper matching corners, and same for DOWN (side_s2) side. */ | |||||
| delta = fabsf(*butal->borders[side_s1] - *butal_other->borders[side_s1]); | |||||
| if (delta < max_delta) { | |||||
| butal->flags[side_s1] |= stitch; | |||||
| butal_other->flags[side_s1] |= stitch_opp; | |||||
| } | |||||
| delta = fabsf(*butal->borders[side_s2] - *butal_other->borders[side_s2]); | |||||
| if (delta < max_delta) { | |||||
| butal->flags[side_s2] |= stitch; | |||||
| butal_other->flags[side_s2] |= stitch_opp; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* We assume two buttons can only share one side at most - for until we have sperical UI... */ | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * This function takes care of case described in this schema: | |||||
| * +-----------+-----------+ | |||||
| * | BUT 1 | BUT 2 | | |||||
| * |-----------------------+ | |||||
| * | BUT 3 | | |||||
| * +-----------+ | |||||
Done Inline Actionsascii art can be inside <pre>...</pre> (to skip doxy formatting), also wouldn't bother to indent (same for other ascii art in this patch). eg: http://fossies.org/dox/blender-2.76b/bmesh__queries_8c.html#a01cc24309f04206082c6b4198d46912c campbellbarton: ascii art can be inside `<pre>...</pre>` (to skip doxy formatting), also wouldn't bother to… | |||||
| * Here, BUT 3 RIGHT side would not get 'dragged' to align with BUT 1 RIGHT side, since BUT 3 has not RIGHT neighbor. | |||||
| * So, this function, when called with BUT 1, will 'walk' the whole column in side_s1 direction (TOP or DOWN when | |||||
Done Inline ActionsCan use Doxygen \a command ... in \a side_s1 direction ... Severin: Can use Doxygen \a command ... `in \a side_s1 direction` ... | |||||
| * called for RIGHT side), and force buttons like BUT 3 to align as needed, if BUT 1 and BUT 3 were detected as needing | |||||
| * top-right corner stitching in block_align_proximity_compute() step. | |||||
| * | |||||
| * \note To avoid doing this twice, some stitching flags are cleared to break the 'stitching connection' | |||||
| * between neighbors. | |||||
| */ | |||||
| 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) | |||||
| { | |||||
| ButAlign *butal_neighbor; | |||||
| const int stitch_s1 = STITCH(side_s1); | |||||
| const int stitch_s2 = STITCH(side_s2); | |||||
| // printf("%s (%d) (%f, %f)\n", butal->but->str[0] ? butal->but->str : "<noname>", i, *butal->borders[i], *butal->borders[i_opp]); | |||||
| // if (STREQ(butal->but->str, "Frame Step: ")) { | |||||
| // printf("%s: main side %d, stride side %d: %f\n", butal->but->str, i, i_s1, butal->dists[i]); | |||||
| // } | |||||
| /* We have to check stitching flags on both sides of the stitching, since we only clear one of them flags to break | |||||
| * any future loop on same 'columns/side' case. | |||||
| * Also, if butal is spanning over several rows or columns of neighbors, it may have both of its stiching flags | |||||
| * set, but would not be the case of its immediate neighbor! */ | |||||
| while ((butal->flags[side] & stitch_s1) && | |||||
| (butal = butal->neighbors[side_s1]) && | |||||
| (butal->flags[side] & stitch_s2)) | |||||
| { | |||||
| butal_neighbor = butal->neighbors[side]; | |||||
| /* If we actually do have a neighbor, we directly set its values accordingly, and clear its matching 'dist' | |||||
| * to prevent it being set again later... */ | |||||
| if (butal_neighbor) { | |||||
| butal->but->drawflag |= align; | |||||
| butal_neighbor->but->drawflag |= align_opp; | |||||
| *butal_neighbor->borders[side_opp] = co; | |||||
| butal_neighbor->dists[side_opp] = 0.0f; | |||||
| } | |||||
| /* See definition of UI_BUT_ALIGN_STITCH_LEFT/TOP for reason of this... */ | |||||
| else if (side == LEFT) { | |||||
| butal->but->drawflag |= UI_BUT_ALIGN_STITCH_LEFT; | |||||
| } | |||||
| else if (side == TOP) { | |||||
| butal->but->drawflag |= UI_BUT_ALIGN_STITCH_TOP; | |||||
| } | |||||
| *butal->borders[side] = co; | |||||
| butal->dists[side] = 0.0f; | |||||
| /* Clearing one of the 'flags pair' here should be enough to prevent this loop running on | |||||
| * the same column, side and direction again. */ | |||||
| butal->flags[side] &= ~stitch_s2; | |||||
| // printf("\t%s\n", butal->but->str[0] ? butal->but->str : "<noname>"); | |||||
| // if (STREQ(butal->but->str, "Frame Step: ")) { | |||||
| // printf("\t\t%s: main side %d, stride side %d: %f (%f vs %f, %f)\n", | |||||
| // butal->but->str, side, side_s1, butal->dists[side], co, | |||||
| // *butal->borders[side], *butal->borders[side_opp]); | |||||
| // } | |||||
| // else if (butal_neighbor && STREQ(butal_neighbor->but->str, "Frame Step: ")) { | |||||
| // printf("\t\t%s (neighbor): main side %d, stride side %d: %f (%f vs %f, %f)\n", | |||||
| // butal_neighbor->but->str, side, side_s1, butal_neighbor->dists[side], co, | |||||
| // *butal_neighbor->borders[side], *butal_neighbor->borders[side_opp]); | |||||
| // } | |||||
Not Done Inline ActionsWould put this in ifdef... #ifdef DEBUG_PRINT, which can be defined at top of file (annoying to change all comments to see logging output). campbellbarton: Would put this in ifdef... `#ifdef DEBUG_PRINT`, which can be defined at top of file (annoying… | |||||
Not Done Inline ActionsWell… my idea was to nuke all those prints for master commit… Those are really dev stuff, only kept until code is considered finished. :) mont29: Well… my idea was to nuke all those prints for master commit… Those are really dev stuff, only… | |||||
| } | |||||
| // printf("\n"); | |||||
| } | |||||
| /** | |||||
| * Compute the alignment of all 'align groups' of buttons in given block. | |||||
| * | |||||
| * This is using an order-independent alorithm, i.e. alignement of buttons should be OK regardless of order in which | |||||
Done Inline ActionsTypos: alorithm->algorithm, alignement->alignment Severin: Typos: alorithm->algorithm, alignement->alignment | |||||
| * they are added to the block. | |||||
| */ | |||||
| void ui_block_align_calc(uiBlock *block) | |||||
| { | |||||
| uiBut *but; | |||||
| int num_buttons = 0; | |||||
| const int sides_to_ui_but_align_flags[4] = { | |||||
| UI_BUT_ALIGN_LEFT, UI_BUT_ALIGN_TOP, UI_BUT_ALIGN_RIGHT, UI_BUT_ALIGN_DOWN}; | |||||
| ButAlign *butal_array; | |||||
| ButAlign *butal, *butal_other; | |||||
| int side; | |||||
| int i, j; | |||||
| /* First loop: we count number of buttons belonging to an align group, and clear their align flag. */ | |||||
| for (but = block->buttons.first; but; but = but->next) { | |||||
| /* Clear old align flags. */ | |||||
| but->drawflag &= ~UI_BUT_ALIGN_ALL; | |||||
| if (but->alignnr == 0) { | |||||
| continue; | |||||
| } | |||||
| num_buttons++; | |||||
| } | |||||
| if (num_buttons < 2) { | |||||
| /* No need to go further if we have nothing to align... */ | |||||
| return; | |||||
| } | |||||
| butal_array = alloca(sizeof(*butal_array) * (size_t)num_buttons); | |||||
| memset(butal_array, 0, sizeof(*butal_array) * (size_t)num_buttons); | |||||
| /* Second loop: we initialize our ButAlign data for each button. */ | |||||
| for (but = block->buttons.first, butal = butal_array; but; but = but->next) { | |||||
| if (but->alignnr == 0) { | |||||
| continue; | |||||
| } | |||||
| butal->but = but; | |||||
Not Done Inline ActionsSince this is pixels, its probably not breaking, Better practice not to convert float -> int here, just do (a < b) ? -1 : 1; campbellbarton: Since this is pixels, its probably not breaking,
but this could stop qsort from working… | |||||
| butal->borders[LEFT] = &but->rect.xmin; | |||||
| butal->borders[RIGHT] = &but->rect.xmax; | |||||
| butal->borders[DOWN] = &but->rect.ymin; | |||||
| butal->borders[TOP] = &but->rect.ymax; | |||||
| copy_v4_fl(butal->dists, FLT_MAX); | |||||
| butal++; | |||||
| } | |||||
| /* Third loop: for each pair of buttons in the same align group, we compute ther potential proximity. | |||||
| * Note that each pair is checked only once. */ | |||||
Done Inline ActionsLine is indented with spaces. Severin: Line is indented with spaces. | |||||
| for (i = 0, butal = butal_array; i < num_buttons; i++, butal++) { | |||||
Done Inline ActionsThink you should use i < num_buttons - 1 here? Loop below won't run for last button, but looks like below, butal_array is accessed out of bounds in case i + 1 == num_buttons. Severin: Think you should use `i < num_buttons - 1` here? Loop below won't run for last button, but… | |||||
Not Done Inline ActionsNo out-of-bound access, since we are only manipulating a pointer in butal_other = &butal_array[i + 1]. Nice catch though! mont29: No out-of-bound access, since we are only manipulating a pointer in `butal_other = &butal_array… | |||||
| const short alignnr = butal->but->alignnr; | |||||
| for (j = i + 1, butal_other = &butal_array[i + 1]; j < num_buttons; j++, butal_other++) { | |||||
| const bool butal_can_align = ui_but_can_align(butal->but); | |||||
| const bool butal_other_can_align = ui_but_can_align(butal_other->but); | |||||
| /* Nothing to do if both buttons are not in the same align group, or if none of them can be aligned. */ | |||||
| if ((butal_other->but->alignnr != alignnr) || !(butal_can_align || butal_other_can_align)) { | |||||
Not Done Inline ActionsShouldn't this be !(butal_can_align && butal_other_can_align)? Severin: Shouldn't this be `!(butal_can_align && butal_other_can_align)`? | |||||
Not Done Inline ActionsTotally not! :) mont29: Totally not! :)
Thing is, if you have to alignable buttons separated by a (thin!) separator… | |||||
| continue; | |||||
| } | |||||
| block_align_proximity_compute(butal, butal_other); | |||||
| } | |||||
| } | |||||
| /* Forth loop: we have all our 'aligned' buttons as a 'map' in butal_array. We need to: | |||||
| * - update their relevant coordinates to stitch them. | |||||
| * - assign them valid flags. | |||||
| */ | |||||
| for (i = 0; i < num_buttons; i++) { | |||||
| butal = &butal_array[i]; | |||||
| // printf("but %s:\n", butal->but->str); | |||||
| // printf("\t left-aligned with %s\n", butal->neighbors.left ? butal->neighbors.left->but->str : "<NONE>"); | |||||
| // printf("\t top-aligned with %s\n", butal->neighbors.top ? butal->neighbors.top->but->str : "<NONE>"); | |||||
| // printf("\tright-aligned with %s\n", butal->neighbors.right ? butal->neighbors.right->but->str : "<NONE>"); | |||||
| // printf("\t down-aligned with %s\n", butal->neighbors.down ? butal->neighbors.down->but->str : "<NONE>"); | |||||
| for (side = 0; side < 4; side++) { | |||||
Done Inline ActionsCan be side < TOTSIDES ;) Severin: Can be `side < TOTSIDES` ;) | |||||
| butal_other = butal->neighbors[side]; | |||||
| if (butal_other) { | |||||
| const int side_opp = OPPOSITE(side); | |||||
| const int side_s1 = SIDE1(side); | |||||
| const int side_s2 = SIDE2(side); | |||||
| const int align = sides_to_ui_but_align_flags[side]; | |||||
| const int align_opp = sides_to_ui_but_align_flags[side_opp]; | |||||
| float co; | |||||
| butal->but->drawflag |= align; | |||||
| butal_other->but->drawflag |= align_opp; | |||||
| if (butal->dists[side]) { | |||||
| float *delta = &butal->dists[side]; | |||||
| if (*butal->borders[side] < *butal_other->borders[side_opp]) { | |||||
| *delta *= 0.5f; | |||||
| } | |||||
| else { | |||||
| *delta *= -0.5f; | |||||
| } | |||||
| co = (*butal->borders[side] += *delta); | |||||
| if (butal_other->dists[side_opp]) { | |||||
| BLI_assert(butal_other->dists[side_opp] * 0.5f == fabsf(*delta)); | |||||
| *butal_other->borders[side_opp] = co; | |||||
| butal_other->dists[side_opp] = 0.0f; | |||||
| } | |||||
| *delta = 0.0f; | |||||
| } | |||||
| else { | |||||
| co = *butal->borders[side]; | |||||
| } | |||||
| block_align_stitch_neighbors(butal, side, side_opp, side_s1, side_s2, align, align_opp, co); | |||||
| block_align_stitch_neighbors(butal, side, side_opp, side_s2, side_s1, align, align_opp, co); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| #else | |||||
| bool ui_but_can_align(uiBut *but) | |||||
| { | |||||
| return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE); | |||||
| } | |||||
| static bool buts_are_horiz(uiBut *but1, uiBut *but2) | static bool buts_are_horiz(uiBut *but1, uiBut *but2) | ||||
| { | { | ||||
| float dx, dy; | float dx, dy; | ||||
| /* simple case which can fail if buttons shift apart | /* simple case which can fail if buttons shift apart | ||||
| * with proportional layouts, see: [#38602] */ | * with proportional layouts, see: [#38602] */ | ||||
| if ((but1->rect.ymin == but2->rect.ymin) && | if ((but1->rect.ymin == but2->rect.ymin) && | ||||
| (but1->rect.xmin != but2->rect.xmin)) | (but1->rect.xmin != but2->rect.xmin)) | ||||
| { | { | ||||
| return true; | return true; | ||||
| } | } | ||||
| dx = fabsf(but1->rect.xmax - but2->rect.xmin); | dx = fabsf(but1->rect.xmax - but2->rect.xmin); | ||||
| dy = fabsf(but1->rect.ymin - but2->rect.ymax); | dy = fabsf(but1->rect.ymin - but2->rect.ymax); | ||||
| return (dx <= dy); | return (dx <= dy); | ||||
| } | } | ||||
| void UI_block_align_end(uiBlock *block) | |||||
| { | |||||
| block->flag &= ~UI_BUT_ALIGN; /* all 4 flags */ | |||||
| } | |||||
| bool ui_but_can_align(uiBut *but) | |||||
| { | |||||
| return !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE); | |||||
| } | |||||
| static void ui_block_align_calc_but(uiBut *first, short nr) | static void ui_block_align_calc_but(uiBut *first, short nr) | ||||
| { | { | ||||
| uiBut *prev, *but = NULL, *next; | uiBut *prev, *but = NULL, *next; | ||||
| int flag = 0, cols = 0, rows = 0; | int flag = 0, cols = 0, rows = 0; | ||||
| /* auto align */ | /* auto align */ | ||||
| for (but = first; but && but->alignnr == nr; but = but->next) { | for (but = first; but && but->alignnr == nr; but = but->next) { | ||||
| ▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | if (but->alignnr) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| but = but->next; | but = but->next; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block) | struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block) | ||||
| { | { | ||||
| return IMB_colormanagement_display_get_named(block->display_device); | return IMB_colormanagement_display_get_named(block->display_device); | ||||
| } | } | ||||
| void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]) | void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 1,606 Lines • Show Last 20 Lines | |||||
Note that interface.c is nearly 5k lines ~ mainly for interface access and defining new buttons, I think this code could be move into interface_align.c (since it defines own struct + flags + utility functions).
For the purpose of patch review its easier to keep as is but think it'd be good to split out.