diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-09-05 15:56:03 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-09-05 15:56:03 +0300 |
commit | 572b1a644f29eff9b37b45543bfc27a2d68022c7 (patch) | |
tree | 86d1a83307378ee0e1506021f8c0729d82f3cc06 | |
parent | 7dfcbe01b0a2a1ca625c80eb385bf4753b3fb3ef (diff) | |
parent | 4d85396fe4f7e3a870fb844b5207179f7dd03eb2 (diff) |
Merge branch 'master' into blender2.8
29 files changed, 348 insertions, 165 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d520ee023f..21f01eac28c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -291,7 +291,7 @@ if(WITH_X11) endif() if(UNIX AND NOT APPLE) - option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" ON) + option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF) option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON) else() # not an option for other OS's diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake index 465ca3c034c..6dbf3f46b1a 100644 --- a/build_files/build_environment/cmake/options.cmake +++ b/build_files/build_environment/cmake/options.cmake @@ -66,9 +66,9 @@ if(WIN32) set(BLENDER_CMAKE_C_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS") if(WITH_OPTIMIZED_DEBUG) - set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /D PLATFORM_WINDOWS /MTd /Zi /Ob0 /Od /RTC1 /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS") - else() set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/MTd /O2 /Ob2 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS") + else() + set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /D PLATFORM_WINDOWS /MTd /Zi /Ob0 /Od /RTC1 /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS") endif() set(BLENDER_CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS") set(BLENDER_CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS") diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 7b3d05e5a6e..75064f2c5ef 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -1013,9 +1013,9 @@ def pymodule2sphinx(basepath, module_name, module, title): context_type_map = { "active_base": ("ObjectBase", False), "active_bone": ("EditBone", False), + "active_gpencil_brush": ("GPencilSculptBrush", False), "active_gpencil_frame": ("GreasePencilLayer", True), "active_gpencil_layer": ("GPencilLayer", True), - "active_gpencil_brush": ("GPencilSculptBrush", False), "active_gpencil_palette": ("GPencilPalette", True), "active_gpencil_palettecolor": ("GPencilPaletteColor", True), "active_node": ("Node", False), @@ -1069,6 +1069,7 @@ context_type_map = { "selected_bones": ("EditBone", True), "selected_editable_bases": ("ObjectBase", True), "selected_editable_bones": ("EditBone", True), + "selected_editable_fcurves": ("FCurce", True), "selected_editable_objects": ("Object", True), "selected_editable_sequences": ("Sequence", True), "selected_nodes": ("Node", True), diff --git a/intern/cycles/kernel/bvh/bvh_nodes.h b/intern/cycles/kernel/bvh/bvh_nodes.h index 74a9ebf14e4..5f1dd434a44 100644 --- a/intern/cycles/kernel/bvh/bvh_nodes.h +++ b/intern/cycles/kernel/bvh/bvh_nodes.h @@ -615,7 +615,7 @@ ccl_device_forceinline int bvh_node_intersect_robust(KernelGlobals *kg, const float3& P, const float3& dir, const ssef& isect_near, - const ssef& isect_far, + const ssef& isect_far, const ssef& tsplat, const ssef Psplat[3], const ssef idirsplat[3], diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h index b91aba6e03c..bb6bdc7fbd0 100644 --- a/intern/cycles/kernel/kernel_shadow.h +++ b/intern/cycles/kernel/kernel_shadow.h @@ -204,7 +204,7 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg, } # ifdef __VOLUME__ if(!blocked && state->volume_stack[0].shader != SHADER_NONE) { - /* Apply attenuation from current volume shader/ */ + /* Apply attenuation from current volume shader. */ kernel_volume_shadow(kg, shadow_sd, state, ray, shadow); } # endif diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h index 50c9acec4ee..19bfee6d039 100644 --- a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h +++ b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h @@ -89,10 +89,10 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg) float3 shadow; if(!shadow_blocked(kg, - emission_sd, - state, - &ray, - &shadow)) + emission_sd, + state, + &ray, + &shadow)) { /* accumulate */ path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp); diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 80ec77f8b4a..bb94b9bb82a 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -522,6 +522,10 @@ bool ImageManager::file_load_image(Image *img, vector<StorageType> pixels_storage; StorageType *pixels; const size_t max_size = max(max(width, height), depth); + if(max_size == 0) { + /* Don't bother with invalid images. */ + return false; + } if(texture_limit > 0 && max_size > texture_limit) { pixels_storage.resize(((size_t)width)*height*depth*4); pixels = &pixels_storage[0]; @@ -529,6 +533,10 @@ bool ImageManager::file_load_image(Image *img, else { pixels = (StorageType*)tex_img.resize(width, height, depth); } + if(pixels == NULL) { + /* Could be that we've run out of memory. */ + return false; + } bool cmyk = false; const size_t num_pixels = ((size_t)width) * height * depth; if(in) { diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 348e652eadd..fb04d49bcd9 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -224,7 +224,7 @@ ccl_device_inline bool isfinite_safe(float f) { /* By IEEE 754 rule, 2*Inf equals Inf */ unsigned int x = __float_as_uint(f); - return (f == f) && (x == 0 || x == (1 << 31) || (f != 2.0f*f)) && !((x << 1) > 0xff000000u); + return (f == f) && (x == 0 || x == (1u << 31) || (f != 2.0f*f)) && !((x << 1) > 0xff000000u); } ccl_device_inline float ensure_finite(float v) diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index 966a1fe877c..185a0e73279 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -37,6 +37,7 @@ __all__ = ( "register_module", "register_manual_map", "unregister_manual_map", + "register_classes_factory", "register_submodule_factory", "make_rna_paths", "manual_map", @@ -702,6 +703,24 @@ def unregister_module(module, verbose=False): print("done.\n") +def register_classes_factory(classes): + """ + Utility function to create register and unregister functions + which simply registers and unregisters a sequence of classes. + """ + def register(): + from bpy.utils import register_class + for cls in classes: + register_class(cls) + + def unregister(): + from bpy.utils import unregister_class + for cls in reversed(classes): + unregister_class(cls) + + return register, unregister + + def register_submodule_factory(module_name, submodule_names): """ Utility function to create register and unregister functions diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py index 94f5e9e17bb..03f43486371 100644 --- a/release/scripts/modules/rna_info.py +++ b/release/scripts/modules/rna_info.py @@ -82,6 +82,32 @@ def float_as_string(f): return val_str +def get_py_class_from_rna(rna_type): + """ Get's the Python type for a class which isn't necessarily added to ``bpy.types``. + """ + identifier = rna_type.identifier + py_class = getattr(bpy.types, identifier, None) + if py_class is not None: + return py_class + + def subclasses_recurse(cls): + for c in cls.__subclasses__(): + # is_registered + if "bl_rna" in cls.__dict__: + yield c + yield from subclasses_recurse(c) + + while py_class is None: + base = rna_type.base + if base is None: + raise Exception("can't find type") + py_class_base = getattr(bpy.types, base.identifier, None) + if py_class_base is not None: + for cls in subclasses_recurse(py_class_base): + if cls.bl_rna.identifier == identifier: + return cls + + class InfoStructRNA: __slots__ = ( "bl_rna", @@ -146,7 +172,8 @@ class InfoStructRNA: def _get_py_visible_attrs(self): attrs = [] - py_class = getattr(bpy.types, self.identifier) + py_class = get_py_class_from_rna(self.bl_rna) + for attr_str in dir(py_class): if attr_str.startswith("_"): continue @@ -437,7 +464,11 @@ class InfoOperatorRNA: self.args.append(prop) def get_location(self): - op_class = getattr(bpy.types, self.identifier) + try: + op_class = getattr(bpy.types, self.identifier) + except AttributeError: + # defined in C. + return None, None op_func = getattr(op_class, "execute", None) if op_func is None: op_func = getattr(op_class, "invoke", None) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 1204effffdc..8f41f0611d4 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2112,6 +2112,11 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac short (*clnors)[2] = NULL; bool free_polynors = false; + /* Note that we enforce computing clnors when the clnor space array is requested by caller here. + * However, we obviously only use the autosmooth angle threshold only in case autosmooth is enabled. */ + const bool use_split_normals = (r_lnors_spacearr != NULL) || ((mesh->flag & ME_AUTOSMOOTH) != 0); + const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI; + if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL); memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop); @@ -2140,10 +2145,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac BKE_mesh_normals_loop_split( mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, - /* Note that we enforce computing clnors when the clnor space array is requested by caller here. - * However, we obviously only use the autosmooth angle threshold only in case autosmooth is enabled. */ - r_lnors_spacearr != NULL, (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI, - r_lnors_spacearr, clnors, NULL); + use_split_normals, split_angle, r_lnors_spacearr, clnors, NULL); if (free_polynors) { MEM_freeN(polynors); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 5f58af7e538..4818c7a0217 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -484,9 +484,12 @@ void BKE_sequencer_editing_free(Scene *scene) static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) { +#if 0 + /* Bute buffer is supposed to be in sequencer working space already. */ if (ibuf->rect != NULL) { IMB_colormanagement_assign_rect_colorspace(ibuf, scene->sequencer_colorspace_settings.name); } +#endif if (ibuf->rect_float != NULL) { IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name); } diff --git a/source/blender/blenlib/BLI_dial.h b/source/blender/blenlib/BLI_dial.h index ad7680fe03e..71ab57bb61a 100644 --- a/source/blender/blenlib/BLI_dial.h +++ b/source/blender/blenlib/BLI_dial.h @@ -52,8 +52,8 @@ typedef struct Dial Dial; -Dial *BLI_dial_initialize(float start_position[2], float threshold); +Dial *BLI_dial_initialize(const float start_position[2], float threshold); -float BLI_dial_angle(Dial *dial, float current_position[2]); +float BLI_dial_angle(Dial *dial, const float current_position[2]); #endif /* __BLI_DIAL_H__ */ diff --git a/source/blender/blenlib/BLI_kdtree.h b/source/blender/blenlib/BLI_kdtree.h index aa54e1c823c..18908f8c551 100644 --- a/source/blender/blenlib/BLI_kdtree.h +++ b/source/blender/blenlib/BLI_kdtree.h @@ -66,6 +66,10 @@ void BLI_kdtree_range_search_cb( const KDTree *tree, const float co[3], float range, bool (*search_cb)(void *user_data, int index, const float co[3], float dist_sq), void *user_data); +int BLI_kdtree_calc_duplicates_fast( + const KDTree *tree, const float range, bool use_index_order, + int *doubles); + /* Normal use is deprecated */ /* remove __normal functions when last users drop */ int BLI_kdtree_find_nearest_n__normal( diff --git a/source/blender/blenlib/intern/BLI_dial.c b/source/blender/blenlib/intern/BLI_dial.c index cfbb52847fd..89f18fa10b4 100644 --- a/source/blender/blenlib/intern/BLI_dial.c +++ b/source/blender/blenlib/intern/BLI_dial.c @@ -46,7 +46,7 @@ struct Dial { }; -Dial *BLI_dial_initialize(float start_position[2], float threshold) +Dial *BLI_dial_initialize(const float start_position[2], float threshold) { Dial *dial = MEM_callocN(sizeof(Dial), "dial"); @@ -56,7 +56,7 @@ Dial *BLI_dial_initialize(float start_position[2], float threshold) return dial; } -float BLI_dial_angle(Dial *dial, float current_position[2]) +float BLI_dial_angle(Dial *dial, const float current_position[2]) { float current_direction[2]; diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c index a81f9b28b83..84ac339cc4d 100644 --- a/source/blender/blenlib/intern/BLI_kdtree.c +++ b/source/blender/blenlib/intern/BLI_kdtree.c @@ -674,3 +674,123 @@ finally: if (stack != defaultstack) MEM_freeN(stack); } + +/** + * Use when we want to loop over nodes ordered by index. + * Requires indices to be aligned with nodes. + */ +static uint *kdtree_order(const KDTree *tree) +{ + const KDTreeNode *nodes = tree->nodes; + uint *order = MEM_mallocN(sizeof(uint) * tree->totnode, __func__); + for (uint i = 0; i < tree->totnode; i++) { + order[nodes[i].index] = i; + } + return order; +} + +/* -------------------------------------------------------------------- */ +/** \name BLI_kdtree_calc_duplicates_fast + * \{ */ + +struct DeDuplicateParams { + /* Static */ + const KDTreeNode *nodes; + float range; + float range_sq; + int *duplicates; + int *duplicates_found; + + /* Per Search */ + float search_co[3]; + int search; +}; + +static void deduplicate_recursive(const struct DeDuplicateParams *p, uint i) +{ + const KDTreeNode *node = &p->nodes[i]; + if (p->search_co[node->d] + p->range <= node->co[node->d]) { + if (node->left != KD_NODE_UNSET) { + deduplicate_recursive(p, node->left); + } + } + else if (p->search_co[node->d] - p->range >= node->co[node->d]) { + if (node->right != KD_NODE_UNSET) { + deduplicate_recursive(p, node->right); + } + } + else { + if ((p->search != node->index) && (p->duplicates[node->index] == -1)) { + if (compare_len_squared_v3v3(node->co, p->search_co, p->range_sq)) { + p->duplicates[node->index] = (int)p->search; + *p->duplicates_found += 1; + } + } + if (node->left != KD_NODE_UNSET) { + deduplicate_recursive(p, node->left); + } + if (node->right != KD_NODE_UNSET) { + deduplicate_recursive(p, node->right); + } + } +} + +/** + * Find duplicate points in \a range. + * Favors speed over quality since it doesn't find the best target vertex for merging. + * Nodes are looped over, duplicates are added when found. + * Nevertheless results are predictable. + * + * \param range: Coordinates in this range are candidates to be merged. + * \param use_index_order: Loop over the coordinates ordered by #KDTreeNode.index + * At the expense of some performance, this ensures the layout of the tree doesn't influence + * the iteration order. + * \param duplicates: An array of int's the length of #KDTree.totnode + * Values initialized to -1 are candidates to me merged. + * Setting the index to it's own position in the array prevents it from being touched, + * although it can still be used as a target. + * \returns The numebr of merges found (includes any merges already in the \a duplicates array). + * + * \note Merging is always a single step (target indices wont be marked for merging). + */ +int BLI_kdtree_calc_duplicates_fast( + const KDTree *tree, const float range, bool use_index_order, + int *duplicates) +{ + int found = 0; + struct DeDuplicateParams p = { + .nodes = tree->nodes, + .range = range, + .range_sq = range * range, + .duplicates = duplicates, + .duplicates_found = &found, + }; + + if (use_index_order) { + uint *order = kdtree_order(tree); + for (uint i = 0; i < tree->totnode; i++) { + const uint node_index = order[i]; + const int index = (int)i; + if (ELEM(duplicates[index], -1, index)) { + p.search = index; + copy_v3_v3(p.search_co, tree->nodes[node_index].co); + deduplicate_recursive(&p, tree->root); + } + } + MEM_freeN(order); + } + else { + for (uint i = 0; i < tree->totnode; i++) { + const uint node_index = i; + const int index = p.nodes[node_index].index; + if (ELEM(duplicates[index], -1, index)) { + p.search = index; + copy_v3_v3(p.search_co, tree->nodes[node_index].co); + deduplicate_recursive(&p, tree->root); + } + } + } + return found; +} + +/** \} */ diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 33e4dec107f..3559500bf63 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1728,6 +1728,9 @@ void rotate_m4(float mat[4][4], const char axis, const float angle) mat[0][col] = temp; } break; + default: + BLI_assert(0); + break; } } diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index f2f5debe73a..d8e6f250adf 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -30,6 +30,7 @@ #include "BLI_math.h" #include "BLI_alloca.h" +#include "BLI_kdtree.h" #include "BLI_stackdefines.h" #include "BLI_stack.h" @@ -277,29 +278,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) BMO_mesh_delete_oflag_context(bm, ELE_DEL, DEL_ONLYTAGGED); } -static int vergaverco(const void *e1, const void *e2) -{ - const BMVert *v1 = *(const void **)e1, *v2 = *(const void **)e2; - float x1 = v1->co[0] + v1->co[1] + v1->co[2]; - float x2 = v2->co[0] + v2->co[1] + v2->co[2]; - - if (x1 > x2) return 1; - else if (x1 < x2) return -1; - - const int i1 = BM_elem_index_get(v1); - const int i2 = BM_elem_index_get(v2); - - if (i1 > i2) return 1; - else if (i1 < i2) return -1; - - else return 0; -} - -// #define VERT_TESTED 1 // UNUSED -#define VERT_DOUBLE 2 -#define VERT_TARGET 4 #define VERT_KEEP 8 -// #define VERT_MARK 16 // UNUSED #define VERT_IN 32 #define EDGE_MARK 1 @@ -591,83 +570,62 @@ static void bmesh_find_doubles_common( BMesh *bm, BMOperator *op, BMOperator *optarget, BMOpSlot *optarget_slot) { - BMVert **verts; - int verts_len; + const BMOpSlot *slot_verts = BMO_slot_get(op->slots_in, "verts"); + BMVert * const *verts = (BMVert **)slot_verts->data.buf; + const int verts_len = slot_verts->len; - int i, j, keepvert = 0; + bool has_keep_vert = false; + bool found_duplicates = false; const float dist = BMO_slot_float_get(op->slots_in, "dist"); - const float dist_sq = dist * dist; - const float dist3 = ((float)M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */ /* Test whether keep_verts arg exists and is non-empty */ if (BMO_slot_exists(op->slots_in, "keep_verts")) { BMOIter oiter; - keepvert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL; + has_keep_vert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL; } - /* get the verts as an array we can sort */ - verts = BMO_slot_as_arrayN(op->slots_in, "verts", &verts_len); - - /* Ensure indices are different so we have a predictable order when values match. */ - for (i = 0; i < verts_len; i++) { - BM_elem_index_set(verts[i], i); /* set_dirty! */ - } - bm->elem_index_dirty |= BM_VERT; - - /* sort by vertex coordinates added together */ - qsort(verts, verts_len, sizeof(BMVert *), vergaverco); - /* Flag keep_verts */ - if (keepvert) { + if (has_keep_vert) { BMO_slot_buffer_flag_enable(bm, op->slots_in, "keep_verts", BM_VERT, VERT_KEEP); } - for (i = 0; i < verts_len; i++) { - BMVert *v_check = verts[i]; - - if (BMO_vert_flag_test(bm, v_check, VERT_DOUBLE | VERT_TARGET)) { - continue; + int *duplicates = MEM_mallocN(sizeof(int) * verts_len, __func__); + { + KDTree *tree = BLI_kdtree_new(verts_len); + for (int i = 0; i < verts_len; i++) { + BLI_kdtree_insert(tree, i, verts[i]->co); + if (has_keep_vert && BMO_vert_flag_test(bm, verts[i], VERT_KEEP)) { + duplicates[i] = i; + } + else { + duplicates[i] = -1; + } } - for (j = i + 1; j < verts_len; j++) { - BMVert *v_other = verts[j]; - - /* a match has already been found, (we could check which is best, for now don't) */ - if (BMO_vert_flag_test(bm, v_other, VERT_DOUBLE | VERT_TARGET)) { - continue; - } + BLI_kdtree_balance(tree); + found_duplicates = BLI_kdtree_calc_duplicates_fast(tree, dist, false, duplicates) != 0; + BLI_kdtree_free(tree); + } - /* Compare sort values of the verts using 3x tolerance (allowing for the tolerance - * on each of the three axes). This avoids the more expensive length comparison - * for most vertex pairs. */ - if ((v_other->co[0] + v_other->co[1] + v_other->co[2]) - - (v_check->co[0] + v_check->co[1] + v_check->co[2]) > dist3) - { - break; + if (found_duplicates) { + for (int i = 0; i < verts_len; i++) { + BMVert *v_check = verts[i]; + if (duplicates[i] == -1) { + /* nop (others can use as target) */ } - - if (keepvert) { - if (BMO_vert_flag_test(bm, v_other, VERT_KEEP) == BMO_vert_flag_test(bm, v_check, VERT_KEEP)) - continue; + else if (duplicates[i] == i) { + /* keep (others can use as target) */ } - - if (compare_len_squared_v3v3(v_check->co, v_other->co, dist_sq)) { - - /* If one vert is marked as keep, make sure it will be the target */ - if (BMO_vert_flag_test(bm, v_other, VERT_KEEP)) { - SWAP(BMVert *, v_check, v_other); - } - - BMO_vert_flag_enable(bm, v_other, VERT_DOUBLE); - BMO_vert_flag_enable(bm, v_check, VERT_TARGET); - - BMO_slot_map_elem_insert(optarget, optarget_slot, v_other, v_check); + else { + BMVert *v_other = verts[duplicates[i]]; + BLI_assert(ELEM(duplicates[duplicates[i]], -1, duplicates[i])); + BMO_slot_map_elem_insert(optarget, optarget_slot, v_check, v_other); } } } - MEM_freeN(verts); + MEM_freeN(duplicates); } void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op) diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp index 41f7da7c49f..0c2da8415f8 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp @@ -28,55 +28,58 @@ extern "C" { MovieClipAttributeOperation::MovieClipAttributeOperation() : NodeOperation() { this->addOutputSocket(COM_DT_VALUE); - this->m_valueSet = false; this->m_framenumber = 0; this->m_attribute = MCA_X; this->m_invert = false; } -void MovieClipAttributeOperation::executePixelSampled(float output[4], - float /*x*/, float /*y*/, - PixelSampler /*sampler*/) +void MovieClipAttributeOperation::initExecution() { - /* TODO(sergey): This code isn't really thread-safe. */ - if (!this->m_valueSet) { - float loc[2], scale, angle; - loc[0] = 0.0f; - loc[1] = 0.0f; - scale = 1.0f; - angle = 0.0f; - if (this->m_clip) { - int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_clip, this->m_framenumber); - BKE_tracking_stabilization_data_get(this->m_clip, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle); - } - switch (this->m_attribute) { - case MCA_SCALE: - this->m_value = scale; - break; - case MCA_ANGLE: - this->m_value = angle; - break; - case MCA_X: - this->m_value = loc[0]; - break; - case MCA_Y: - this->m_value = loc[1]; - break; + float loc[2], scale, angle; + loc[0] = 0.0f; + loc[1] = 0.0f; + scale = 1.0f; + angle = 0.0f; + int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame( + this->m_clip, this->m_framenumber); + BKE_tracking_stabilization_data_get(this->m_clip, + clip_framenr, + getWidth(), getHeight(), + loc, &scale, &angle); + switch (this->m_attribute) { + case MCA_SCALE: + this->m_value = scale; + break; + case MCA_ANGLE: + this->m_value = angle; + break; + case MCA_X: + this->m_value = loc[0]; + break; + case MCA_Y: + this->m_value = loc[1]; + break; + } + if (this->m_invert) { + if (this->m_attribute != MCA_SCALE) { + this->m_value = -this->m_value; } - if (this->m_invert) { - if (this->m_attribute != MCA_SCALE) { - this->m_value = -this->m_value; - } - else { - this->m_value = 1.0f / this->m_value; - } + else { + this->m_value = 1.0f / this->m_value; } - this->m_valueSet = true; } +} + +void MovieClipAttributeOperation::executePixelSampled(float output[4], + float /*x*/, float /*y*/, + PixelSampler /*sampler*/) +{ output[0] = this->m_value; } -void MovieClipAttributeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void MovieClipAttributeOperation::determineResolution( + unsigned int resolution[2], + unsigned int preferredResolution[2]) { resolution[0] = preferredResolution[0]; resolution[1] = preferredResolution[1]; diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h index 731b9debaf0..659f54c1ca2 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h @@ -39,16 +39,18 @@ class MovieClipAttributeOperation : public NodeOperation { private: MovieClip *m_clip; float m_value; - bool m_valueSet; int m_framenumber; bool m_invert; MovieClipAttribute m_attribute; + public: /** * Default constructor */ MovieClipAttributeOperation(); - + + void initExecution(); + /** * the inner loop of this program */ diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp index 117ae743ee7..46e155e43b5 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cpp +++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp @@ -271,9 +271,9 @@ bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, Read { rcti newInput; - newInput.xmax = (input->xmax - m_offsetX) * this->m_relX; + newInput.xmax = (input->xmax - m_offsetX) * this->m_relX + 1; newInput.xmin = (input->xmin - m_offsetX) * this->m_relX; - newInput.ymax = (input->ymax - m_offsetY) * this->m_relY; + newInput.ymax = (input->ymax - m_offsetY) * this->m_relY + 1; newInput.ymin = (input->ymin - m_offsetY) * this->m_relY; return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 9227f9b1097..90d44503013 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -252,8 +252,10 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl) for (gpf = gpl->frames.first; gpf; gpf = gpfn) { gpfn = gpf->next; - if (gpf->flag & GP_FRAME_SELECT) - changed |= BKE_gpencil_layer_delframe(gpl, gpf); + if (gpf->flag & GP_FRAME_SELECT) { + BKE_gpencil_layer_delframe(gpl, gpf); + changed = true; + } } return changed; diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 4bcc9f7b811..83e2a85db49 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -117,8 +117,8 @@ static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_t /* Interpolate all values */ interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor); - pt->pressure = interpf(prev->pressure, next->pressure, factor); - pt->strength = interpf(prev->strength, next->strength, factor); + pt->pressure = interpf(prev->pressure, next->pressure, 1.0f - factor); + pt->strength = interpf(prev->strength, next->strength, 1.0f - factor); CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); } } diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 553be0ad290..17edbc6cc1d 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -262,6 +262,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s { /* loop over data selecting */ switch (ale->type) { +#if 0 /* XXXX: Keyframes are not currently shown here */ case ANIMTYPE_GPDATABLOCK: { bGPdata *gpd = ale->data; @@ -271,6 +272,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s } break; } +#endif case ANIMTYPE_GPLAYER: ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode); break; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index fadc0dc3b60..6a11029d933 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -8401,8 +8401,15 @@ static void initTimeSlide(TransInfo *t) TransData *td = t->data; for (i = 0; i < t->total; i++, td++) { - if (min > *(td->val)) min = *(td->val); - if (max < *(td->val)) max = *(td->val); + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + float val = *(td->val); + + /* strip/action time to global (mapped) time */ + if (adt) + val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP); + + if (min > val) min = val; + if (max < val) max = val; } if (min == max) { @@ -8477,25 +8484,38 @@ static void applyTimeSlideValue(TransInfo *t, float sval) */ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; float cval = t->values[0]; - - /* apply NLA-mapping to necessary values */ - if (adt) - cval = BKE_nla_tweakedit_remap(adt, cval, NLATIME_CONVERT_UNMAP); - + /* only apply to data if in range */ if ((sval > minx) && (sval < maxx)) { float cvalc = CLAMPIS(cval, minx, maxx); + float ival = td->ival; float timefac; - + + /* NLA mapping magic here works as follows: + * - "ival" goes from strip time to global time + * - calculation is performed into td->val in global time + * (since sval and min/max are all in global time) + * - "td->val" then gets put back into strip time + */ + if (adt) { + /* strip to global */ + ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP); + } + /* left half? */ - if (td->ival < sval) { - timefac = (sval - td->ival) / (sval - minx); + if (ival < sval) { + timefac = (sval - ival) / (sval - minx); *(td->val) = cvalc - timefac * (cvalc - minx); } else { - timefac = (td->ival - sval) / (maxx - sval); + timefac = (ival - sval) / (maxx - sval); *(td->val) = cvalc + timefac * (maxx - cvalc); } + + if (adt) { + /* global to strip */ + *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP); + } } } } diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 1f3be8d73bb..f510ded6b60 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -47,6 +47,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_filetype.h" +#include "IMB_filter.h" #include "IMB_moviecache.h" #include "MEM_guardedalloc.h" @@ -1635,12 +1636,13 @@ static void *do_processor_transform_thread(void *handle_v) if (float_from_byte) { IMB_buffer_float_from_byte(float_buffer, byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - true, + false, width, height, width, width); - IMB_colormanagement_processor_apply(handle->cm_processor, - float_buffer, - width, height, channels, - predivide); + IMB_colormanagement_processor_apply(handle->cm_processor, + float_buffer, + width, height, channels, + predivide); + IMB_premultiply_rect_float(float_buffer, 4, width, height); } else { if (byte_buffer != NULL) { @@ -1776,14 +1778,15 @@ void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsig */ IMB_buffer_float_from_byte(float_buffer, byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - true, + false, width, height, width, width); + IMB_premultiply_rect_float(float_buffer, 4, width, height); return; } cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); processor_transform_apply_threaded(byte_buffer, float_buffer, width, height, channels, - cm_processor, true, true); + cm_processor, false, true); IMB_colormanagement_processor_free(cm_processor); } diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 156f8f85485..689a6406375 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1553,6 +1553,7 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_struct_register_funcs(srna, "rna_Operator_register", "rna_Operator_unregister", "rna_Operator_instance"); #endif RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); + RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -1638,7 +1639,7 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Operator Properties", "Input properties of an Operator"); RNA_def_struct_refine_func(srna, "rna_OperatorProperties_refine"); RNA_def_struct_idprops_func(srna, "rna_OperatorProperties_idprops"); - RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_PUBLIC_NAMESPACE_INHERIT); + RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); } static void rna_def_macro_operator(BlenderRNA *brna) @@ -1656,6 +1657,7 @@ static void rna_def_macro_operator(BlenderRNA *brna) "rna_Operator_instance"); #endif RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); + RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index b8ff0588581..6598d402f72 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -200,12 +200,12 @@ static int bpy_slot_from_py( { /* XXX - BMesh operator design is crappy here, operator slot should define matrix size, * not the caller! */ - unsigned short size; MatrixObject *pymat; if (!Matrix_ParseAny(value, &pymat)) { return -1; } - if ((size = (pymat->num_col) != pymat->num_row) || (!ELEM(size, 3, 4))) { + const ushort size = pymat->num_col; + if ((size != pymat->num_row) || (!ELEM(size, 3, 4))) { PyErr_Format(PyExc_TypeError, "%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix Matrix", opname, slot_name); diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 3afde45195c..9d57adca946 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -53,7 +53,7 @@ static void operator_properties_init(wmOperatorType *ot) * * Note the 'no_struct_map' function is used since the actual struct name is already used by the operator. */ - RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); + RNA_def_struct_identifier_no_struct_map(ot->srna, ot->idname); if (pyrna_deferred_register_class(ot->srna, py_class) != 0) { PyErr_Print(); /* failed to register operator props */ |