Changeset View
Standalone View
source/blender/blenlib/intern/array_utils.c
| Show All 24 Lines | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_array_utils.h" | #include "BLI_array_utils.h" | ||||
| #include "BLI_alloca.h" | #include "BLI_alloca.h" | ||||
| #include "BLI_math_base.h" | |||||
| #include "BLI_sys_types.h" | #include "BLI_sys_types.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLI_strict_flags.h" | #include "BLI_strict_flags.h" | ||||
| /** | /** | ||||
| *In-place array reverse. | *In-place array reverse. | ||||
| * | * | ||||
| ▲ Show 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | bool _bli_array_is_zeroed(const void *arr_v, unsigned int arr_len, size_t arr_stride) | ||||
| size_t i = arr_stride * arr_len; | size_t i = arr_stride * arr_len; | ||||
| while (i--) { | while (i--) { | ||||
| if (*(arr_step++)) { | if (*(arr_step++)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| /** | |||||
| * Smart function to sample a rect spiraling outside, nice for selection ID. | |||||
| * | |||||
| * \param arr_shape: size [h, w]. | |||||
| * \param center: coordinates [y, x] indicating where to start reading. | |||||
brecht: Why flip the x/y order? I'm having a hard time reading the code since I have to mentally flip… | |||||
mano-wiiAuthorUnsubmitted Done Inline ActionsIn fact, using the x, y order can be useful when, for example, the mouse coordinates are passed. value = buff[h][w] Having the h before the w. But this is not mandatory. In fact, I had set the order x, y before. mano-wii: In fact, using the x, y order can be useful when, for example, the mouse coordinates are passed. | |||||
brechtUnsubmitted Done Inline ActionsPlease use the standard x,y and w,h order we use everywhere else in Blender. brecht: Please use the standard x,y and w,h order we use everywhere else in Blender. | |||||
| */ | |||||
| bool _bli_array_iter_spiral_square(const void *arr_v, | |||||
| const int arr_shape[2], | |||||
| const size_t arr_stride[2], | |||||
brechtUnsubmitted Done Inline ActionsThis stride handling is too complicated. All you need is the size of an element, and you can multiply with that at the very end when calling test_fn, using it earlier makes things hard to understand. brecht: This stride handling is too complicated.
All you need is the size of an element, and you can… | |||||
mano-wiiAuthorUnsubmitted Done Inline Actions
I feel that the patch will have to change a lot if it is to implement another way of dealing with the offsets. test_fn(arr + offset_other + offset_iter, user_data) mano-wii: > (...) and you can multiply with that at the very end when calling `test_fn`, using it earlier… | |||||
| const int center[2], | |||||
| const bool (*test_fn)(const void *arr_item, void *user_data), | |||||
| void *user_data) | |||||
| { | |||||
| BLI_assert(center[0] >= 0 && center[1] >= 0 && center[0] < arr_shape[0] && | |||||
| center[1] < arr_shape[1]); | |||||
| const char *arr = arr_v; | |||||
| const int stride[2] = {(int)arr_stride[0], (int)arr_stride[1]}; | |||||
| int offset[2] = {center[0] * stride[0], center[1] * stride[1]}; | |||||
| if (test_fn(arr + offset[0] + offset[1], user_data)) { | |||||
| return true; | |||||
| } | |||||
| int step_max; | |||||
| { | |||||
| /* Calculate the maximum number of possible steps. */ | |||||
| int step_max_w, step_max_h; | |||||
| if (2 * center[0] < (arr_shape[0] - 1)) { | |||||
| step_max_w = 2 * (arr_shape[0] - center[0] - 1); | |||||
| } | |||||
| else { | |||||
| step_max_w = 2 * center[0] + 1; | |||||
| } | |||||
| if (2 * center[1] < (arr_shape[1] - 1)) { | |||||
| step_max_h = 2 * (arr_shape[1] - center[1] - 1) - 1; | |||||
| } | |||||
| else { | |||||
| step_max_h = 2 * center[1]; | |||||
| } | |||||
| step_max = max_ii(step_max_h, step_max_w); | |||||
| } | |||||
| int step_num = 1; | |||||
| int limits[2]; | |||||
| limits[0] = (arr_shape[0] - 1) * stride[0]; | |||||
| limits[1] = stride[0] - stride[1]; | |||||
| bool sign = false; | |||||
| while (true) { | |||||
| int axis = 2; | |||||
| while (axis--) { | |||||
| int offset_step = stride[axis]; | |||||
| if (!sign) { | |||||
| offset_step *= -1; | |||||
| } | |||||
| int offset_src = offset[axis] + offset_step; | |||||
| int offset_dst = offset[axis] + step_num * offset_step; | |||||
brechtUnsubmitted Done Inline ActionsUse start/end rather then src/dst, the latter is usually used to copy something from src to dst, not for iteration. brecht: Use start/end rather then src/dst, the latter is usually used to copy something from src to dst… | |||||
| /* Even if the offset_dst is out bound, update the result. */ | |||||
| offset[axis] = offset_dst; | |||||
| int offset_other = offset[!axis]; | |||||
| if (offset_other < 0 || offset_other > limits[!axis]) { | |||||
| /* This entire range is out of bound. */ | |||||
| continue; | |||||
| } | |||||
| if (sign) { | |||||
| CLAMP_MIN(offset_src, 0); | |||||
| CLAMP_MAX(offset_dst, limits[axis]); | |||||
| } | |||||
| else { | |||||
| CLAMP_MAX(offset_src, limits[axis]); | |||||
| CLAMP_MIN(offset_dst, 0); | |||||
| } | |||||
brechtUnsubmitted Done Inline ActionsKeep it simple: CLAMP(offset_src, 0, limits[axis]); CLAMP(offset_dst, 0, limits[axis]); brecht: Keep it simple:
```
CLAMP(offset_src, 0, limits[axis]);
CLAMP(offset_dst, 0, limits[axis]);
``` | |||||
| /* Iterate each value in the range. */ | |||||
| while (true) { | |||||
| if (test_fn(arr + offset_other + offset_src, user_data)) { | |||||
| return true; | |||||
| } | |||||
| if (offset_src == offset_dst) { | |||||
| break; | |||||
| } | |||||
| offset_src += offset_step; | |||||
| } | |||||
| } | |||||
| if (step_num == step_max) { | |||||
brechtUnsubmitted Done Inline ActionsComputing step_max in advance looks tricky, can you terminate in a way similar to the old code, but checking both axes? if ((offset[0] < 0 || offset[0] > limits[0]) &&
(offset[1] < 0 || offset[1] > limits[1]))brecht: Computing `step_max` in advance looks tricky, can you terminate in a way similar to the old… | |||||
| return false; | |||||
| } | |||||
| step_num++; | |||||
| sign = !sign; | |||||
| } | |||||
| } | |||||
Why flip the x/y order? I'm having a hard time reading the code since I have to mentally flip the axes all the time.