diff options
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_compiler_compat.h | 34 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_fileops.h | 1 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_gsqueue.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_geom.h | 6 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_temporary_allocator.cc | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_timer.c | 1 | ||||
-rw-r--r-- | source/blender/blenlib/intern/delaunay_2d.c | 126 | ||||
-rw-r--r-- | source/blender/blenlib/intern/expr_pylike_eval.c | 8 | ||||
-rw-r--r-- | source/blender/blenlib/intern/fileops.c | 193 | ||||
-rw-r--r-- | source/blender/blenlib/intern/scanfill.c | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/storage.c | 1 |
11 files changed, 329 insertions, 47 deletions
diff --git a/source/blender/blenlib/BLI_compiler_compat.h b/source/blender/blenlib/BLI_compiler_compat.h index bd1cd327d3c..312991e7f15 100644 --- a/source/blender/blenlib/BLI_compiler_compat.h +++ b/source/blender/blenlib/BLI_compiler_compat.h @@ -15,7 +15,7 @@ */ #ifndef __BLI_COMPILER_COMPAT_H__ -# define __BLI_COMPILER_COMPAT_H__ +#define __BLI_COMPILER_COMPAT_H__ /** \file * \ingroup bli @@ -23,32 +23,32 @@ * Use to help with cross platform portability. */ -# if defined(_MSC_VER) -# define alloca _alloca -# endif +#if defined(_MSC_VER) +# define alloca _alloca +#endif -# if (defined(__GNUC__) || defined(__clang__)) && defined(__cplusplus) +#if (defined(__GNUC__) || defined(__clang__)) && defined(__cplusplus) extern "C++" { /* Some magic to be sure we don't have reference in the type. */ template<typename T> static inline T decltype_helper(T x) { return x; } -# define typeof(x) decltype(decltype_helper(x)) +# define typeof(x) decltype(decltype_helper(x)) } -# endif +#endif /* little macro so inline keyword works */ -# if defined(_MSC_VER) -# define BLI_INLINE static __forceinline -# else -# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__)) -# endif +#if defined(_MSC_VER) +# define BLI_INLINE static __forceinline +#else +# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__)) +#endif -# if defined(__GNUC__) -# define BLI_NOINLINE __attribute__((noinline)) -# else -# define BLI_NOINLINE -# endif +#if defined(__GNUC__) +# define BLI_NOINLINE __attribute__((noinline)) +#else +# define BLI_NOINLINE +#endif #endif /* __BLI_COMPILER_COMPAT_H__ */ diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index d78f167a8fd..bdf7588291f 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -50,6 +50,7 @@ int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BLI_copy(const char *path, const char *to) ATTR_NONNULL(); int BLI_rename(const char *from, const char *to) ATTR_NONNULL(); int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL(); +int BLI_delete_soft(const char *path, const char **error_message) ATTR_NONNULL(); #if 0 /* Unused */ int BLI_move(const char *path, const char *to) ATTR_NONNULL(); int BLI_create_symlink(const char *path, const char *to) ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h index 4bd53dfddbe..b8a87e9d9fa 100644 --- a/source/blender/blenlib/BLI_gsqueue.h +++ b/source/blender/blenlib/BLI_gsqueue.h @@ -26,7 +26,7 @@ typedef struct _GSQueue GSQueue; -GSQueue *BLI_gsqueue_new(size_t elem_size); +GSQueue *BLI_gsqueue_new(const size_t elem_size); bool BLI_gsqueue_is_empty(const GSQueue *gq); size_t BLI_gsqueue_len(const GSQueue *gq); void BLI_gsqueue_pop(GSQueue *gq, void *r_item); diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 87517ebe060..eec5d214473 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -97,10 +97,10 @@ bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]); bool is_poly_convex_v2(const float verts[][2], unsigned int nr); int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]); -bool is_quad_flip_v3_first_third_fast(const float v0[3], - const float v1[3], +bool is_quad_flip_v3_first_third_fast(const float v1[3], const float v2[3], - const float v3[3]); + const float v3[3], + const float v4[3]); /********************************* Distance **********************************/ diff --git a/source/blender/blenlib/intern/BLI_temporary_allocator.cc b/source/blender/blenlib/intern/BLI_temporary_allocator.cc index e41cf36f66d..b145e65530d 100644 --- a/source/blender/blenlib/intern/BLI_temporary_allocator.cc +++ b/source/blender/blenlib/intern/BLI_temporary_allocator.cc @@ -73,7 +73,7 @@ struct ThreadLocalBuffers { } }; -thread_local ThreadLocalBuffers local_storage; +static thread_local ThreadLocalBuffers local_storage; void *BLI_temporary_allocate(uint size) { diff --git a/source/blender/blenlib/intern/BLI_timer.c b/source/blender/blenlib/intern/BLI_timer.c index 0443dea9a2e..af987587d90 100644 --- a/source/blender/blenlib/intern/BLI_timer.c +++ b/source/blender/blenlib/intern/BLI_timer.c @@ -42,7 +42,6 @@ typedef struct TimedFunction { typedef struct TimerContainer { ListBase funcs; - bool file_load_cb_registered; } TimerContainer; static TimerContainer GlobalTimer = {{0}}; diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c index d5dcd40346f..af4fa9fa54e 100644 --- a/source/blender/blenlib/intern/delaunay_2d.c +++ b/source/blender/blenlib/intern/delaunay_2d.c @@ -325,6 +325,18 @@ static bool exists_edge(const CDTVert *a, const CDTVert *b) return false; } +/** Is the vertex v incident on face f? */ +static bool vert_touches_face(const CDTVert *v, const CDTFace *f) +{ + SymEdge *se = v->symedge; + do { + if (se->face == f) { + return true; + } + } while ((se = se->rot) != v->symedge); + return false; +} + /** * Assume s1 and s2 are both SymEdges in a face with > 3 sides, * and one is not the next of the other. @@ -1901,35 +1913,108 @@ static void dissolve_symedge(CDT_state *cdt, SymEdge *se) delete_edge(cdt, se); } -static void remove_non_constraint_edges(CDT_state *cdt, const bool valid_bmesh) +/* Remove all non-constraint edges. */ +static void remove_non_constraint_edges(CDT_state *cdt) +{ + LinkNode *ln; + CDTEdge *e; + SymEdge *se; + + for (ln = cdt->edges; ln; ln = ln->next) { + e = (CDTEdge *)ln->link; + se = &e->symedges[0]; + if (!is_deleted_edge(e) && !is_constrained_edge(e)) { + dissolve_symedge(cdt, se); + } + } +} + +/* + * Remove the non-constraint edges, but leave enough of them so that all of the + * faces that would be bmesh faces (that is, the faces that have some input representative) + * are valid: they can't have holes, they can't have repeated vertices, and they can't have + * repeated edges. + * + * Not essential, but to make the result look more aesthetically nice, + * remove the edges in order of decreasing length, so that it is more likely that the + * final remaining support edges are short, and therefore likely to make a fairly + * direct path from an outer face to an inner hole face. + */ + +/* For sorting edges by decreasing length (squared). */ +struct EdgeToSort { + double len_squared; + CDTEdge *e; +}; + +static int edge_to_sort_cmp(const void *a, const void *b) +{ + const struct EdgeToSort *e1 = a; + const struct EdgeToSort *e2 = b; + + if (e1->len_squared > e2->len_squared) { + return -1; + } + else if (e1->len_squared < e2->len_squared) { + return 1; + } + return 0; +} + +static void remove_non_constraint_edges_leave_valid_bmesh(CDT_state *cdt) { LinkNode *ln; CDTEdge *e; SymEdge *se, *se2; CDTFace *fleft, *fright; bool dissolve; + size_t nedges; + int i, ndissolvable; + const double *co1, *co2; + struct EdgeToSort *sorted_edges; + nedges = 0; + for (ln = cdt->edges; ln; ln = ln->next) { + nedges++; + } + if (nedges == 0) { + return; + } + sorted_edges = BLI_memarena_alloc(cdt->arena, nedges * sizeof(*sorted_edges)); + i = 0; for (ln = cdt->edges; ln; ln = ln->next) { e = (CDTEdge *)ln->link; - dissolve = !is_deleted_edge(e) && !is_constrained_edge(e); - if (dissolve) { - se = &e->symedges[0]; - if (valid_bmesh && !edge_touches_frame(e)) { - fleft = se->face; - fright = sym(se)->face; - if (fleft != cdt->outer_face && fright != cdt->outer_face && - (fleft->input_ids != NULL || fright->input_ids != NULL)) { - /* Is there another symedge with same left and right faces? */ - for (se2 = se->next; dissolve && se2 != se; se2 = se2->next) { - if (sym(se2)->face == fright) { - dissolve = false; - } + if (!is_deleted_edge(e) && !is_constrained_edge(e)) { + sorted_edges[i].e = e; + co1 = e->symedges[0].vert->co; + co2 = e->symedges[1].vert->co; + sorted_edges[i].len_squared = len_squared_v2v2_db(co1, co2); + i++; + } + } + ndissolvable = i; + qsort(sorted_edges, ndissolvable, sizeof(*sorted_edges), edge_to_sort_cmp); + for (i = 0; i < ndissolvable; i++) { + e = sorted_edges[i].e; + se = &e->symedges[0]; + dissolve = true; + if (!edge_touches_frame(e)) { + fleft = se->face; + fright = sym(se)->face; + if (fleft != cdt->outer_face && fright != cdt->outer_face && + (fleft->input_ids != NULL || fright->input_ids != NULL)) { + /* Is there another symedge with same left and right faces? + * Or is there a vertex not part of e touching the same left and right faces? */ + for (se2 = se->next; dissolve && se2 != se; se2 = se2->next) { + if (sym(se2)->face == fright || + (se2->vert != se->next->vert && vert_touches_face(se2->vert, fright))) { + dissolve = false; } } } - if (dissolve) { - dissolve_symedge(cdt, se); - } + } + if (dissolve) { + dissolve_symedge(cdt, se); } } } @@ -2066,8 +2151,11 @@ static void prepare_cdt_for_output(CDT_state *cdt, const CDT_output_type output_ UNUSED_VARS(f); #endif - if (output_type == CDT_CONSTRAINTS || output_type == CDT_CONSTRAINTS_VALID_BMESH) { - remove_non_constraint_edges(cdt, output_type == CDT_CONSTRAINTS_VALID_BMESH); + if (output_type == CDT_CONSTRAINTS) { + remove_non_constraint_edges(cdt); + } + else if (output_type == CDT_CONSTRAINTS_VALID_BMESH) { + remove_non_constraint_edges_leave_valid_bmesh(cdt); } else if (output_type == CDT_FULL || output_type == CDT_INSIDE) { remove_outer_edges(cdt, output_type == CDT_INSIDE); diff --git a/source/blender/blenlib/intern/expr_pylike_eval.c b/source/blender/blenlib/intern/expr_pylike_eval.c index 14fc4c5bf26..c7631f8991e 100644 --- a/source/blender/blenlib/intern/expr_pylike_eval.c +++ b/source/blender/blenlib/intern/expr_pylike_eval.c @@ -504,7 +504,9 @@ static bool parse_add_func(ExprParseState *state, eOpCode code, int args, void * if (jmp_gap >= 1 && prev_ops[-1].opcode == OPCODE_CONST) { UnaryOpFunc func = funcptr; - double result = func(prev_ops[-1].arg.dval); + /* volatile because some compilers overly aggressive optimize this call out. + * see D6012 for details. */ + volatile double result = func(prev_ops[-1].arg.dval); if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) { prev_ops[-1].arg.dval = result; @@ -520,7 +522,9 @@ static bool parse_add_func(ExprParseState *state, eOpCode code, int args, void * prev_ops[-1].opcode == OPCODE_CONST) { BinaryOpFunc func = funcptr; - double result = func(prev_ops[-2].arg.dval, prev_ops[-1].arg.dval); + /* volatile because some compilers overly aggressive optimize this call out. + * see D6012 for details. */ + volatile double result = func(prev_ops[-2].arg.dval, prev_ops[-1].arg.dval); if (fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0) { prev_ops[-2].arg.dval = result; diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 99149f5ea42..3a45989fb63 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -33,16 +33,24 @@ #include "zlib.h" #ifdef WIN32 +# include <windows.h> +# include <shellapi.h> +# include <shobjidl.h> # include <io.h> # include "BLI_winstuff.h" # include "BLI_fileops_types.h" # include "utf_winfunc.h" # include "utfconv.h" #else +# if defined(__APPLE__) +# include <CoreFoundation/CoreFoundation.h> +# include <objc/runtime.h> +# include <objc/message.h> +# endif # include <sys/param.h> # include <dirent.h> # include <unistd.h> -# include <sys/stat.h> +# include <sys/wait.h> #endif #include "MEM_guardedalloc.h" @@ -288,6 +296,64 @@ int BLI_access(const char *filename, int mode) return uaccess(filename, mode); } +static bool delete_soft(const wchar_t *path_16, const char **error_message) +{ + /* Deletes file or directory to recycling bin. The latter moves all contained files and + * directories recursively to the recycling bin as well. */ + IFileOperation *pfo; + IShellItem *pSI; + + HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + + if (FAILED(hr)) { + *error_message = "Failed to initialize COM"; + goto error_1; + } + + hr = CoCreateInstance( + &CLSID_FileOperation, NULL, CLSCTX_ALL, &IID_IFileOperation, (void **)&pfo); + if (FAILED(hr)) { + *error_message = "Failed to create FileOperation instance"; + goto error_2; + } + + /* Flags for deletion: + * FOF_ALLOWUNDO: Enables moving file to recycling bin. + * FOF_SILENT: Don't show progress dialog box. + * FOF_WANTNUKEWARNING: Show dialog box if file can't be moved to recycling bin. */ + hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_ALLOWUNDO | FOF_SILENT | FOF_WANTNUKEWARNING); + + if (FAILED(hr)) { + *error_message = "Failed to set operation flags"; + goto error_2; + } + + hr = SHCreateItemFromParsingName(path_16, NULL, &IID_IShellItem, (void **)&pSI); + if (FAILED(hr)) { + *error_message = "Failed to parse path"; + goto error_2; + } + + hr = pfo->lpVtbl->DeleteItem(pfo, pSI, NULL); + if (FAILED(hr)) { + *error_message = "Failed to prepare delete operation"; + goto error_2; + } + + hr = pfo->lpVtbl->PerformOperations(pfo); + + if (FAILED(hr)) { + *error_message = "Failed to delete file or directory"; + } + +error_2: + pfo->lpVtbl->Release(pfo); + CoUninitialize(); /* Has to be uninitialized when CoInitializeEx returns either S_OK or S_FALSE + */ +error_1: + return FAILED(hr); +} + static bool delete_unique(const char *path, const bool dir) { bool err; @@ -370,6 +436,24 @@ int BLI_delete(const char *file, bool dir, bool recursive) return err; } +/** + * Moves the files or directories to the recycling bin. + */ +int BLI_delete_soft(const char *file, const char **error_message) +{ + int err; + + BLI_assert(!BLI_path_is_rel(file)); + + UTF16_ENCODE(file); + + err = delete_soft(file_16, error_message); + + UTF16_UN_ENCODE(file); + + return err; +} + /* Not used anywhere! */ # if 0 int BLI_move(const char *file, const char *to) @@ -720,6 +804,100 @@ static int delete_single_file(const char *from, const char *UNUSED(to)) return RecursiveOp_Callback_OK; } +# ifdef __APPLE__ +static int delete_soft(const char *file, const char **error_message) +{ + int ret = -1; + + Class NSAutoreleasePoolClass = objc_getClass("NSAutoreleasePool"); + SEL allocSel = sel_registerName("alloc"); + SEL initSel = sel_registerName("init"); + id poolAlloc = ((id(*)(Class, SEL))objc_msgSend)(NSAutoreleasePoolClass, allocSel); + id pool = ((id(*)(id, SEL))objc_msgSend)(poolAlloc, initSel); + + Class NSStringClass = objc_getClass("NSString"); + SEL stringWithUTF8StringSel = sel_registerName("stringWithUTF8String:"); + id pathString = ((id(*)(Class, SEL, const char *))objc_msgSend)( + NSStringClass, stringWithUTF8StringSel, file); + + Class NSFileManagerClass = objc_getClass("NSFileManager"); + SEL defaultManagerSel = sel_registerName("defaultManager"); + id fileManager = ((id(*)(Class, SEL))objc_msgSend)(NSFileManagerClass, defaultManagerSel); + + Class NSURLClass = objc_getClass("NSURL"); + SEL fileURLWithPathSel = sel_registerName("fileURLWithPath:"); + id nsurl = ((id(*)(Class, SEL, id))objc_msgSend)(NSURLClass, fileURLWithPathSel, pathString); + + SEL trashItemAtURLSel = sel_registerName("trashItemAtURL:resultingItemURL:error:"); + BOOL deleteSuccessful = ((BOOL(*)(id, SEL, id, id, id))objc_msgSend)( + fileManager, trashItemAtURLSel, nsurl, nil, nil); + + if (deleteSuccessful) { + ret = 0; + } + else { + *error_message = "The Cocoa API call to delete file or directory failed"; + } + + SEL drainSel = sel_registerName("drain"); + ((void (*)(id, SEL))objc_msgSend)(pool, drainSel); + + return ret; +} +# else +static int delete_soft(const char *file, const char **error_message) +{ + const char *args[5]; + const char *process_failed; + + char *xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP"); + char *xdg_session_desktop = getenv("XDG_SESSION_DESKTOP"); + + if ((xdg_current_desktop != NULL && strcmp(xdg_current_desktop, "KDE") == 0) || + (xdg_session_desktop != NULL && strcmp(xdg_session_desktop, "KDE") == 0)) { + args[0] = "kioclient5"; + args[1] = "move"; + args[2] = file; + args[3] = "trash:/"; + args[4] = NULL; + process_failed = "kioclient5 reported failure"; + } + else { + args[0] = "gio"; + args[1] = "trash"; + args[2] = file; + args[3] = NULL; + process_failed = "gio reported failure"; + } + + int pid = fork(); + + if (pid != 0) { + /* Parent process */ + int wstatus = 0; + + waitpid(pid, &wstatus, 0); + + if (!WIFEXITED(wstatus)) { + *error_message = + "Blender may not support moving files or directories to trash on your system."; + return -1; + } + else if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus)) { + *error_message = process_failed; + return -1; + } + + return 0; + } + + execvp(args[0], (char **)args); + + *error_message = "Forking process failed."; + return -1; /* This should only be reached if execvp fails and stack isn't replaced. */ +} +# endif + FILE *BLI_fopen(const char *filename, const char *mode) { BLI_assert(!BLI_path_is_rel(filename)); @@ -770,6 +948,19 @@ int BLI_delete(const char *file, bool dir, bool recursive) } /** + * Soft deletes the specified file or directory (depending on dir) by moving the files to the + * recycling bin, optionally doing recursive delete of directory contents. + * + * \return zero on success (matching 'remove' behavior). + */ +int BLI_delete_soft(const char *file, const char **error_message) +{ + BLI_assert(!BLI_path_is_rel(file)); + + return delete_soft(file, error_message); +} + +/** * Do the two paths denote the same file-system object? */ static bool check_the_same(const char *path_a, const char *path_b) diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 08c3653153e..c9b0eb3ed5e 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -907,7 +907,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const return 0; } - axis_dominant_v3_to_m3(mat_2d, n); + axis_dominant_v3_to_m3_negate(mat_2d, n); } /* STEP 1: COUNT POLYS */ diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 05a2d766fe0..fd5de717a24 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -209,7 +209,6 @@ int BLI_exists(const char *name) BLI_stat_t st; wchar_t *tmp_16 = alloc_utf16_from_8(name, 1); int len, res; - unsigned int old_error_mode; len = wcslen(tmp_16); /* in Windows #stat doesn't recognize dir ending on a slash |