diff options
author | Thomas Dinges <blender@dingto.org> | 2013-06-20 00:40:54 +0400 |
---|---|---|
committer | Thomas Dinges <blender@dingto.org> | 2013-06-20 00:40:54 +0400 |
commit | e6fc17415223d97a5a8c8bca0af443fb3a655699 (patch) | |
tree | 8696c810b22464262db029f55e937782cd64cc7b /source | |
parent | ac4058a2117a24901f2462ba34d49e6714532148 (diff) | |
parent | 93af050824170913d716e42e918ab58c224ed7f1 (diff) |
Merged revision(s) 57499-57586 from trunk/blender into soc-2013-dingto
Diffstat (limited to 'source')
61 files changed, 1376 insertions, 905 deletions
diff --git a/source/blender/blenkernel/BKE_autoexec.h b/source/blender/blenkernel/BKE_autoexec.h new file mode 100644 index 00000000000..7dc1e76ed5c --- /dev/null +++ b/source/blender/blenkernel/BKE_autoexec.h @@ -0,0 +1,31 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation 2013 + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BKE_AUTOEXEC_H__ +#define __BKE_AUTOEXEC_H__ + +/** \file BKE_autoexec.h + * \ingroup bke + */ + +bool BKE_autoexec_match(const char *path); + +#endif /* __BKE_AUTOEXEC_H__ */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 6b9392a4169..3f3a5739d55 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -391,5 +391,30 @@ void modifier_mdef_compact_influences(struct ModifierData *md); void modifier_path_init(char *path, int path_maxlen, const char *name); const char *modifier_path_relbase(struct Object *ob); + +/* wrappers for modifier callbacks */ + +struct DerivedMesh *modwrap_applyModifier( + ModifierData *md, struct Object *ob, + struct DerivedMesh *dm, + ModifierApplyFlag flag); + +struct DerivedMesh *modwrap_applyModifierEM( + ModifierData *md, struct Object *ob, + struct BMEditMesh *em, + struct DerivedMesh *dm, + ModifierApplyFlag flag); + +void modwrap_deformVerts( + ModifierData *md, struct Object *ob, + struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts, + ModifierApplyFlag flag); + +void modwrap_deformVertsEM( + ModifierData *md, struct Object *ob, + struct BMEditMesh *em, struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts); + #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 3864fe3b350..7e1355b5421 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -63,6 +63,7 @@ set(SRC intern/anim.c intern/anim_sys.c intern/armature.c + intern/autoexec.c intern/blender.c intern/bmfont.c intern/boids.c @@ -163,6 +164,7 @@ set(SRC BKE_anim.h BKE_animsys.h BKE_armature.h + BKE_autoexec.h BKE_blender.h BKE_bmesh.h BKE_bmfont.h diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 6a21f33ac15..96ccc5be8e0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -845,69 +845,6 @@ DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3]) return dm; } -/***/ - -/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */ - -static DerivedMesh *modwrap_applyModifier( - ModifierData *md, Object *ob, - DerivedMesh *dm, - ModifierApplyFlag flag) -{ - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); - - if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { - DM_ensure_normals(dm); - } - return mti->applyModifier(md, ob, dm, flag); -} - -static DerivedMesh *modwrap_applyModifierEM( - ModifierData *md, Object *ob, - BMEditMesh *em, - DerivedMesh *dm, - ModifierApplyFlag flag) -{ - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); - - if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { - DM_ensure_normals(dm); - } - return mti->applyModifierEM(md, ob, em, dm, flag); -} - -static void modwrap_deformVerts( - ModifierData *md, Object *ob, - DerivedMesh *dm, - float (*vertexCos)[3], int numVerts, - ModifierApplyFlag flag) -{ - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); - - if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { - DM_ensure_normals(dm); - } - mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag); -} - -static void modwrap_deformVertsEM( - ModifierData *md, Object *ob, - BMEditMesh *em, DerivedMesh *dm, - float (*vertexCos)[3], int numVerts) -{ - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); - - if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { - DM_ensure_normals(dm); - } - mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts); -} -/* end modifier callback wrappers */ - DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md, int build_shapekey_layers) { @@ -2148,7 +2085,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D if (mti->applyModifierEM) ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE); else - ndm = mti->applyModifier(md, ob, dm, MOD_APPLY_USECACHE); + ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE); if (ndm) { if (dm && dm != ndm) diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c new file mode 100644 index 00000000000..c27343bf80a --- /dev/null +++ b/source/blender/blenkernel/intern/autoexec.c @@ -0,0 +1,70 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation 2013 + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/armature.c + * \ingroup bke + * + * Currently just checks if a blend file can be trusted to autoexec, + * may add signing here later. + */ + +#include <stdlib.h> +#include <string.h> + +#include "DNA_userdef_types.h" + +#include "BLI_utildefines.h" +#include "BLI_fnmatch.h" +#include "BLI_string.h" +#include "BLI_path_util.h" + +#include "BKE_autoexec.h" /* own include */ + +/** + * \param path The path to check against. + * \return Success + */ +bool BKE_autoexec_match(const char *path) +{ + bPathCompare *path_cmp; + +#ifdef WIN32 + const int fnmatch_flags = FNM_CASEFOLD; +#else + const int fnmatch_flags = 0; +#endif + + BLI_assert((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0); + + for (path_cmp = U.autoexec_paths.first; path_cmp; path_cmp = path_cmp->next) { + if ((path_cmp->flag & USER_PATHCMP_GLOB)) { + if (fnmatch(path_cmp->path, path, fnmatch_flags) == 0) { + return true; + } + } + else if (BLI_path_ncmp(path_cmp->path, path, strlen(path_cmp->path)) == 0) { + return true; + } + } + + return false; +} diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 87a8def52bf..1e7aba6d25b 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -416,6 +416,8 @@ void BKE_userdef_free(void) MEM_freeN(addon); } + BLI_freelistN(&U.autoexec_paths); + BLI_freelistN(&U.uistyles); BLI_freelistN(&U.uifonts); BLI_freelistN(&U.themes); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index f3de4001dea..e1ecf00104a 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -976,7 +976,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba dm = tdm; CDDM_apply_vert_coords(dm, vertCos); - CDDM_calc_normals_mapping(dm); } } else { @@ -989,8 +988,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba } dm = CDDM_from_curve_displist(ob, dispbase); - - CDDM_calc_normals_mapping(dm); } if (vertCos) { @@ -1001,7 +998,8 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba if (useCache) appf |= MOD_APPLY_USECACHE; - ndm = mti->applyModifier(md, ob, dm, appf); + + ndm = modwrap_applyModifier(md, ob, dm, appf); if (ndm) { /* Modifier returned a new derived mesh */ @@ -1031,8 +1029,19 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba } if (derivedFinal) { - if (dm) - DM_ensure_tessface(dm); /* needed for drawing */ + if (dm) { + /* see: mesh_calc_modifiers */ + if (dm->getNumTessFaces(dm) == 0) { + dm->recalcTessellation(dm); + } + /* Even if tessellation is not needed, some modifiers might have modified CD layers + * (like mloopcol or mloopuv), hence we have to update those. */ + else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) { + DM_update_tessface_data(dm); + } + + CDDM_calc_normals_mapping_ex(dm, (dm->dirty & DM_DIRTY_NORMALS) ? false : true); + } (*derivedFinal) = dm; } @@ -1169,7 +1178,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina if (!orcodm) orcodm = create_orco_dm(scene, ob); - ndm = mti->applyModifier(md, ob, orcodm, app_flag); + ndm = modwrap_applyModifier(md, ob, orcodm, app_flag); if (ndm) { /* if the modifier returned a new dm, release the old one */ diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c index 979a38f0346..160972889fd 100644 --- a/source/blender/blenkernel/intern/editmesh_bvh.c +++ b/source/blender/blenkernel/intern/editmesh_bvh.c @@ -382,7 +382,7 @@ static void bmbvh_find_vert_closest_cb(void *userdata, int index, const float *U bmbvh_tri_from_face(tri_cos, ltri, bmcb_data->cos_cage); for (i = 0; i < 3; i++) { - dist = len_v3v3(hit->co, tri_cos[i]); + dist = len_squared_v3v3(hit->co, tri_cos[i]); if (dist < hit->dist && dist < maxdist) { copy_v3_v3(hit->co, tri_cos[i]); /* XXX, normal ignores cage */ @@ -398,17 +398,17 @@ BMVert *BKE_bmbvh_find_vert_closest(BMBVHTree *bmtree, const float co[3], const { BVHTreeNearest hit; struct VertSearchUserData bmcb_data; + const float maxdist_sq = maxdist * maxdist; if (bmtree->cos_cage) BLI_assert(!(bmtree->em->bm->elem_index_dirty & BM_VERT)); copy_v3_v3(hit.co, co); - /* XXX, why x5, scampbell */ - hit.dist = maxdist * 5; + hit.dist = maxdist_sq; hit.index = -1; bmcb_data.looptris = (const BMLoop *(*)[3])bmtree->em->looptris; bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage; - bmcb_data.maxdist = maxdist; + bmcb_data.maxdist = maxdist_sq; BLI_bvhtree_find_nearest(bmtree->tree, co, &hit, bmbvh_find_vert_closest_cb, &bmcb_data); if (hit.dist != FLT_MAX && hit.index != -1) { diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 43819e1e80e..0546c85db67 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -112,19 +112,6 @@ typedef struct intlists { /* list of list of integers */ struct intlists *next; /* remaining elements */ } INTLISTS; -typedef struct process { /* parameters, function, storage */ - /* what happens here? floats, I think. */ - /* float (*function)(void); */ /* implicit surface function */ - float (*function)(float, float, float); - float size, delta; /* cube size, normal delta */ - int bounds; /* cube range within lattice */ - CUBES *cubes; /* active cubes */ - VERTICES vertices; /* surface vertices */ - CENTERLIST **centers; /* cube center hash table */ - CORNER **corners; /* corner value hash table */ - EDGELIST **edges; /* edge and vertex id hash table */ -} PROCESS; - /* dividing scene using octal tree makes polygonisation faster */ typedef struct ml_pointer { struct ml_pointer *next, *prev; @@ -153,20 +140,41 @@ struct pgn_elements { char *data; }; -/* Forward declarations */ -static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb); -static int setcenter(CENTERLIST *table[], const int i, const int j, const int k); -static CORNER *setcorner(PROCESS *p, int i, int j, int k); -static void converge(const float p1[3], const float p2[3], float v1, float v2, - float (*function)(float, float, float), float p[3], MetaBall *mb, int f); - -/* Global variables */ -static struct { +typedef struct process { /* parameters, function, storage */ + /* ** old G_mb contents ** */ float thresh; int totelem; MetaElem **mainb; octal_tree *metaball_tree; -} G_mb = {0}; + + /* ** old process contents ** */ + + /* what happens here? floats, I think. */ + /* float (*function)(void); */ /* implicit surface function */ + float (*function)(struct process*, float, float, float); + float size, delta; /* cube size, normal delta */ + int bounds; /* cube range within lattice */ + CUBES *cubes; /* active cubes */ + VERTICES vertices; /* surface vertices */ + CENTERLIST **centers; /* cube center hash table */ + CORNER **corners; /* corner value hash table */ + EDGELIST **edges; /* edge and vertex id hash table */ + + /* Runtime things */ + int *indices; + int totindex, curindex; + + int pgn_offset; + struct pgn_elements *pgn_current; + ListBase pgn_list; +} PROCESS; + +/* Forward declarations */ +static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb); +static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k); +static CORNER *setcorner(PROCESS *process, int i, int j, int k); +static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, + float p[3], MetaBall *mb, int f); /* Functions */ @@ -519,43 +527,23 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) Scene *sce_iter = scene; Base *base; Object *ob, *bob = basis; - MetaElem *ml = NULL; int basisnr, obnr; char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - G_mb.totelem = 0; /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ if (F_ERROR == BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL)) return NULL; - + while (BKE_scene_base_iter_next(&sce_iter, 1, &base, &ob)) { - if (ob->type == OB_MBALL) { - if (ob == bob) { - MetaBall *mb = ob->data; - - /* if bob object is in edit mode, then dynamic list of all MetaElems - * is stored in editelems */ - if (mb->editelems) ml = mb->editelems->first; - /* if bob object is in object mode */ - else ml = mb->elems.first; - } - else { + if (ob != bob) { BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); /* object ob has to be in same "group" ... it means, that it has to have * same base of its name */ if (strcmp(obname, basisname) == 0) { - MetaBall *mb = ob->data; - - /* if object is in edit mode, then dynamic list of all MetaElems - * is stored in editelems */ - if (mb->editelems) ml = mb->editelems->first; - /* if bob object is in object mode */ - else ml = mb->elems.first; - if (obnr < basisnr) { if (!(ob->flag & OB_FROMDUPLI)) { basis = ob; @@ -564,12 +552,6 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) } } } - - for ( ; ml; ml = ml->next) { - if (!(ml->flag & MB_HIDE)) { - G_mb.totelem++; - } - } } } @@ -768,60 +750,57 @@ static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, return node; } -static float metaball(float x, float y, float z) +static float metaball(PROCESS *process, float x, float y, float z) /* float x, y, z; */ { + octal_tree *metaball_tree = process->metaball_tree; struct octal_node *node; struct ml_pointer *ml_p; float dens = 0; int a; - if (G_mb.totelem > 1) { - node = find_metaball_octal_node(G_mb.metaball_tree->first, x, y, z, G_mb.metaball_tree->depth); + if (process->totelem > 1) { + node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth); if (node) { for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) { dens += densfunc(ml_p->ml, x, y, z); } - dens += -0.5f * (G_mb.metaball_tree->pos - node->pos); - dens += 0.5f * (G_mb.metaball_tree->neg - node->neg); + dens += -0.5f * (metaball_tree->pos - node->pos); + dens += 0.5f * (metaball_tree->neg - node->neg); } else { - for (a = 0; a < G_mb.totelem; a++) { - dens += densfunc(G_mb.mainb[a], x, y, z); + for (a = 0; a < process->totelem; a++) { + dens += densfunc(process->mainb[a], x, y, z); } } } else { - dens += densfunc(G_mb.mainb[0], x, y, z); + dens += densfunc(process->mainb[0], x, y, z); } - return G_mb.thresh - dens; + return process->thresh - dens; } /* ******************************************** */ -static int *indices = NULL; -static int totindex, curindex; - - -static void accum_mballfaces(int i1, int i2, int i3, int i4) +static void accum_mballfaces(PROCESS *process, int i1, int i2, int i3, int i4) { int *newi, *cur; /* static int i = 0; I would like to delete altogether, but I don't dare to, yet */ - if (totindex == curindex) { - totindex += 256; - newi = MEM_mallocN(4 * sizeof(int) * totindex, "vertindex"); + if (process->totindex == process->curindex) { + process->totindex += 256; + newi = MEM_mallocN(4 * sizeof(int) * process->totindex, "vertindex"); - if (indices) { - memcpy(newi, indices, 4 * sizeof(int) * (totindex - 256)); - MEM_freeN(indices); + if (process->indices) { + memcpy(newi, process->indices, 4 * sizeof(int) * (process->totindex - 256)); + MEM_freeN(process->indices); } - indices = newi; + process->indices = newi; } - cur = indices + 4 * curindex; + cur = process->indices + 4 * process->curindex; /* displists now support array drawing, we treat tri's as fake quad */ @@ -833,63 +812,62 @@ static void accum_mballfaces(int i1, int i2, int i3, int i4) else cur[3] = i4; - curindex++; + process->curindex++; } /* ******************* MEMORY MANAGEMENT *********************** */ -static void *new_pgn_element(int size) +static void *new_pgn_element(PROCESS *process, int size) { /* during polygonize 1000s of elements are allocated * and never freed in between. Freeing only done at the end. */ int blocksize = 16384; - static int offs = 0; /* the current free address */ - static struct pgn_elements *cur = NULL; - static ListBase lb = {NULL, NULL}; void *adr; if (size > 10000 || size == 0) { printf("incorrect use of new_pgn_element\n"); } else if (size == -1) { - cur = lb.first; + struct pgn_elements *cur = process->pgn_list.first; while (cur) { MEM_freeN(cur->data); cur = cur->next; } - BLI_freelistN(&lb); + BLI_freelistN(&process->pgn_list); return NULL; } size = 4 * ( (size + 3) / 4); - if (cur) { - if (size + offs < blocksize) { - adr = (void *) (cur->data + offs); - offs += size; + if (process->pgn_current) { + if (size + process->pgn_offset < blocksize) { + adr = (void *) (process->pgn_current->data + process->pgn_offset); + process->pgn_offset += size; return adr; } } - cur = MEM_callocN(sizeof(struct pgn_elements), "newpgn"); - cur->data = MEM_callocN(blocksize, "newpgn"); - BLI_addtail(&lb, cur); + process->pgn_current = MEM_callocN(sizeof(struct pgn_elements), "newpgn"); + process->pgn_current->data = MEM_callocN(blocksize, "newpgn"); + BLI_addtail(&process->pgn_list, process->pgn_current); - offs = size; - return cur->data; + process->pgn_offset = size; + return process->pgn_current->data; } -static void freepolygonize(PROCESS *p) +static void freepolygonize(PROCESS *process) { - MEM_freeN(p->corners); - MEM_freeN(p->edges); - MEM_freeN(p->centers); + MEM_freeN(process->corners); + MEM_freeN(process->edges); + MEM_freeN(process->centers); - new_pgn_element(-1); - - if (p->vertices.ptr) MEM_freeN(p->vertices.ptr); + new_pgn_element(process, -1); + + if (process->vertices.ptr) { + MEM_freeN(process->vertices.ptr); + } } /**** Cubical Polygonization (optional) ****/ @@ -928,7 +906,7 @@ static int rightface[12] = { /* docube: triangulate the cube directly, without decomposition */ -static void docube(CUBE *cube, PROCESS *p, MetaBall *mb) +static void docube(PROCESS *process, CUBE *cube, MetaBall *mb) { INTLISTS *polys; CORNER *c1, *c2; @@ -945,45 +923,45 @@ static void docube(CUBE *cube, PROCESS *p, MetaBall *mb) c1 = cube->corners[corner1[edges->i]]; c2 = cube->corners[corner2[edges->i]]; - indexar[count] = vertid(c1, c2, p, mb); + indexar[count] = vertid(process, c1, c2, mb); count++; } if (count > 2) { switch (count) { case 3: - accum_mballfaces(indexar[2], indexar[1], indexar[0], 0); + accum_mballfaces(process, indexar[2], indexar[1], indexar[0], 0); break; case 4: - if (indexar[0] == 0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); - else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); + if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); break; case 5: - if (indexar[0] == 0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); - else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); + if (indexar[0] == 0) accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + else accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(indexar[4], indexar[3], indexar[0], 0); + accum_mballfaces(process, indexar[4], indexar[3], indexar[0], 0); break; case 6: if (indexar[0] == 0) { - accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); - accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]); + accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); } else { - accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]); + accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); } break; case 7: if (indexar[0] == 0) { - accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); - accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]); + accum_mballfaces(process, indexar[0], indexar[3], indexar[2], indexar[1]); + accum_mballfaces(process, indexar[0], indexar[5], indexar[4], indexar[3]); } else { - accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); - accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]); + accum_mballfaces(process, indexar[3], indexar[2], indexar[1], indexar[0]); + accum_mballfaces(process, indexar[5], indexar[4], indexar[3], indexar[0]); } - accum_mballfaces(indexar[6], indexar[5], indexar[0], 0); + accum_mballfaces(process, indexar[6], indexar[5], indexar[0], 0); break; } @@ -996,10 +974,10 @@ static void docube(CUBE *cube, PROCESS *p, MetaBall *mb) * if surface crosses face, compute other four corners of adjacent cube * and add new cube to cube stack */ -static void testface(int i, int j, int k, CUBE *old, int bit, int c1, int c2, int c3, int c4, PROCESS *p) +static void testface(PROCESS *process, int i, int j, int k, CUBE *old, int bit, int c1, int c2, int c3, int c4) { CUBE newc; - CUBES *oldcubes = p->cubes; + CUBES *oldcubes = process->cubes; CORNER *corn1, *corn2, *corn3, *corn4; int n, pos; @@ -1015,12 +993,13 @@ static void testface(int i, int j, int k, CUBE *old, int bit, int c1, int c2, in /* test if cube out of bounds */ /*if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;*/ /* test if already visited (always as last) */ - if (setcenter(p->centers, i, j, k)) return; - + if (setcenter(process, process->centers, i, j, k)) { + return; + } /* create new cube and add cube to top of stack: */ - p->cubes = (CUBES *) new_pgn_element(sizeof(CUBES)); - p->cubes->next = oldcubes; + process->cubes = (CUBES *) new_pgn_element(process, sizeof(CUBES)); + process->cubes->next = oldcubes; newc.i = i; newc.j = j; @@ -1032,22 +1011,22 @@ static void testface(int i, int j, int k, CUBE *old, int bit, int c1, int c2, in newc.corners[FLIP(c3, bit)] = corn3; newc.corners[FLIP(c4, bit)] = corn4; - if (newc.corners[0] == NULL) newc.corners[0] = setcorner(p, i, j, k); - if (newc.corners[1] == NULL) newc.corners[1] = setcorner(p, i, j, k + 1); - if (newc.corners[2] == NULL) newc.corners[2] = setcorner(p, i, j + 1, k); - if (newc.corners[3] == NULL) newc.corners[3] = setcorner(p, i, j + 1, k + 1); - if (newc.corners[4] == NULL) newc.corners[4] = setcorner(p, i + 1, j, k); - if (newc.corners[5] == NULL) newc.corners[5] = setcorner(p, i + 1, j, k + 1); - if (newc.corners[6] == NULL) newc.corners[6] = setcorner(p, i + 1, j + 1, k); - if (newc.corners[7] == NULL) newc.corners[7] = setcorner(p, i + 1, j + 1, k + 1); + if (newc.corners[0] == NULL) newc.corners[0] = setcorner(process, i, j, k); + if (newc.corners[1] == NULL) newc.corners[1] = setcorner(process, i, j, k + 1); + if (newc.corners[2] == NULL) newc.corners[2] = setcorner(process, i, j + 1, k); + if (newc.corners[3] == NULL) newc.corners[3] = setcorner(process, i, j + 1, k + 1); + if (newc.corners[4] == NULL) newc.corners[4] = setcorner(process, i + 1, j, k); + if (newc.corners[5] == NULL) newc.corners[5] = setcorner(process, i + 1, j, k + 1); + if (newc.corners[6] == NULL) newc.corners[6] = setcorner(process, i + 1, j + 1, k); + if (newc.corners[7] == NULL) newc.corners[7] = setcorner(process, i + 1, j + 1, k + 1); - p->cubes->cube = newc; + process->cubes->cube = newc; } /* setcorner: return corner with the given lattice location * set (and cache) its function value */ -static CORNER *setcorner(PROCESS *p, int i, int j, int k) +static CORNER *setcorner(PROCESS *process, int i, int j, int k) { /* for speed, do corner value caching here */ CORNER *c; @@ -1055,7 +1034,7 @@ static CORNER *setcorner(PROCESS *p, int i, int j, int k) /* does corner exist? */ index = HASH(i, j, k); - c = p->corners[index]; + c = process->corners[index]; for (; c != NULL; c = c->next) { if (c->i == i && c->j == j && c->k == k) { @@ -1063,18 +1042,18 @@ static CORNER *setcorner(PROCESS *p, int i, int j, int k) } } - c = (CORNER *) new_pgn_element(sizeof(CORNER)); + c = (CORNER *) new_pgn_element(process, sizeof(CORNER)); c->i = i; - c->co[0] = ((float)i - 0.5f) * p->size; + c->co[0] = ((float)i - 0.5f) * process->size; c->j = j; - c->co[1] = ((float)j - 0.5f) * p->size; + c->co[1] = ((float)j - 0.5f) * process->size; c->k = k; - c->co[2] = ((float)k - 0.5f) * p->size; - c->value = p->function(c->co[0], c->co[1], c->co[2]); + c->co[2] = ((float)k - 0.5f) * process->size; + c->value = process->function(process, c->co[0], c->co[1], c->co[2]); - c->next = p->corners[index]; - p->corners[index] = c; + c->next = process->corners[index]; + process->corners[index] = c; return c; } @@ -1196,7 +1175,7 @@ void BKE_mball_cubeTable_free(void) /* setcenter: set (i, j, k) entry of table[] * return 1 if already set; otherwise, set and return 0 */ -static int setcenter(CENTERLIST *table[], const int i, const int j, const int k) +static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k) { int index; CENTERLIST *newc, *l, *q; @@ -1208,7 +1187,7 @@ static int setcenter(CENTERLIST *table[], const int i, const int j, const int k) if (l->i == i && l->j == j && l->k == k) return 1; } - newc = (CENTERLIST *) new_pgn_element(sizeof(CENTERLIST)); + newc = (CENTERLIST *) new_pgn_element(process, sizeof(CENTERLIST)); newc->i = i; newc->j = j; newc->k = k; @@ -1221,7 +1200,8 @@ static int setcenter(CENTERLIST *table[], const int i, const int j, const int k) /* setedge: set vertex id for edge */ -static void setedge(EDGELIST *table[], +static void setedge(PROCESS *process, + EDGELIST *table[], int i1, int j1, int k1, int i2, int j2, int k2, @@ -1242,7 +1222,7 @@ static void setedge(EDGELIST *table[], k2 = t; } index = HASH(i1, j1, k1) + HASH(i2, j2, k2); - newe = (EDGELIST *) new_pgn_element(sizeof(EDGELIST)); + newe = (EDGELIST *) new_pgn_element(process, sizeof(EDGELIST)); newe->i1 = i1; newe->j1 = j1; newe->k1 = k1; @@ -1316,14 +1296,14 @@ static void addtovertices(VERTICES *vertices, VERTEX v) /* vnormal: compute unit length surface normal at point */ -static void vnormal(const float point[3], PROCESS *p, float r_no[3]) +static void vnormal(PROCESS *process, const float point[3], float r_no[3]) { - const float delta = 0.2f * p->delta; - const float f = p->function(point[0], point[1], point[2]); + const float delta = 0.2f * process->delta; + const float f = process->function(process, point[0], point[1], point[2]); - r_no[0] = p->function(point[0] + delta, point[1], point[2]) - f; - r_no[1] = p->function(point[0], point[1] + delta, point[2]) - f; - r_no[2] = p->function(point[0], point[1], point[2] + delta) - f; + r_no[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; + r_no[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; + r_no[2] = process->function(process, point[0], point[1], point[2] + delta) - f; #if 1 normalize_v3(r_no); @@ -1335,11 +1315,11 @@ static void vnormal(const float point[3], PROCESS *p, float r_no[3]) delta *= 2.0f; - f = p->function(point[0], point[1], point[2]); + f = process->function(process, point[0], point[1], point[2]); - tvec[0] = p->function(point[0] + delta, point[1], point[2]) - f; - tvec[1] = p->function(point[0], point[1] + delta, point[2]) - f; - tvec[2] = p->function(point[0], point[1], point[2] + delta) - f; + tvec[0] = process->function(process, point[0] + delta, point[1], point[2]) - f; + tvec[1] = process->function(process, point[0], point[1] + delta, point[2]) - f; + tvec[2] = process->function(process, point[0], point[1], point[2] + delta) - f; if (normalize_v3(tvec) != 0.0f) { add_v3_v3(r_no, tvec); @@ -1350,32 +1330,30 @@ static void vnormal(const float point[3], PROCESS *p, float r_no[3]) } -static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb) +static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2, MetaBall *mb) { VERTEX v; - int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); + int vid = getedge(process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); if (vid != -1) { return vid; /* previously computed */ } - converge(c1->co, c2->co, c1->value, c2->value, p->function, v.co, mb, 1); /* position */ - vnormal(v.co, p, v.no); + converge(process, c1->co, c2->co, c1->value, c2->value, v.co, mb, 1); /* position */ + vnormal(process, v.co, v.no); - addtovertices(&p->vertices, v); /* save vertex */ - vid = p->vertices.count - 1; - setedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); + addtovertices(&process->vertices, v); /* save vertex */ + vid = process->vertices.count - 1; + setedge(process, process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); return vid; } - - /* converge: from two points of differing sign, converge to zero crossing */ /* watch it: p1 and p2 are used to calculate */ -static void converge(const float p1[3], const float p2[3], float v1, float v2, - float (*function)(float, float, float), float p[3], MetaBall *mb, int f) +static void converge(PROCESS *process, const float p1[3], const float p2[3], float v1, float v2, + float p[3], MetaBall *mb, int f) { int i = 0; float pos[3], neg[3]; @@ -1426,8 +1404,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[0] = 0.5f * (pos[0] + neg[0]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; - else neg[0] = p[0]; + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; + else neg[0] = p[0]; } } @@ -1437,8 +1415,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[1] = 0.5f * (pos[1] + neg[1]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; - else neg[1] = p[1]; + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; + else neg[1] = p[1]; } } @@ -1448,8 +1426,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[2] = 0.5f * (pos[2] + neg[2]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; - else neg[2] = p[2]; + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; + else neg[2] = p[2]; } } @@ -1461,7 +1439,7 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, return; } - if ((function(p[0], p[1], p[2])) > 0.0f) { + if ((process->function(process, p[0], p[1], p[2])) > 0.0f) { copy_v3_v3(pos, &p[0]); } else { @@ -1471,7 +1449,7 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, } /* ************************************** */ -static void add_cube(PROCESS *mbproc, int i, int j, int k, int count) +static void add_cube(PROCESS *process, int i, int j, int k, int count) { CUBES *ncube; int n; @@ -1483,11 +1461,11 @@ static void add_cube(PROCESS *mbproc, int i, int j, int k, int count) for (b = j - 1; b < j + count; b++) for (c = k - 1; c < k + count; c++) { /* test if cube has been found before */ - if (setcenter(mbproc->centers, a, b, c) == 0) { + if (setcenter(process, process->centers, a, b, c) == 0) { /* push cube on stack: */ - ncube = (CUBES *) new_pgn_element(sizeof(CUBES)); - ncube->next = mbproc->cubes; - mbproc->cubes = ncube; + ncube = (CUBES *) new_pgn_element(process, sizeof(CUBES)); + ncube->next = process->cubes; + process->cubes = ncube; ncube->cube.i = a; ncube->cube.j = b; @@ -1495,18 +1473,18 @@ static void add_cube(PROCESS *mbproc, int i, int j, int k, int count) /* set corners of initial cube: */ for (n = 0; n < 8; n++) - ncube->cube.corners[n] = setcorner(mbproc, a + MB_BIT(n, 2), b + MB_BIT(n, 1), c + MB_BIT(n, 0)); + ncube->cube.corners[n] = setcorner(process, a + MB_BIT(n, 2), b + MB_BIT(n, 1), c + MB_BIT(n, 0)); } } } -static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) +static void find_first_points(PROCESS *process, MetaBall *mb, int a) { MetaElem *ml; float f; - ml = G_mb.mainb[a]; + ml = process->mainb[a]; f = 1.0f - (mb->thresh / ml->s); /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be @@ -1521,7 +1499,7 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) float tmp_v, workp_v, max_len, nx, ny, nz, max_dim; calc_mballco(ml, in); - in_v = mbproc->function(in[0], in[1], in[2]); + in_v = process->function(process, in[0], in[1], in[2]); for (i = 0; i < 3; i++) { switch (ml->type) { @@ -1566,16 +1544,16 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) calc_mballco(ml, out); - /*out_v = mbproc->function(out[0], out[1], out[2]);*/ /*UNUSED*/ + /*out_v = process->function(out[0], out[1], out[2]);*/ /*UNUSED*/ /* find "first points" on Implicit Surface of MetaElemnt ml */ copy_v3_v3(workp, in); workp_v = in_v; max_len = len_v3v3(out, in); - nx = abs((out[0] - in[0]) / mbproc->size); - ny = abs((out[1] - in[1]) / mbproc->size); - nz = abs((out[2] - in[2]) / mbproc->size); + nx = abs((out[0] - in[0]) / process->size); + ny = abs((out[1] - in[1]) / process->size); + nz = abs((out[2] - in[2]) / process->size); max_dim = max_fff(nx, ny, nz); if (max_dim != 0.0f) { @@ -1589,22 +1567,22 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) add_v3_v3(workp, dvec); /* compute value of implicite function */ - tmp_v = mbproc->function(workp[0], workp[1], workp[2]); + tmp_v = process->function(process, workp[0], workp[1], workp[2]); /* add cube to the stack, when value of implicite function crosses zero value */ if ((tmp_v < 0.0f && workp_v >= 0.0f) || (tmp_v > 0.0f && workp_v <= 0.0f)) { /* indexes of CUBE, which includes "first point" */ - c_i = (int)floor(workp[0] / mbproc->size); - c_j = (int)floor(workp[1] / mbproc->size); - c_k = (int)floor(workp[2] / mbproc->size); + c_i = (int)floor(workp[0] / process->size); + c_j = (int)floor(workp[1] / process->size); + c_k = (int)floor(workp[2] / process->size); /* add CUBE (with indexes c_i, c_j, c_k) to the stack, * this cube includes found point of Implicit Surface */ if ((ml->flag & MB_NEGATIVE) == 0) { - add_cube(mbproc, c_i, c_j, c_k, 1); + add_cube(process, c_i, c_j, c_k, 1); } else { - add_cube(mbproc, c_i, c_j, c_k, 2); + add_cube(process, c_i, c_j, c_k, 2); } } len = len_v3v3(workp, in); @@ -1618,43 +1596,43 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) } } -static void polygonize(PROCESS *mbproc, MetaBall *mb) +static void polygonize(PROCESS *process, MetaBall *mb) { CUBE c; int a; - mbproc->vertices.count = mbproc->vertices.max = 0; - mbproc->vertices.ptr = NULL; + process->vertices.count = process->vertices.max = 0; + process->vertices.ptr = NULL; /* allocate hash tables and build cube polygon table: */ - mbproc->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); - mbproc->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); - mbproc->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); + process->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); + process->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); + process->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); makecubetable(); - for (a = 0; a < G_mb.totelem; a++) { + for (a = 0; a < process->totelem; a++) { /* try to find 8 points on the surface for each MetaElem */ - find_first_points(mbproc, mb, a); + find_first_points(process, mb, a); } /* polygonize all MetaElems of current MetaBall */ - while (mbproc->cubes != NULL) { /* process active cubes till none left */ - c = mbproc->cubes->cube; + while (process->cubes != NULL) { /* process active cubes till none left */ + c = process->cubes->cube; /* polygonize the cube directly: */ - docube(&c, mbproc, mb); + docube(process, &c, mb); /* pop current cube from stack */ - mbproc->cubes = mbproc->cubes->next; + process->cubes = process->cubes->next; /* test six face directions, maybe add to stack: */ - testface(c.i - 1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF, mbproc); - testface(c.i + 1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF, mbproc); - testface(c.i, c.j - 1, c.k, &c, 1, LBN, LBF, RBN, RBF, mbproc); - testface(c.i, c.j + 1, c.k, &c, 1, LTN, LTF, RTN, RTF, mbproc); - testface(c.i, c.j, c.k - 1, &c, 0, LBN, LTN, RBN, RTN, mbproc); - testface(c.i, c.j, c.k + 1, &c, 0, LBF, LTF, RBF, RTF, mbproc); + testface(process, c.i - 1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF); + testface(process, c.i + 1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF); + testface(process, c.i, c.j - 1, c.k, &c, 1, LBN, LBF, RBN, RBF); + testface(process, c.i, c.j + 1, c.k, &c, 1, LTN, LTF, RTN, RTF); + testface(process, c.i, c.j, c.k - 1, &c, 0, LBN, LTN, RBN, RTN); + testface(process, c.i, c.j, c.k + 1, &c, 0, LBF, LTF, RBF, RTF); } } @@ -1666,7 +1644,7 @@ BLI_INLINE void copy_v3_fl3(float v[3], float x, float y, float z) v[2] = z; } -static float init_meta(Scene *scene, Object *ob) /* return totsize */ +static float init_meta(PROCESS *process, Scene *scene, Object *ob) /* return totsize */ { Scene *sce_iter = scene; Base *base; @@ -1733,7 +1711,7 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ ml_count++; ml = ml->next; } - G_mb.totelem -= ml_count; + process->totelem -= ml_count; } else { while (ml) { @@ -1763,12 +1741,12 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ mul_m4_m4m4(temp1, temp2, temp3); /* make a copy because of duplicates */ - G_mb.mainb[a] = new_pgn_element(sizeof(MetaElem)); - *(G_mb.mainb[a]) = *ml; - G_mb.mainb[a]->bb = new_pgn_element(sizeof(BoundBox)); + process->mainb[a] = new_pgn_element(process, sizeof(MetaElem)); + *(process->mainb[a]) = *ml; + process->mainb[a]->bb = new_pgn_element(process, sizeof(BoundBox)); - mat = new_pgn_element(4 * 4 * sizeof(float)); - imat = new_pgn_element(4 * 4 * sizeof(float)); + mat = new_pgn_element(process, 4 * 4 * sizeof(float)); + imat = new_pgn_element(process, 4 * 4 * sizeof(float)); /* mat is the matrix to transform from mball into the basis-mball */ invert_m4_m4(obinv, obmat); @@ -1778,10 +1756,10 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ invert_m4_m4(imat, mat); - G_mb.mainb[a]->rad2 = ml->rad * ml->rad; + process->mainb[a]->rad2 = ml->rad * ml->rad; - G_mb.mainb[a]->mat = (float *) mat; - G_mb.mainb[a]->imat = (float *) imat; + process->mainb[a]->mat = (float *) mat; + process->mainb[a]->imat = (float *) imat; if (!MB_TYPE_SIZE_SQUARED(ml->type)) { expx = ml->expx; @@ -1796,40 +1774,40 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ /* untransformed Bounding Box of MetaElem */ /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */ - copy_v3_fl3(G_mb.mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */ + copy_v3_fl3(process->mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */ + copy_v3_fl3(process->mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */ + copy_v3_fl3(process->mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */ + copy_v3_fl3(process->mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */ + copy_v3_fl3(process->mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */ + copy_v3_fl3(process->mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */ + copy_v3_fl3(process->mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */ + copy_v3_fl3(process->mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */ /* transformation of Metalem bb */ for (i = 0; i < 8; i++) - mul_m4_v3((float (*)[4])mat, G_mb.mainb[a]->bb->vec[i]); + mul_m4_v3((float (*)[4])mat, process->mainb[a]->bb->vec[i]); /* find max and min of transformed bb */ for (i = 0; i < 8; i++) { /* find maximums */ - if (G_mb.mainb[a]->bb->vec[i][0] > max_x) max_x = G_mb.mainb[a]->bb->vec[i][0]; - if (G_mb.mainb[a]->bb->vec[i][1] > max_y) max_y = G_mb.mainb[a]->bb->vec[i][1]; - if (G_mb.mainb[a]->bb->vec[i][2] > max_z) max_z = G_mb.mainb[a]->bb->vec[i][2]; + if (process->mainb[a]->bb->vec[i][0] > max_x) max_x = process->mainb[a]->bb->vec[i][0]; + if (process->mainb[a]->bb->vec[i][1] > max_y) max_y = process->mainb[a]->bb->vec[i][1]; + if (process->mainb[a]->bb->vec[i][2] > max_z) max_z = process->mainb[a]->bb->vec[i][2]; /* find minimums */ - if (G_mb.mainb[a]->bb->vec[i][0] < min_x) min_x = G_mb.mainb[a]->bb->vec[i][0]; - if (G_mb.mainb[a]->bb->vec[i][1] < min_y) min_y = G_mb.mainb[a]->bb->vec[i][1]; - if (G_mb.mainb[a]->bb->vec[i][2] < min_z) min_z = G_mb.mainb[a]->bb->vec[i][2]; + if (process->mainb[a]->bb->vec[i][0] < min_x) min_x = process->mainb[a]->bb->vec[i][0]; + if (process->mainb[a]->bb->vec[i][1] < min_y) min_y = process->mainb[a]->bb->vec[i][1]; + if (process->mainb[a]->bb->vec[i][2] < min_z) min_z = process->mainb[a]->bb->vec[i][2]; } /* create "new" bb, only point 0 and 6, which are * necessary for octal tree filling */ - G_mb.mainb[a]->bb->vec[0][0] = min_x - ml->rad; - G_mb.mainb[a]->bb->vec[0][1] = min_y - ml->rad; - G_mb.mainb[a]->bb->vec[0][2] = min_z - ml->rad; + process->mainb[a]->bb->vec[0][0] = min_x - ml->rad; + process->mainb[a]->bb->vec[0][1] = min_y - ml->rad; + process->mainb[a]->bb->vec[0][2] = min_z - ml->rad; - G_mb.mainb[a]->bb->vec[6][0] = max_x + ml->rad; - G_mb.mainb[a]->bb->vec[6][1] = max_y + ml->rad; - G_mb.mainb[a]->bb->vec[6][2] = max_z + ml->rad; + process->mainb[a]->bb->vec[6][0] = max_x + ml->rad; + process->mainb[a]->bb->vec[6][1] = max_y + ml->rad; + process->mainb[a]->bb->vec[6][2] = max_z + ml->rad; a++; } @@ -1842,13 +1820,13 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ /* totsize (= 'manhattan' radius) */ totsize = 0.0; - for (a = 0; a < G_mb.totelem; a++) { + for (a = 0; a < process->totelem; a++) { - vec[0] = G_mb.mainb[a]->x + G_mb.mainb[a]->rad + G_mb.mainb[a]->expx; - vec[1] = G_mb.mainb[a]->y + G_mb.mainb[a]->rad + G_mb.mainb[a]->expy; - vec[2] = G_mb.mainb[a]->z + G_mb.mainb[a]->rad + G_mb.mainb[a]->expz; + vec[0] = process->mainb[a]->x + process->mainb[a]->rad + process->mainb[a]->expx; + vec[1] = process->mainb[a]->y + process->mainb[a]->rad + process->mainb[a]->expy; + vec[2] = process->mainb[a]->z + process->mainb[a]->rad + process->mainb[a]->expz; - calc_mballco(G_mb.mainb[a], vec); + calc_mballco(process->mainb[a], vec); size = fabsf(vec[0]); if (size > totsize) totsize = size; @@ -1857,11 +1835,11 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ size = fabsf(vec[2]); if (size > totsize) totsize = size; - vec[0] = G_mb.mainb[a]->x - G_mb.mainb[a]->rad; - vec[1] = G_mb.mainb[a]->y - G_mb.mainb[a]->rad; - vec[2] = G_mb.mainb[a]->z - G_mb.mainb[a]->rad; + vec[0] = process->mainb[a]->x - process->mainb[a]->rad; + vec[1] = process->mainb[a]->y - process->mainb[a]->rad; + vec[2] = process->mainb[a]->z - process->mainb[a]->rad; - calc_mballco(G_mb.mainb[a], vec); + calc_mballco(process->mainb[a], vec); size = fabsf(vec[0]); if (size > totsize) totsize = size; @@ -1871,8 +1849,8 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ if (size > totsize) totsize = size; } - for (a = 0; a < G_mb.totelem; a++) { - G_mb.thresh += densfunc(G_mb.mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); + for (a = 0; a < process->totelem; a++) { + process->thresh += densfunc(process->mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); } return totsize; @@ -2181,20 +2159,20 @@ static void free_metaball_octal_node(octal_node *node) } /* If scene include more than one MetaElem, then octree is used */ -static void init_metaball_octal_tree(int depth) +static void init_metaball_octal_tree(PROCESS *process, int depth) { struct octal_node *node; ml_pointer *ml_p; float size[3]; int a; - G_mb.metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); - G_mb.metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); + process->metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); + process->metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); /* maximal depth of octree */ - G_mb.metaball_tree->depth = depth; + process->metaball_tree->depth = depth; - G_mb.metaball_tree->neg = node->neg = 0; - G_mb.metaball_tree->pos = node->pos = 0; + process->metaball_tree->neg = node->neg = 0; + process->metaball_tree->pos = node->pos = 0; node->elems.first = NULL; node->elems.last = NULL; @@ -2207,26 +2185,26 @@ static void init_metaball_octal_tree(int depth) node->x_max = node->y_max = node->z_max = -FLT_MAX; /* size of octal tree scene */ - for (a = 0; a < G_mb.totelem; a++) { - if (G_mb.mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = G_mb.mainb[a]->bb->vec[0][0]; - if (G_mb.mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = G_mb.mainb[a]->bb->vec[0][1]; - if (G_mb.mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = G_mb.mainb[a]->bb->vec[0][2]; + for (a = 0; a < process->totelem; a++) { + if (process->mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = process->mainb[a]->bb->vec[0][0]; + if (process->mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = process->mainb[a]->bb->vec[0][1]; + if (process->mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = process->mainb[a]->bb->vec[0][2]; - if (G_mb.mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = G_mb.mainb[a]->bb->vec[6][0]; - if (G_mb.mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = G_mb.mainb[a]->bb->vec[6][1]; - if (G_mb.mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = G_mb.mainb[a]->bb->vec[6][2]; + if (process->mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = process->mainb[a]->bb->vec[6][0]; + if (process->mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = process->mainb[a]->bb->vec[6][1]; + if (process->mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = process->mainb[a]->bb->vec[6][2]; ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); - ml_p->ml = G_mb.mainb[a]; + ml_p->ml = process->mainb[a]; BLI_addtail(&node->elems, ml_p); - if ((G_mb.mainb[a]->flag & MB_NEGATIVE) == 0) { + if ((process->mainb[a]->flag & MB_NEGATIVE) == 0) { /* number of positive MetaElem in scene */ - G_mb.metaball_tree->pos++; + process->metaball_tree->pos++; } else { /* number of negative MetaElem in scene */ - G_mb.metaball_tree->neg++; + process->metaball_tree->neg++; } } @@ -2236,61 +2214,106 @@ static void init_metaball_octal_tree(int depth) size[2] = node->z_max - node->z_min; /* first node is subdivided recursively */ - subdivide_metaball_octal_node(node, size[0], size[1], size[2], G_mb.metaball_tree->depth); + subdivide_metaball_octal_node(node, size[0], size[1], size[2], process->metaball_tree->depth); +} + +static void mball_count(PROCESS *process, Scene *scene, Object *basis) +{ + Scene *sce_iter = scene; + Base *base; + Object *ob, *bob = basis; + MetaElem *ml = NULL; + int basisnr, obnr; + char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; + + BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); + process->totelem = 0; + + /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ + if (F_ERROR == BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL)) + return; + + while (BKE_scene_base_iter_next(&sce_iter, 1, &base, &ob)) { + if (ob->type == OB_MBALL) { + if (ob == bob) { + MetaBall *mb = ob->data; + + /* if bob object is in edit mode, then dynamic list of all MetaElems + * is stored in editelems */ + if (mb->editelems) ml = mb->editelems->first; + /* if bob object is in object mode */ + else ml = mb->elems.first; + } + else { + BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); + + /* object ob has to be in same "group" ... it means, that it has to have + * same base of its name */ + if (strcmp(obname, basisname) == 0) { + MetaBall *mb = ob->data; + + /* if object is in edit mode, then dynamic list of all MetaElems + * is stored in editelems */ + if (mb->editelems) ml = mb->editelems->first; + /* if bob object is in object mode */ + else ml = mb->elems.first; + } + } + + for ( ; ml; ml = ml->next) { + if (!(ml->flag & MB_HIDE)) { + process->totelem++; + } + } + } + } } void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) { - PROCESS mbproc; MetaBall *mb; DispList *dl; int a, nr_cubes; float *co, *no, totsize, width; + PROCESS process = {0}; mb = ob->data; - if (G_mb.totelem == 0) return; + mball_count(&process, scene, ob); + + if (process.totelem == 0) return; if ((G.is_rendering == FALSE) && (mb->flag == MB_UPDATE_NEVER)) return; if (G.moving && mb->flag == MB_UPDATE_FAST) return; - curindex = totindex = 0; - indices = NULL; - G_mb.thresh = mb->thresh; + process.thresh = mb->thresh; /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */ - G_mb.mainb = MEM_mallocN(sizeof(void *) * G_mb.totelem, "mainb"); + process.mainb = MEM_mallocN(sizeof(void *) * process.totelem, "mainb"); /* initialize all mainb (MetaElems) */ - totsize = init_meta(scene, ob); - - if (G_mb.metaball_tree) { - free_metaball_octal_node(G_mb.metaball_tree->first); - MEM_freeN(G_mb.metaball_tree); - G_mb.metaball_tree = NULL; - } + totsize = init_meta(&process, scene, ob); /* if scene includes more than one MetaElem, then octal tree optimization is used */ - if ((G_mb.totelem > 1) && (G_mb.totelem <= 64)) init_metaball_octal_tree(1); - if ((G_mb.totelem > 64) && (G_mb.totelem <= 128)) init_metaball_octal_tree(2); - if ((G_mb.totelem > 128) && (G_mb.totelem <= 512)) init_metaball_octal_tree(3); - if ((G_mb.totelem > 512) && (G_mb.totelem <= 1024)) init_metaball_octal_tree(4); - if (G_mb.totelem > 1024) init_metaball_octal_tree(5); + if ((process.totelem > 1) && (process.totelem <= 64)) init_metaball_octal_tree(&process, 1); + if ((process.totelem > 64) && (process.totelem <= 128)) init_metaball_octal_tree(&process, 2); + if ((process.totelem > 128) && (process.totelem <= 512)) init_metaball_octal_tree(&process, 3); + if ((process.totelem > 512) && (process.totelem <= 1024)) init_metaball_octal_tree(&process, 4); + if (process.totelem > 1024) init_metaball_octal_tree(&process, 5); /* don't polygonize metaballs with too high resolution (base mball to small) * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ - if (G_mb.metaball_tree) { - if (ob->size[0] <= 0.00001f * (G_mb.metaball_tree->first->x_max - G_mb.metaball_tree->first->x_min) || - ob->size[1] <= 0.00001f * (G_mb.metaball_tree->first->y_max - G_mb.metaball_tree->first->y_min) || - ob->size[2] <= 0.00001f * (G_mb.metaball_tree->first->z_max - G_mb.metaball_tree->first->z_min)) + if (process.metaball_tree) { + if (ob->size[0] <= 0.00001f * (process.metaball_tree->first->x_max - process.metaball_tree->first->x_min) || + ob->size[1] <= 0.00001f * (process.metaball_tree->first->y_max - process.metaball_tree->first->y_min) || + ob->size[2] <= 0.00001f * (process.metaball_tree->first->z_max - process.metaball_tree->first->z_min)) { - new_pgn_element(-1); /* free values created by init_meta */ + new_pgn_element(&process, -1); /* free values created by init_meta */ - MEM_freeN(G_mb.mainb); + MEM_freeN(process.mainb); /* free tree */ - free_metaball_octal_node(G_mb.metaball_tree->first); - MEM_freeN(G_mb.metaball_tree); - G_mb.metaball_tree = NULL; + free_metaball_octal_node(process.metaball_tree->first); + MEM_freeN(process.metaball_tree); return; } @@ -2308,46 +2331,46 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) nr_cubes = (int)(0.5f + totsize / width); /* init process */ - mbproc.function = metaball; - mbproc.size = width; - mbproc.bounds = nr_cubes; - mbproc.cubes = NULL; - mbproc.delta = width / (float)(RES * RES); + process.function = metaball; + process.size = width; + process.bounds = nr_cubes; + process.cubes = NULL; + process.delta = width / (float)(RES * RES); - polygonize(&mbproc, mb); + polygonize(&process, mb); - MEM_freeN(G_mb.mainb); + MEM_freeN(process.mainb); /* free octal tree */ - if (G_mb.totelem > 1) { - free_metaball_octal_node(G_mb.metaball_tree->first); - MEM_freeN(G_mb.metaball_tree); - G_mb.metaball_tree = NULL; + if (process.totelem > 1) { + free_metaball_octal_node(process.metaball_tree->first); + MEM_freeN(process.metaball_tree); + process.metaball_tree = NULL; } - if (curindex) { - VERTEX *ptr = mbproc.vertices.ptr; + if (process.curindex) { + VERTEX *ptr = process.vertices.ptr; dl = MEM_callocN(sizeof(DispList), "mbaldisp"); BLI_addtail(dispbase, dl); dl->type = DL_INDEX4; - dl->nr = mbproc.vertices.count; - dl->parts = curindex; + dl->nr = process.vertices.count; + dl->parts = process.curindex; - dl->index = indices; - indices = NULL; + dl->index = process.indices; + process.indices = NULL; - a = mbproc.vertices.count; + a = process.vertices.count; dl->verts = co = MEM_mallocN(sizeof(float) * 3 * a, "mballverts"); dl->nors = no = MEM_mallocN(sizeof(float) * 3 * a, "mballnors"); - for (a = 0; a < mbproc.vertices.count; ptr++, a++, no += 3, co += 3) { + for (a = 0; a < process.vertices.count; ptr++, a++, no += 3, co += 3) { copy_v3_v3(co, ptr->co); copy_v3_v3(no, ptr->no); } } - freepolygonize(&mbproc); + freepolygonize(&process); } /* basic vertex data functions */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index c17830639e4..a0fa3317297 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -36,7 +36,7 @@ * \ingroup bke */ - +#include <stdlib.h> #include <stddef.h> #include <string.h> #include <stdarg.h> @@ -60,6 +60,7 @@ #include "BKE_cloth.h" #include "BKE_key.h" #include "BKE_multires.h" +#include "BKE_DerivedMesh.h" /* may move these, only for modifier_path_relbase */ #include "BKE_global.h" /* ugh, G.main->name only */ @@ -693,3 +694,65 @@ void modifier_path_init(char *path, int path_maxlen, const char *name) G.relbase_valid ? "//" : BLI_temporary_dir(), name); } + + +/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */ + +struct DerivedMesh *modwrap_applyModifier( + ModifierData *md, Object *ob, + struct DerivedMesh *dm, + ModifierApplyFlag flag) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); + + if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { + DM_ensure_normals(dm); + } + return mti->applyModifier(md, ob, dm, flag); +} + +struct DerivedMesh *modwrap_applyModifierEM( + ModifierData *md, Object *ob, + struct BMEditMesh *em, + DerivedMesh *dm, + ModifierApplyFlag flag) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); + + if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { + DM_ensure_normals(dm); + } + return mti->applyModifierEM(md, ob, em, dm, flag); +} + +void modwrap_deformVerts( + ModifierData *md, Object *ob, + DerivedMesh *dm, + float (*vertexCos)[3], int numVerts, + ModifierApplyFlag flag) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); + + if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + DM_ensure_normals(dm); + } + mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag); +} + +void modwrap_deformVertsEM( + ModifierData *md, Object *ob, + struct BMEditMesh *em, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); + + if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { + DM_ensure_normals(dm); + } + mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts); +} +/* end modifier callback wrappers */ diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index a36627bd903..e0a34e35acc 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -162,7 +162,7 @@ void BLI_path_rel(char *file, const char *relfile); bool BLI_path_is_rel(const char *path); /* path string comparisons: case-insensitive for Windows, case-sensitive otherwise */ -#ifdef WIN32 +#if defined(WIN32) # define BLI_path_cmp BLI_strcasecmp # define BLI_path_ncmp BLI_strncasecmp #else diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 224d02163cb..4d80080ed86 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -263,9 +263,21 @@ #define STACK_PUSH(stack, val) (void)((stack)[(_##stack##_index)++] = val) #define STACK_PUSH_RET(stack) ((void)stack, ((stack)[(_##stack##_index)++])) #define STACK_PUSH_RET_PTR(stack) ((void)stack, &((stack)[(_##stack##_index)++])) -#define STACK_POP(stack) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : NULL) -#define STACK_POP_ELSE(stack, r) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : r) +#define STACK_POP(stack) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : NULL) +#define STACK_POP_PTR(stack) ((_##stack##_index) ? &((stack)[--(_##stack##_index)]) : NULL) +#define STACK_POP_ELSE(stack, r) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : r) #define STACK_FREE(stack) ((void)stack) +#ifdef __GNUC__ +#define STACK_SWAP(stack_a, stack_b) { \ + SWAP(typeof(stack_a), stack_a, stack_b); \ + SWAP(unsigned int, _##stack_a##_index, _##stack_b##_index); \ + } (void)0 +#else +#define STACK_SWAP(stack_a, stack_b) { \ + SWAP(void *, stack_a, stack_b); \ + SWAP(unsigned int, _##stack_a##_index, _##stack_b##_index); \ + } (void)0 +#endif /* array helpers */ #define ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot) \ diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index a8fdcd56abb..2da36377e55 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -30,6 +30,7 @@ * \ingroup bli */ +#include <stdlib.h> #include <string.h> #include "MEM_guardedalloc.h" @@ -207,6 +208,8 @@ void *BLI_heap_popmin(Heap *heap) { void *ptr = heap->tree[0]->ptr; + BLI_assert(heap->size == 0); + heap->tree[0]->ptr = heap->freenodes; heap->freenodes = heap->tree[0]; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d44e3fd4948..07ed2f18111 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9605,6 +9605,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) link_list(fd, &user->themes); link_list(fd, &user->user_keymaps); link_list(fd, &user->addons); + link_list(fd, &user->autoexec_paths); for (keymap=user->user_keymaps.first; keymap; keymap=keymap->next) { keymap->modal_items= NULL; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d8bf1a5e4c4..9b6699f3f21 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -860,6 +860,7 @@ static void write_userdef(WriteData *wd) wmKeyMapItem *kmi; wmKeyMapDiffItem *kmdi; bAddon *bext; + bPathCompare *path_cmp; uiStyle *style; writestruct(wd, USER, "UserDef", 1, &U); @@ -888,6 +889,10 @@ static void write_userdef(WriteData *wd) IDP_WriteProperty(bext->prop, wd); } } + + for (path_cmp = U.autoexec_paths.first; path_cmp; path_cmp = path_cmp->next) { + writestruct(wd, DATA, "bPathCompare", 1, path_cmp); + } for (style= U.uistyles.first; style; style= style->next) { writestruct(wd, DATA, "uiStyle", 1, style); diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 8d95ab85df8..c92b049eafb 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -290,6 +290,6 @@ extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self); * but should not error on valid cases */ #define BM_LOOP_RADIAL_MAX 10000 #define BM_NGON_MAX 100000 -#define BM_OMP_LIMIT 10000 /* setting zero so we can catch bugs in OpenMP/BMesh */ +#define BM_OMP_LIMIT 0 /* 10000 */ /* setting zero so we can catch bugs in OpenMP/BMesh */ #endif /* __BMESH_CLASS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 2608a79d455..313d76721fa 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -498,6 +498,8 @@ static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag, BMIter iter; int tot = 0; + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + if (htype & BM_VERT) { for (ele = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); ele; ele = BM_iter_step(&iter)) { if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) continue; @@ -803,6 +805,8 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl int i; + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + if (hflag & BM_ELEM_SELECT) { BM_select_history_clear(bm); } @@ -872,6 +876,8 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla BMElem *ele; int i; + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + if (hflag & BM_ELEM_SELECT) { BM_select_history_clear(bm); } diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 79dacaad2fa..4027d4b2c19 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -628,6 +628,8 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu */ int BM_mesh_elem_count(BMesh *bm, const char htype) { + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + switch (htype) { case BM_VERT: return bm->totvert; case BM_EDGE: return bm->totedge; diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c index eda252f18f5..9fc1996e51a 100644 --- a/source/blender/bmesh/tools/bmesh_path.c +++ b/source/blender/bmesh/tools/bmesh_path.c @@ -144,7 +144,8 @@ LinkNode *BM_mesh_calc_path_vert( BLI_heap_insert(heap, 0.0f, v_src); cost[BM_elem_index_get(v_src)] = 0.0f; - while ((v = BLI_heap_popmin(heap))) { + while (!BLI_heap_is_empty(heap)) { + v = BLI_heap_popmin(heap); if (v == v_dst) break; @@ -261,7 +262,8 @@ LinkNode *BM_mesh_calc_path_edge( BLI_heap_insert(heap, 0.0f, e_src); cost[BM_elem_index_get(e_src)] = 0.0f; - while ((e = BLI_heap_popmin(heap))) { + while (!BLI_heap_is_empty(heap)) { + e = BLI_heap_popmin(heap); if (e == e_dst) break; @@ -386,7 +388,8 @@ LinkNode *BM_mesh_calc_path_face( BLI_heap_insert(heap, 0.0f, f_src); cost[BM_elem_index_get(f_src)] = 0.0f; - while ((f = BLI_heap_popmin(heap))) { + while (!BLI_heap_is_empty(heap)) { + f = BLI_heap_popmin(heap); if (f == f_dst) break; diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 097ea477501..f35edb70251 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -76,6 +76,8 @@ struct MeshStatVis; /* editmesh_utils.c */ +void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const bool use_self, const bool use_select, + const bool is_topo, float maxdist, int *r_index); void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const bool use_self, const bool use_select); void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to); struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index cb2f3e3286e..86e51b201d9 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -304,7 +304,7 @@ typedef struct uiSearchItems uiSearchItems; typedef void (*uiButHandleFunc)(struct bContext *C, void *arg1, void *arg2); typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origstr); typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2); -typedef void (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg); +typedef bool (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg); typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, const char *str, uiSearchItems *items); typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event); @@ -644,7 +644,7 @@ typedef struct AutoComplete AutoComplete; AutoComplete *autocomplete_begin(const char *startname, size_t maxlen); void autocomplete_do_name(AutoComplete *autocpl, const char *name); -void autocomplete_end(AutoComplete *autocpl, char *autoname); +bool autocomplete_end(AutoComplete *autocpl, char *autoname); /* Panels * diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 5a1ba8f31f0..19eb978a01e 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -443,17 +443,24 @@ void uiExplicitBoundsBlock(uiBlock *block, int minx, int miny, int maxx, int max static int ui_but_float_precision(uiBut *but, double value) { int prec; + const double pow10_neg[PRECISION_FLOAT_MAX + 1] = {1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001}; /* first check if prec is 0 and fallback to a simple default */ if ((prec = (int)but->a2) == -1) { prec = (but->hardmax < 10.001f) ? 3 : 2; } + BLI_assert(prec <= PRECISION_FLOAT_MAX); + BLI_assert(pow10_neg[prec] == pow(10, -prec)); + /* check on the number of decimal places need to display * the number, this is so 0.00001 is not displayed as 0.00, * _but_, this is only for small values si 10.0001 will not get * the same treatment */ - if (value != 0.0 && (value = ABS(value)) < 0.1) { + value = ABS(value); + if ((value < pow10_neg[prec]) && + (value > (1.0 / PRECISION_FLOAT_MAX_POW))) + { int value_i = (int)((value * PRECISION_FLOAT_MAX_POW) + 0.5); if (value_i != 0) { const int prec_span = 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */ @@ -3086,16 +3093,21 @@ void autocomplete_do_name(AutoComplete *autocpl, const char *name) } } -void autocomplete_end(AutoComplete *autocpl, char *autoname) +bool autocomplete_end(AutoComplete *autocpl, char *autoname) { - if (autocpl->truncate[0]) + bool change = false; + if (autocpl->truncate[0]) { BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen); + change = true; + } else { - if (autoname != autocpl->startname) /* don't copy a string over its self */ + if (autoname != autocpl->startname) { /* don't copy a string over its self */ BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen); + } } MEM_freeN(autocpl->truncate); MEM_freeN(autocpl); + return change; } static void ui_check_but_and_iconize(uiBut *but, int icon) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index a9378d11cc3..7aee228ddaa 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1828,20 +1828,19 @@ static bool ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directi static bool ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData *data) { char *str; - /* TODO, should return false if it cant autocomp. */ - bool changed = true; + bool change = true; str = data->str; if (data->searchbox) - ui_searchbox_autocomplete(C, data->searchbox, but, data->str); + change = ui_searchbox_autocomplete(C, data->searchbox, but, data->str); else - but->autocomplete_func(C, str, but->autofunc_arg); + change = but->autocomplete_func(C, str, but->autofunc_arg); but->pos = strlen(str); but->selsta = but->selend = but->pos; - return changed; + return change; } /* mode for ui_textedit_copypaste() */ @@ -6581,7 +6580,8 @@ static void ui_mouse_motion_towards_reinit(uiPopupBlockHandle *menu, const int x ui_mouse_motion_towards_init_ex(menu, xy, true); } -static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, const int xy[2]) +static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, const int xy[2], + const bool use_wiggle_room) { float p1[2], p2[2], p3[2], p4[2]; float oldp[2] = {menu->towards_xy[0], menu->towards_xy[1]}; @@ -6615,8 +6615,8 @@ static bool ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *me p4[1] = rect_px.ymax + margin; /* allow for some wiggle room, if the user moves a few pixels away, - * don't immediately quit */ - { + * don't immediately quit (only for top level menus) */ + if (use_wiggle_room) { const float cent[2] = { BLI_rctf_cent_x(&rect_px), BLI_rctf_cent_y(&rect_px)}; @@ -6789,7 +6789,8 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock return retval; } -static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, int level) +static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, + int level, const bool is_parent_inside) { ARegion *ar; uiBlock *block; @@ -7130,7 +7131,7 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH menu->menuretval = UI_RETURN_CANCEL | UI_RETURN_POPUP_OK; } else { - ui_mouse_motion_towards_check(block, menu, &event->x); + ui_mouse_motion_towards_check(block, menu, &event->x, is_parent_inside == false); /* check mouse moving outside of the menu */ if (inside == 0 && (block->flag & UI_BLOCK_MOVEMOUSE_QUIT)) { @@ -7233,7 +7234,8 @@ static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPo return WM_UI_HANDLER_BREAK; } -static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, int level) +static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, + int level, const bool is_parent_inside) { uiBut *but; uiHandleButtonData *data; @@ -7246,8 +7248,21 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB data = (but) ? but->active : NULL; submenu = (data) ? data->menu : NULL; - if (submenu) - retval = ui_handle_menus_recursive(C, event, submenu, level + 1); + if (submenu) { + bool inside = false; + + if (is_parent_inside == false) { + int mx, my; + uiBlock *block = menu->region->uiblocks.first; + + mx = event->x; + my = event->y; + ui_window_to_block(menu->region, block, &mx, &my); + inside = BLI_rctf_isect_pt(&block->rect, mx, my); + } + + retval = ui_handle_menus_recursive(C, event, submenu, level + 1, is_parent_inside || inside); + } /* now handle events for our own menu */ if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) { @@ -7275,7 +7290,7 @@ static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupB } } else { - retval = ui_handle_menu_event(C, event, menu, level); + retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside); } } @@ -7371,7 +7386,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE /* handle events for menus and their buttons recursively, * this will handle events from the top to the bottom menu */ if (data->menu) - retval = ui_handle_menus_recursive(C, event, data->menu, 0); + retval = ui_handle_menus_recursive(C, event, data->menu, 0, false); /* handle events for the activated button */ if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) || @@ -7417,7 +7432,7 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata) retval = WM_UI_HANDLER_CONTINUE; } - ui_handle_menus_recursive(C, event, menu, 0); + ui_handle_menus_recursive(C, event, menu, 0, false); /* free if done, does not free handle itself */ if (menu->menuretval) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 9de608f2730..a6076b8df78 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -471,7 +471,7 @@ ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBu bool ui_searchbox_inside(struct ARegion *ar, int x, int y); int ui_searchbox_find_index(struct ARegion *ar, const char *name); void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, const bool reset); -void ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str); +bool ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str); void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, const struct wmEvent *event); bool ui_searchbox_apply(uiBut *but, struct ARegion *ar); void ui_searchbox_free(struct bContext *C, struct ARegion *ar); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index b6575f4eca0..ef839f1d143 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -525,7 +525,7 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt name = (!uiname || uiname[0]) ? item->name : ""; icon = item->icon; value = item->value; - itemw = ui_text_icon_width(block->curlayout, name, icon, 0); + itemw = ui_text_icon_width(block->curlayout, icon_only ? "" : name, icon, 0); if (icon && name[0] && !icon_only) but = uiDefIconTextButR_prop(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index b764c70b111..1ff46004bdf 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1039,18 +1039,20 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset) ED_region_tag_redraw(ar); } -void ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str) +bool ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str) { uiSearchboxData *data = ar->regiondata; + bool changed = false; if (str[0]) { data->items.autocpl = autocomplete_begin(str, ui_get_but_string_max_length(but)); but->search_func(C, but->search_arg, but->editstr, &data->items); - autocomplete_end(data->items.autocpl, str); + changed = autocomplete_end(data->items.autocpl, str); data->items.autocpl = NULL; } + return changed; } static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 00eabad729e..d8efb972ce9 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2286,8 +2286,7 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol) } /* ************ button callbacks, draw ***************** */ - -static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) +static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign, bool emboss) { uiWidgetBase wtb; const float rad = 0.5f * BLI_rcti_size_y(rect); @@ -2298,9 +2297,10 @@ static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int round widget_init(&wtb); - /* fully rounded */ - round_box_edges(&wtb, roundboxalign, rect, rad); - + if (!emboss) { + round_box_edges(&wtb, roundboxalign, rect, rad); + } + /* decoration */ if (!(state & UI_TEXTINPUT)) { widget_num_tria(&wtb.tria1, rect, 0.6f, 'l'); @@ -2314,6 +2314,19 @@ static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int round rect->xmax -= textofs; } +static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) +{ + widget_numbut_draw(wcol, rect, state, roundboxalign, false); +} + +/* + * Draw number buttons still with triangles when field is not embossed +*/ +static void widget_numbut_embossn(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) +{ + widget_numbut_draw(wcol, rect, state, roundboxalign, true); +} + int ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol) { float dist, vec[4][2]; @@ -2671,7 +2684,7 @@ static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUS ui_draw_but_NORMAL(but, wcol, rect); } -static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) +static void widget_icon_has_anim(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) { if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) { uiWidgetBase wtb; @@ -2685,6 +2698,11 @@ static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti round_box_edges(&wtb, UI_CNR_ALL, rect, rad); widgetbase_draw(&wtb, wcol); } + else if (but->type == NUM) { + /* Draw number buttons still with left/right + * triangles when field is not embossed */ + widget_numbut_embossn(but, wcol, rect, state, roundboxalign); + } } diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index fa857edb6fc..963b9cf134b 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -507,17 +507,20 @@ bool EDBM_index_arrays_check(BMEditMesh *em) BMVert *EDBM_vert_at_index(BMEditMesh *em, int index) { - return em->vert_index && index < em->bm->totvert ? em->vert_index[index] : NULL; + BLI_assert((index >= 0) && (index < em->bm->totvert)); + return em->vert_index[index]; } BMEdge *EDBM_edge_at_index(BMEditMesh *em, int index) { - return em->edge_index && index < em->bm->totedge ? em->edge_index[index] : NULL; + BLI_assert((index >= 0) && (index < em->bm->totedge)); + return em->edge_index[index]; } BMFace *EDBM_face_at_index(BMEditMesh *em, int index) { - return (em->face_index && index < em->bm->totface && index >= 0) ? em->face_index[index] : NULL; + BLI_assert((index >= 0) && (index < em->bm->totface)); + return em->face_index[index]; } void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode) @@ -1144,46 +1147,58 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index) * preference */ #define BM_SEARCH_MAXDIST_MIRR 0.00002f #define BM_CD_LAYER_ID "__mirror_index" -void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bool use_select) +/** + * \param em Editmesh. + * \param use_self Allow a vertex to point to its self (middle verts). + * \param use_select Restrict to selected verts. + * \param is_topo Use topology mirror. + * \param maxdist Distance for close point test. + * \param r_index Optional array to write into, as an alternative to a customdata layer (length of total verts). + */ +void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const bool use_self, const bool use_select, + /* extra args */ + const bool is_topo, float maxdist, int *r_index) { Mesh *me = (Mesh *)em->ob->data; BMesh *bm = em->bm; BMIter iter; BMVert *v; - bool topo = false; int cd_vmirr_offset; + int i; /* one or the other is used depending if topo is enabled */ struct BMBVHTree *tree = NULL; MirrTopoStore_t mesh_topo_store = {NULL, -1, -1, -1}; - if (me && (me->editflag & ME_EDIT_MIRROR_TOPO)) { - topo = 1; - } - EDBM_index_arrays_ensure(em, BM_VERT); - em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID); - if (em->mirror_cdlayer == -1) { - BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID); - em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID); - } + if (r_index == NULL) { + const char *layer_id = BM_CD_LAYER_ID; + em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id); + if (em->mirror_cdlayer == -1) { + BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, layer_id); + em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id); + } - cd_vmirr_offset = CustomData_get_n_offset(&bm->vdata, CD_PROP_INT, - em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT)); + cd_vmirr_offset = CustomData_get_n_offset(&bm->vdata, CD_PROP_INT, + em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT)); - bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY; + bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY; + } BM_mesh_elem_index_ensure(bm, BM_VERT); - if (topo) { + if (is_topo) { ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, true); } else { tree = BKE_bmbvh_new(em, 0, NULL, false); } - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { +#define VERT_INTPTR(_v, _i) r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset); + + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + BLI_assert(BM_elem_index_get(v) == i); /* temporary for testing, check for selection */ if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) { @@ -1191,20 +1206,21 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bo } else { BMVert *v_mirr; - int *idx = BM_ELEM_CD_GET_VOID_P(v, cd_vmirr_offset); + int *idx = VERT_INTPTR(v, i); - if (topo) { - v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, BM_elem_index_get(v)); + if (is_topo) { + v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i); } else { float co[3] = {-v->co[0], v->co[1], v->co[2]}; - v_mirr = BKE_bmbvh_find_vert_closest(tree, co, BM_SEARCH_MAXDIST_MIRR); + v_mirr = BKE_bmbvh_find_vert_closest(tree, co, maxdist); } if (v_mirr && (use_self || (v_mirr != v))) { - *idx = BM_elem_index_get(v_mirr); - idx = BM_ELEM_CD_GET_VOID_P(v_mirr, cd_vmirr_offset); - *idx = BM_elem_index_get(v); + const int i_mirr = BM_elem_index_get(v_mirr); + *idx = i_mirr; + idx = VERT_INTPTR(v_mirr, i_mirr); + *idx = i; } else { *idx = -1; @@ -1213,8 +1229,9 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bo } +#undef VERT_INTPTR - if (topo) { + if (is_topo) { ED_mesh_mirrtopo_free(&mesh_topo_store); } else { @@ -1222,6 +1239,18 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bo } } +void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bool use_select) +{ + Mesh *me = (Mesh *)em->ob->data; + bool is_topo; + + is_topo = (me && (me->editflag & ME_EDIT_MIRROR_TOPO)); + + EDBM_verts_mirror_cache_begin_ex(em, use_self, use_select, + /* extra args */ + is_topo, BM_SEARCH_MAXDIST_MIRR, NULL); +} + BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v) { int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 74f1515fe74..8da953c4f84 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2905,9 +2905,9 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ - prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all Groups"); + prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All verts", "Clear Active Group"); + prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Verts", "Clear the active group"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 20edd3d32e7..527715cdbd3 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -220,7 +220,7 @@ static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( return OPERATOR_CANCELLED; } -static int screenshot_check(bContext *UNUSED(C), wmOperator *op) +static bool screenshot_check(bContext *UNUSED(C), wmOperator *op) { ScreenshotData *scd = op->customdata; return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 1ff7df3b041..181b32d58fc 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2145,7 +2145,7 @@ struct WPaintData { }; /* ensure we have data on wpaint start, add if needed */ -static int wpaint_ensure_data(bContext *C, wmOperator *op) +static bool wpaint_ensure_data(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); @@ -3390,6 +3390,10 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) vert_cache = gesture->userdata; } else { + if (wpaint_ensure_data(C, op) == FALSE) { + return OPERATOR_CANCELLED; + } + data.is_init = true; vert_cache = MEM_mallocN(sizeof(DMGradient_vertStore) * me->totvert, __func__); } diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 0cb0a3d6e5c..a2189f6237c 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -391,7 +391,7 @@ static const char *snd_ext_sound[] = { NULL }; -static int sound_mixdown_check(bContext *UNUSED(C), wmOperator *op) +static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op) { AUD_Container container = RNA_enum_get(op->ptr, "container"); diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index b20301cfc3b..9e045a39a0c 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -35,7 +35,6 @@ set(INC_SYS set(SRC buttons_context.c - buttons_header.c buttons_ops.c buttons_texture.c space_buttons.c diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c deleted file mode 100644 index f9742121e99..00000000000 --- a/source/blender/editors/space_buttons/buttons_header.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - * - * - * Contributor(s): Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/space_buttons/buttons_header.c - * \ingroup spbuttons - */ - - -#include <string.h> -#include <stdio.h> - -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" - -#include "BLF_translation.h" - -#include "BKE_context.h" -#include "BKE_modifier.h" -#include "BKE_paint.h" -#include "BKE_scene.h" - -#include "ED_buttons.h" -#include "ED_screen.h" -#include "ED_types.h" - -#include "DNA_brush_types.h" -#include "DNA_object_force.h" -#include "DNA_object_types.h" - -#include "UI_interface.h" -#include "UI_resources.h" -#include "UI_view2d.h" - -#include "buttons_intern.h" - - -#define B_CONTEXT_SWITCH 101 - -static void set_texture_context(const bContext *C, SpaceButs *sbuts) -{ - Scene *scene = CTX_data_scene(C); - - if (BKE_scene_use_new_shading_nodes(scene)) { - return; /* No texture context in new shading mode */ - } - - if ((sbuts->mainb == BCONTEXT_WORLD) && ED_texture_context_check_world(C)) { - sbuts->texture_context = SB_TEXC_WORLD; - } - else if ((sbuts->mainb == BCONTEXT_MATERIAL) && ED_texture_context_check_material(C)) { - sbuts->texture_context = SB_TEXC_MATERIAL; - } - else if ((sbuts->mainb == BCONTEXT_DATA) && ED_texture_context_check_lamp(C)) { - sbuts->texture_context = SB_TEXC_LAMP; - } - else if ((sbuts->mainb == BCONTEXT_PARTICLE) && ED_texture_context_check_particles(C)) { - sbuts->texture_context = SB_TEXC_PARTICLES; - } - else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && ED_texture_context_check_others(C)) { - sbuts->texture_context = SB_TEXC_OTHER; - } - /* Second pass: sbuts->mainbuser still contains the previous button context. - * Useful e.g. when we switch to material, no material present, add a material, switch to texture. - * See #35741. */ - else if ((sbuts->mainbuser == BCONTEXT_WORLD) && ED_texture_context_check_world(C)) { - sbuts->texture_context = SB_TEXC_WORLD; - } - else if ((sbuts->mainbuser == BCONTEXT_MATERIAL) && ED_texture_context_check_material(C)) { - sbuts->texture_context = SB_TEXC_MATERIAL; - } - else if ((sbuts->mainbuser == BCONTEXT_DATA) && ED_texture_context_check_lamp(C)) { - sbuts->texture_context = SB_TEXC_LAMP; - } - else if ((sbuts->mainbuser == BCONTEXT_PARTICLE) && ED_texture_context_check_particles(C)) { - sbuts->texture_context = SB_TEXC_PARTICLES; - } - else if ((ELEM(sbuts->mainbuser, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && ED_texture_context_check_others(C)) { - sbuts->texture_context = SB_TEXC_OTHER; - } - /* Else, just be sure that current context is valid! */ - else { - buttons_check_texture_context(C, sbuts); - } -} - -static void do_buttons_buttons(bContext *C, void *UNUSED(arg), int event) -{ - SpaceButs *sbuts = CTX_wm_space_buts(C); - - if (!sbuts) /* editor type switch */ - return; - - switch (event) { - case B_CONTEXT_SWITCH: - ED_area_tag_redraw(CTX_wm_area(C)); - - set_texture_context(C, sbuts); - - sbuts->preview = 1; - break; - } - - sbuts->mainbuser = sbuts->mainb; -} - -#define BUT_UNIT_X (UI_UNIT_X + 2 * U.pixelsize) - -void buttons_header_buttons(const bContext *C, ARegion *ar) -{ - SpaceButs *sbuts = CTX_wm_space_buts(C); - uiBlock *block; - uiBut *but; - int headery = ED_area_headersize(); - int xco, yco = 0.5f * (headery - UI_UNIT_Y); - - buttons_context_compute(C, sbuts); - - block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); - uiBlockSetHandleFunc(block, do_buttons_buttons, NULL); - - xco = ED_area_header_switchbutton(C, block, yco); - - uiBlockSetEmboss(block, UI_EMBOSS); - - xco -= UI_UNIT_X; - - /* Default panels */ - - uiBlockBeginAlign(block); - -#define BUTTON_HEADER_CTX(_ctx, _icon, _tip) \ - if (sbuts->pathflag & (1 << _ctx)) { \ - but = uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, _icon, xco += BUT_UNIT_X, yco, BUT_UNIT_X, UI_UNIT_Y, \ - &(sbuts->mainb), 0.0, (float)_ctx, 0, 0, TIP_(_tip)); \ - uiButClearFlag(but, UI_BUT_UNDO); \ - } (void)0 - - BUTTON_HEADER_CTX(BCONTEXT_RENDER, ICON_SCENE, N_("Render")); - BUTTON_HEADER_CTX(BCONTEXT_RENDER_LAYER, ICON_RENDERLAYERS, N_("Render Layers")); - BUTTON_HEADER_CTX(BCONTEXT_SCENE, ICON_SCENE_DATA, N_("Scene")); - BUTTON_HEADER_CTX(BCONTEXT_WORLD, ICON_WORLD, N_("World")); - BUTTON_HEADER_CTX(BCONTEXT_OBJECT, ICON_OBJECT_DATA, N_("Object")); - BUTTON_HEADER_CTX(BCONTEXT_CONSTRAINT, ICON_CONSTRAINT, N_("Object Constraints")); - BUTTON_HEADER_CTX(BCONTEXT_MODIFIER, ICON_MODIFIER, N_("Object Modifiers")); - BUTTON_HEADER_CTX(BCONTEXT_DATA, sbuts->dataicon, N_("Object Data")); - BUTTON_HEADER_CTX(BCONTEXT_BONE, ICON_BONE_DATA, N_("Bone")); - BUTTON_HEADER_CTX(BCONTEXT_BONE_CONSTRAINT, ICON_CONSTRAINT_BONE, N_("Bone Constraints")); - BUTTON_HEADER_CTX(BCONTEXT_MATERIAL, ICON_MATERIAL, N_("Material")); - BUTTON_HEADER_CTX(BCONTEXT_TEXTURE, ICON_TEXTURE, N_("Textures")); - BUTTON_HEADER_CTX(BCONTEXT_PARTICLE, ICON_PARTICLES, N_("Particles")); - BUTTON_HEADER_CTX(BCONTEXT_PHYSICS, ICON_PHYSICS, N_("Physics")); - -#undef BUTTON_HEADER_CTX - - xco += BUT_UNIT_X; - - uiBlockEndAlign(block); - - /* always as last */ - UI_view2d_totRect_set(&ar->v2d, xco + (UI_UNIT_X / 2), BLI_rctf_size_y(&ar->v2d.tot)); - - uiEndBlock(C, block); - uiDrawBlock(C, block); -} - - diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 55c9bf0dffd..f294729ae97 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -97,9 +97,6 @@ typedef struct ButsContextTexture { /* internal exports only */ -/* buttons_header.c */ -void buttons_header_buttons(const struct bContext *C, struct ARegion *ar); - /* buttons_context.c */ void buttons_context_compute(const struct bContext *C, struct SpaceButs *sbuts); int buttons_context(const struct bContext *C, const char *member, struct bContextDataResult *result); @@ -111,7 +108,6 @@ extern const char *buttons_context_dir[]; /* doc access */ /* buttons_texture.c */ void buttons_texture_context_compute(const struct bContext *C, struct SpaceButs *sbuts); -void buttons_check_texture_context(const struct bContext *C, struct SpaceButs *sbuts); /* buttons_ops.c */ void BUTTONS_OT_file_browse(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 0b1f244a1b5..51e740e539f 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -135,8 +135,7 @@ bool ED_texture_context_check_others(const bContext *C) return false; } -/* Only change texture context if current one is invalid! */ -void buttons_check_texture_context(const bContext *C, SpaceButs *sbuts) +static void set_texture_context(const bContext *C, SpaceButs *sbuts) { Scene *scene = CTX_data_scene(C); @@ -151,11 +150,27 @@ void buttons_check_texture_context(const bContext *C, SpaceButs *sbuts) bool valid_particles = ED_texture_context_check_particles(C); bool valid_others = ED_texture_context_check_others(C); - if (((sbuts->texture_context == SB_TEXC_WORLD) && !valid_world) || - ((sbuts->texture_context == SB_TEXC_MATERIAL) && !valid_material) || - ((sbuts->texture_context == SB_TEXC_LAMP) && !valid_lamp) || - ((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) || - ((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others)) + if ((sbuts->mainb == BCONTEXT_WORLD) && valid_world) { + sbuts->texture_context = SB_TEXC_WORLD; + } + else if ((sbuts->mainb == BCONTEXT_MATERIAL) && valid_material) { + sbuts->texture_context = SB_TEXC_MATERIAL; + } + else if ((sbuts->mainb == BCONTEXT_DATA) && valid_lamp) { + sbuts->texture_context = SB_TEXC_LAMP; + } + else if ((sbuts->mainb == BCONTEXT_PARTICLE) && valid_particles) { + sbuts->texture_context = SB_TEXC_PARTICLES; + } + else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && valid_others) { + sbuts->texture_context = SB_TEXC_OTHER; + } + /* Else, just be sure that current context is valid! */ + else if (((sbuts->texture_context == SB_TEXC_WORLD) && !valid_world) || + ((sbuts->texture_context == SB_TEXC_MATERIAL) && !valid_material) || + ((sbuts->texture_context == SB_TEXC_LAMP) && !valid_lamp) || + ((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) || + ((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others)) { if (valid_others) { sbuts->texture_context = SB_TEXC_OTHER; @@ -368,7 +383,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts) Scene *scene = CTX_data_scene(C); ID *pinid = sbuts->pinid; - buttons_check_texture_context(C, sbuts); + set_texture_context(C, sbuts); if (!(BKE_scene_use_new_shading_nodes(scene) || (sbuts->texture_context == SB_TEXC_OTHER))) { if (ct) { diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 02b06e08eed..e6c6df416bf 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -87,7 +87,7 @@ static SpaceLink *buttons_new(const bContext *UNUSED(C)) BLI_addtail(&sbuts->regionbase, ar); ar->regiontype = RGN_TYPE_WINDOW; - + return (SpaceLink *)sbuts; } @@ -200,22 +200,17 @@ static void buttons_keymap(struct wmKeyConfig *keyconf) /* add handlers, stuff you only do once or on area/region changes */ static void buttons_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar) { - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); + ED_region_header_init(ar); } static void buttons_header_area_draw(const bContext *C, ARegion *ar) { - /* clear */ - UI_ThemeClearColor(ED_screen_area_active(C) ? TH_HEADER : TH_HEADERDESEL); - glClear(GL_COLOR_BUFFER_BIT); - - /* set view2d view matrix for scrolling (without scrollers) */ - UI_view2d_view_ortho(&ar->v2d); - - buttons_header_buttons(C, ar); + SpaceButs *sbuts = CTX_wm_space_buts(C); + + /* Needed for RNA to get the good values! */ + buttons_context_compute(C, sbuts); - /* restore view matrix? */ - UI_view2d_view_restore(C); + ED_region_header(C, ar); } /* draw a certain button set only if properties area is currently diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 60420649093..986b71abc8a 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -807,7 +807,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_PATH) - if (ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */ + if (ELEM4(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */ return TRUE; return FALSE; diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index e5c6a839380..240106d37d5 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -105,8 +105,8 @@ float file_string_width(const char *str); float file_font_pointsize(void); void file_change_dir(bContext *C, int checkdir); int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file); -void autocomplete_directory(struct bContext *C, char *str, void *arg_v); -void autocomplete_file(struct bContext *C, char *str, void *arg_v); +bool autocomplete_directory(struct bContext *C, char *str, void *arg_v); +bool autocomplete_file(struct bContext *C, char *str, void *arg_v); /* file_panels.c */ void file_panels_register(struct ARegionType *art); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 25d865d857b..a31af851575 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -609,6 +609,7 @@ void file_change_dir(bContext *C, int checkdir) folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + file_draw_check_cb(C, NULL, NULL); } } @@ -637,9 +638,10 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche return match; } -void autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) +bool autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) { SpaceFile *sfile = CTX_wm_space_file(C); + bool change = false; /* search if str matches the beginning of name */ if (str[0] && sfile->files) { @@ -674,20 +676,25 @@ void autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v)) } closedir(dir); - autocomplete_end(autocpl, str); - if (BLI_exists(str)) { - BLI_add_slash(str); - } - else { - BLI_strncpy(sfile->params->dir, str, sizeof(sfile->params->dir)); + change = autocomplete_end(autocpl, str); + if (change) { + if (BLI_exists(str)) { + BLI_add_slash(str); + } + else { + BLI_strncpy(sfile->params->dir, str, sizeof(sfile->params->dir)); + } } } } + + return change; } -void autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) +bool autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) { SpaceFile *sfile = CTX_wm_space_file(C); + bool change = false; /* search if str matches the beginning of name */ if (str[0] && sfile->files) { @@ -701,8 +708,9 @@ void autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) autocomplete_do_name(autocpl, file->relname); } } - autocomplete_end(autocpl, str); + change = autocomplete_end(autocpl, str); } + return change; } void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 8272222e4c2..0a2bd2aad81 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1441,7 +1441,7 @@ static int image_save_as_exec(bContext *C, wmOperator *op) } -static int image_save_as_check(bContext *UNUSED(C), wmOperator *op) +static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op) { ImageFormatData *imf = op->customdata; return WM_operator_filesel_ensure_ext_imtype(op, imf); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 164382c300d..159cc74af56 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -425,8 +425,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) if (items == 0) { BKE_report(op->reports, RPT_ERROR, - "No active track(s) to add strip to. " - "Select an existing track or add one before trying again"); + "No active track(s) to add strip to, select an existing track or add one before trying again"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 0d875acb040..2fa901a2f28 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -773,8 +773,12 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float #define B_VGRP_PNL_COPY 1 #define B_VGRP_PNL_NORMALIZE 2 -#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */ -#define B_VGRP_PNL_COPY_SINGLE 16384 /* or greater */ +#define B_VGRP_PNL_TOGGLE_USE_ALL 4 +#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */ +#define B_VGRP_PNL_DELETE_SINGLE 4096 /* or greater */ +#define B_VGRP_PNL_COPY_SINGLE 8192 /* or greater */ +#define B_VGRP_PNL_ACTIVE 16384 /* or greater */ + static MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index) { @@ -904,6 +908,18 @@ static void vgroup_adjust_active(Object *ob, int def_nr) } } +static void vgroup_remove_weight(Object *ob, const int def_nr) +{ + MDeformVert *dvert_act; + MDeformWeight *dw; + + dvert_act = ED_mesh_active_dvert_get_only(ob); + + dw = defvert_find_index(dvert_act, def_nr); + defvert_remove_group(dvert_act, dw); + +} + static void vgroup_copy_active_to_sel(Object *ob) { Mesh *me = ob->data; @@ -1064,9 +1080,15 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) else if (event == B_VGRP_PNL_COPY) { vgroup_copy_active_to_sel(ob); } + else if (event >= B_VGRP_PNL_ACTIVE) { + ob->actdef = event - B_VGRP_PNL_ACTIVE + 1; + } else if (event >= B_VGRP_PNL_COPY_SINGLE) { vgroup_copy_active_to_sel_single(ob, event - B_VGRP_PNL_COPY_SINGLE); } + else if (event >= B_VGRP_PNL_DELETE_SINGLE) { + vgroup_remove_weight(ob, event - B_VGRP_PNL_DELETE_SINGLE); + } else if (event >= B_VGRP_PNL_EDIT_SINGLE) { vgroup_adjust_active(ob, event - B_VGRP_PNL_EDIT_SINGLE); } @@ -1111,6 +1133,9 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) if (dv && dv->totweight) { uiLayout *col; + uiLayout *row; + uiLayout *box; + uiBut *but; bDeformGroup *dg; unsigned int i; int subset_count, vgroup_tot; @@ -1119,22 +1144,50 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) int yco = 0; uiBlockSetHandleFunc(block, do_view3d_vgroup_buttons, NULL); + box = uiLayoutBox(pa->layout); - col = uiLayoutColumn(pa->layout, FALSE); - block = uiLayoutAbsoluteBlock(col); - - uiBlockBeginAlign(block); + col = uiLayoutColumn(box, true); vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count); for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) { if (vgroup_validmap[i]) { MDeformWeight *dw = defvert_find_index(dv, i); if (dw) { - uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + i, dg->name, 0, yco, 180, 20, + int x, xco = 0; + row = uiLayoutRow(col, true); + (void)row; + + uiBlockSetEmboss(block, UI_EMBOSSN); + but = uiDefBut(block, BUT, B_VGRP_PNL_ACTIVE + i, dg->name, + xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, + NULL, 0.0, 1.0, 1, 3, ""); + uiButSetFlag(but, UI_TEXT_LEFT); + + if (ob->actdef != i + 1) { + uiButSetFlag(but, UI_BUT_INACTIVE); + } + xco += x; + + //uiBlockSetEmboss(block, UI_EMBOSS); + + but = uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + i, "", + xco, yco, (x = UI_UNIT_X * 4), UI_UNIT_Y, &dw->weight, 0.0, 1.0, 1, 3, ""); - uiDefBut(block, BUT, B_VGRP_PNL_COPY_SINGLE + i, "C", 180, yco, 20, 20, - NULL, 0, 0, 0, 0, TIP_("Copy this group's weight to other selected verts")); - yco -= 20; + uiButSetFlag(but, UI_TEXT_LEFT); + xco += x; + + uiDefIconBut(block, BUT, B_VGRP_PNL_COPY_SINGLE + i, ICON_PASTEDOWN, + xco, yco, (x = UI_UNIT_X), UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Copy this group's weight to other selected verts")); + xco += x; + + uiDefIconBut(block, BUT, B_VGRP_PNL_DELETE_SINGLE + i, ICON_X, + xco, yco, (x = UI_UNIT_X), UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Delete this weight from the vertex")); + xco += x; + + yco -= UI_UNIT_Y; + (void)xco; } } } @@ -1142,13 +1195,16 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) yco -= 2; - uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefBut(block, BUT, B_VGRP_PNL_NORMALIZE, IFACE_("Normalize"), 0, yco, 100, 20, + uiBlockSetEmboss(block, UI_EMBOSS); + col = uiLayoutColumn(pa->layout, true); + row = uiLayoutRow(col, true); + + uiDefBut(block, BUT, B_VGRP_PNL_NORMALIZE, IFACE_("Normalize"), + 0, yco, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Normalize active vertex weights")); - uiDefBut(block, BUT, B_VGRP_PNL_COPY, IFACE_("Copy"), 100, yco, 100, 20, + uiDefBut(block, BUT, B_VGRP_PNL_COPY, IFACE_("Copy"), + UI_UNIT_X * 5, yco, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Copy active vertex to other selected verts")); - uiBlockEndAlign(block); } } diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index 9e310c84bd0..180686b4b82 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -237,7 +237,7 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const flo foreachScreenFace_userData *data = userData; BMFace *efa = EDBM_face_at_index(data->vc.em, index); - if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { float screen_co[2]; if (ED_view3d_project_float_object(data->vc.ar, cent, screen_co, data->clip_flag) == V3D_PROJ_RET_OK) { data->func(data->userData, efa, screen_co, index); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index bba151f1a5e..c119fe24210 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1166,6 +1166,26 @@ static bool selectbuffer_has_bones(const unsigned int *buffer, const unsigned in return false; } +/* utility function for mixed_bones_object_selectbuffer */ +static short selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const short hits15) +{ + return hits15; +} + +static short selectbuffer_ret_hits_9(unsigned int *buffer, const short hits15, const short hits9) +{ + const int offs = 4 * hits15; + memcpy(buffer, buffer + offs, 4 * offs); + return hits9; +} + +static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, const short hits9, const short hits5) +{ + const int offs = 4 * hits15 + 4 * hits9; + memcpy(buffer, buffer + offs, 4 * offs); + return hits5; +} + /* we want a select buffer with bones, if there are... */ /* so check three selection levels and compare */ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2]) @@ -1177,48 +1197,39 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14); hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect); - if (hits15 > 0) { + if (hits15 == 1) { + return selectbuffer_ret_hits_15(buffer, hits15); + } + else if (hits15 > 0) { has_bones15 = selectbuffer_has_bones(buffer, hits15); offs = 4 * hits15; BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9); hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect); - if (hits9 > 0) { + if (hits9 == 1) { + return selectbuffer_ret_hits_9(buffer, hits15, hits9); + } + else if (hits9 > 0) { has_bones9 = selectbuffer_has_bones(buffer + offs, hits9); offs += 4 * hits9; BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5); hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect); - if (hits5 > 0) { + if (hits5 == 1) { + return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + } + else if (hits5 > 0) { has_bones5 = selectbuffer_has_bones(buffer + offs, hits5); } } + + if (has_bones5) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + else if (has_bones9) return selectbuffer_ret_hits_9(buffer, hits15, hits9); + else if (has_bones15) return selectbuffer_ret_hits_15(buffer, hits15); - if (has_bones5) { - offs = 4 * hits15 + 4 * hits9; - memcpy(buffer, buffer + offs, 4 * offs); - return hits5; - } - if (has_bones9) { - offs = 4 * hits15; - memcpy(buffer, buffer + offs, 4 * offs); - return hits9; - } - if (has_bones15) { - return hits15; - } - - if (hits5 > 0) { - offs = 4 * hits15 + 4 * hits9; - memcpy(buffer, buffer + offs, 4 * offs); - return hits5; - } - if (hits9 > 0) { - offs = 4 * hits15; - memcpy(buffer, buffer + offs, 4 * offs); - return hits9; - } - return hits15; + if (hits5 > 0) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + else if (hits9 > 0) return selectbuffer_ret_hits_9(buffer, hits15, hits9); + else return selectbuffer_ret_hits_15(buffer, hits15); } return 0; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index d8f763c6a54..ac5727a116c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -196,7 +196,7 @@ static void sort_trans_data(TransInfo *t) /* distance calculated from not-selected vertex to nearest selected vertex * warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */ -static void set_prop_dist(TransInfo *t, short with_dist) +static void set_prop_dist(TransInfo *t, const bool with_dist) { TransData *tob; int a; @@ -216,12 +216,9 @@ static void set_prop_dist(TransInfo *t, short with_dist) if (td->flag & TD_SELECTED) { sub_v3_v3v3(vec, tob->center, td->center); mul_m3_v3(tob->mtx, vec); - dist = normalize_v3(vec); - if (tob->rdist == -1.0f) { - tob->rdist = dist; - } - else if (dist < tob->rdist) { - tob->rdist = dist; + dist = len_squared_v3(vec); + if ((tob->rdist == -1.0f) || (dist < (tob->rdist * tob->rdist))) { + tob->rdist = sqrtf(dist); } } else { @@ -1778,90 +1775,125 @@ void flushTransParticles(TransInfo *t) /* ********************* mesh ****************** */ -/* I did this wrong, it should be a breadth-first search - * but instead it's a depth-first search, fudged - * to report shortest distances. I have no idea how fast - * or slow this is. */ -static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[3][3], float *dists) +static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, + float *dists, const float *dists_prev, + float mtx[3][3]) { - BMVert **queue = NULL; - float *dqueue = NULL; - int *tots = MEM_callocN(sizeof(int) * em->bm->totvert, "tots editmesh_set_connectivity_distance"); - BLI_array_declare(queue); - BLI_array_declare(dqueue); - SmallHash svisit, *visit = &svisit; - BMVert *v; - BMIter viter; - int i, start; - - fill_vn_fl(dists, em->bm->totvert, FLT_MAX); + if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && + (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) + { + const int i = BM_elem_index_get(v); + const int i_other = BM_elem_index_get(v_other); + float vec[3]; + float dist_other; + sub_v3_v3v3(vec, v->co, v_other->co); + mul_m3_v3(mtx, vec); + + dist_other = dists_prev[i] + len_v3(vec); + if (dist_other < dists[i_other]) { + dists[i_other] = dist_other; + return true; + } + } - BM_mesh_elem_index_ensure(em->bm, BM_VERT); + return false; +} - BLI_smallhash_init(visit); +static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists) +{ + /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ + float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__); - BM_ITER_MESH (v, &viter, em->bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) - continue; - - - BLI_smallhash_insert(visit, (uintptr_t)v, NULL); - BLI_array_append(queue, v); - BLI_array_append(dqueue, 0.0f); - dists[BM_elem_index_get(v)] = 0.0f; + BMVert **queue = MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__); + STACK_DECLARE(queue); + + /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ + BMVert **queue_next = MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__); + STACK_DECLARE(queue_next); + + STACK_INIT(queue); + STACK_INIT(queue_next); + + { + BMIter viter; + BMVert *v; + int i; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + BM_elem_index_set(v, i); /* set_inline */ + BM_elem_flag_disable(v, BM_ELEM_TAG); + + if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + dists[i] = FLT_MAX; + } + else { + STACK_PUSH(queue, v); + + dists[i] = 0.0f; + } + } } - - start = 0; - while (start < BLI_array_count(queue)) { - BMIter eiter; - BMEdge *e; - BMVert *v3, *v2; - float d, vec[3]; - - v2 = queue[start]; - d = dqueue[start]; - - BM_ITER_ELEM (e, &eiter, v2, BM_EDGES_OF_VERT) { - float d2; - v3 = BM_edge_other_vert(e, v2); - - if (BM_elem_flag_test(v3, BM_ELEM_SELECT) || BM_elem_flag_test(v3, BM_ELEM_HIDDEN)) - continue; - - sub_v3_v3v3(vec, v2->co, v3->co); - mul_m3_v3(mtx, vec); - - d2 = d + len_v3(vec); - - if (dists[BM_elem_index_get(v3)] != FLT_MAX) - dists[BM_elem_index_get(v3)] = min_ff(d2, dists[BM_elem_index_get(v3)]); - else - dists[BM_elem_index_get(v3)] = d2; - - tots[BM_elem_index_get(v3)] = 1; - if (BLI_smallhash_haskey(visit, (uintptr_t)v3)) - continue; - - BLI_smallhash_insert(visit, (uintptr_t)v3, NULL); + do { + BMVert *v; + unsigned int i; + + memcpy(dists_prev, dists, sizeof(float) * bm->totvert); + + while ((v = STACK_POP(queue))) { + BMIter iter; + BMEdge *e; + BMLoop *l; + + /* connected edge-verts */ + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == 0) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { + BM_elem_flag_enable(v_other, BM_ELEM_TAG); + STACK_PUSH(queue_next, v_other); + } + } + } + } - BLI_array_append(queue, v3); - BLI_array_append(dqueue, d2); + /* connected face-verts (excluding adjacent verts) */ + BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + if ((BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0) && (l->f->len > 3)) { + BMLoop *l_end = l->prev; + l = l->next->next; + do { + BMVert *v_other = l->v; + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { + BM_elem_flag_enable(v_other, BM_ELEM_TAG); + STACK_PUSH(queue_next, v_other); + } + } + } while ((l = l->next) != l_end); + } + } } - - start++; - } - BLI_smallhash_release(visit); - - for (i = 0; i < em->bm->totvert; i++) { - if (tots[i]) - dists[i] /= (float)tots[i]; - } - - BLI_array_free(queue); - BLI_array_free(dqueue); - MEM_freeN(tots); + /* clear for the next loop */ + for (i = 0; i < STACK_SIZE(queue_next); i++) { + BM_elem_flag_disable(queue_next[i], BM_ELEM_TAG); + } + + STACK_SWAP(queue, queue_next); + + /* none should be tagged now since 'queue_next' is empty */ + BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0); + + } while (STACK_SIZE(queue)); + + STACK_FREE(queue); + STACK_FREE(queue_next); + + MEM_freeN(queue); + MEM_freeN(queue_next); + MEM_freeN(dists_prev); } static BMElem *bm_vert_single_select_face(BMVert *eve) @@ -2099,7 +2131,7 @@ static void createTransEditVerts(TransInfo *t) pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); if (propmode & T_PROP_CONNECTED) { - editmesh_set_connectivity_distance(em, mtx, dists); + editmesh_set_connectivity_distance(em->bm, mtx, dists); } /* detect CrazySpace [tm] */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 917335e2068..386eda7dd38 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2113,7 +2113,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo hitlen = hit.efa->len; } else if (selectmode == UV_SELECT_ISLAND) { - uv_find_nearest_vert(scene, ima, em, co, NULL, &hit); + uv_find_nearest_edge(scene, ima, em, co, &hit); if (hit.efa == NULL) { return OPERATOR_CANCELLED; @@ -2378,7 +2378,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent RNA_float_get_array(op->ptr, "location", co); } - uv_find_nearest_vert(scene, ima, em, co, NULL, &hit); + uv_find_nearest_edge(scene, ima, em, co, &hit); hit_p = &hit; } diff --git a/source/blender/freestyle/intern/application/AppCanvas.cpp b/source/blender/freestyle/intern/application/AppCanvas.cpp index e1f300b3ce0..f621f45ff77 100644 --- a/source/blender/freestyle/intern/application/AppCanvas.cpp +++ b/source/blender/freestyle/intern/application/AppCanvas.cpp @@ -136,8 +136,8 @@ void AppCanvas::readColorPixels(int x, int y, int w, int h, RGBImage& oImage) co int ymin = border().getMin().y(); int xmax = border().getMax().x(); int ymax = border().getMax().y(); - int rectx = _pass_z.width; - int recty = _pass_z.height; + int rectx = _pass_diffuse.width; + int recty = _pass_diffuse.height; float xfac = ((float)rectx) / ((float)(xmax - xmin)); float yfac = ((float)recty) / ((float)(ymax - ymin)); #if 0 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index a846ac697f0..e0c5cd5608e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -360,6 +360,12 @@ typedef struct bAddon { IDProperty *prop; /* User-Defined Properties on this Addon (for storing preferences) */ } bAddon; +typedef struct bPathCompare { + struct bPathCompare *next, *prev; + char path[768]; /* FILE_MAXDIR */ + char flag, pad[7]; +} bPathCompare; + typedef struct SolidLight { int flag, pad; float col[4], spec[4], vec[4]; @@ -412,6 +418,7 @@ typedef struct UserDef { struct ListBase keymaps DNA_DEPRECATED; /* deprecated in favor of user_keymaps */ struct ListBase user_keymaps; struct ListBase addons; + struct ListBase autoexec_paths; char keyconfigstr[64]; short undosteps; @@ -522,7 +529,12 @@ typedef enum eUserPref_Flag { USER_TXT_TABSTOSPACES_DISABLE = (1 << 25), USER_TOOLTIPS_PYTHON = (1 << 26), } eUserPref_Flag; - + +/* flag */ +typedef enum ePathCompare_Flag { + USER_PATHCMP_GLOB = (1 << 0), +} ePathCompare_Flag; + /* helper macro for checking frame clamping */ #define FRAMENUMBER_MIN_CLAMP(cfra) { \ if ((U.flag & USER_NONEGFRAMES) && (cfra < 0)) \ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 36da4e3508c..4513694e59d 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -138,6 +138,25 @@ EnumPropertyItem clip_editor_mode_items[] = { }; /* Actually populated dynamically trough a function, but helps for context-less access (e.g. doc, i18n...). */ +static EnumPropertyItem buttons_context_items[] = { + {BCONTEXT_SCENE, "SCENE", ICON_SCENE_DATA, "Scene", "Scene"}, + {BCONTEXT_RENDER, "RENDER", ICON_SCENE, "Render", "Render"}, + {BCONTEXT_RENDER_LAYER, "RENDER_LAYER", ICON_RENDERLAYERS, "Render Layers", "Render layers"}, + {BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"}, + {BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"}, + {BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Object constraints"}, + {BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifiers", "Object modifiers"}, + {BCONTEXT_DATA, "DATA", ICON_NONE, "Data", "Object data"}, + {BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone"}, + {BCONTEXT_BONE_CONSTRAINT, "BONE_CONSTRAINT", ICON_CONSTRAINT, "Bone Constraints", "Bone constraints"}, + {BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material"}, + {BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"}, + {BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"}, + {BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"}, + {0, NULL, 0, NULL, NULL} +}; + +/* Actually populated dynamically trough a function, but helps for context-less access (e.g. doc, i18n...). */ static EnumPropertyItem buttons_texture_context_items[] = { {SB_TEXC_MATERIAL, "MATERIAL", ICON_MATERIAL, "", "Show material textures"}, {SB_TEXC_WORLD, "WORLD", ICON_WORLD, "", "Show world textures"}, @@ -831,6 +850,76 @@ static void rna_SpaceProperties_context_set(PointerRNA *ptr, int value) sbuts->mainbuser = value; } +static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *C, PointerRNA *ptr, + PropertyRNA *UNUSED(prop), int *free) +{ + SpaceButs *sbuts = (SpaceButs *)(ptr->data); + EnumPropertyItem *item = NULL; + int totitem = 0; + + if (sbuts->pathflag & (1 << BCONTEXT_RENDER)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_RENDER); + } + + if (sbuts->pathflag & (1 << BCONTEXT_RENDER_LAYER)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_RENDER_LAYER); + } + + if (sbuts->pathflag & (1 << BCONTEXT_SCENE)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_SCENE); + } + + if (sbuts->pathflag & (1 << BCONTEXT_WORLD)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_WORLD); + } + + if (sbuts->pathflag & (1 << BCONTEXT_OBJECT)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_OBJECT); + } + + if (sbuts->pathflag & (1 << BCONTEXT_CONSTRAINT)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_CONSTRAINT); + } + + if (sbuts->pathflag & (1 << BCONTEXT_MODIFIER)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_MODIFIER); + } + + if (sbuts->pathflag & (1 << BCONTEXT_DATA)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_DATA); + (item + totitem - 1)->icon = sbuts->dataicon; + } + + if (sbuts->pathflag & (1 << BCONTEXT_BONE)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_BONE); + } + + if (sbuts->pathflag & (1 << BCONTEXT_BONE_CONSTRAINT)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_BONE_CONSTRAINT); + } + + if (sbuts->pathflag & (1 << BCONTEXT_MATERIAL)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_MATERIAL); + } + + if (sbuts->pathflag & (1 << BCONTEXT_TEXTURE)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_TEXTURE); + } + + if (sbuts->pathflag & (1 << BCONTEXT_PARTICLE)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_PARTICLE); + } + + if (sbuts->pathflag & (1 << BCONTEXT_PHYSICS)) { + RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_PHYSICS); + } + + RNA_enum_item_end(&item, &totitem); + *free = 1; + + return item; +} + static void rna_SpaceProperties_align_set(PointerRNA *ptr, int value) { SpaceButs *sbuts = (SpaceButs *)(ptr->data); @@ -2068,24 +2157,6 @@ static void rna_def_space_buttons(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static EnumPropertyItem buttons_context_items[] = { - {BCONTEXT_SCENE, "SCENE", ICON_SCENE, "Scene", "Scene"}, - {BCONTEXT_RENDER, "RENDER", ICON_SCENE_DATA, "Render", "Render"}, - {BCONTEXT_RENDER_LAYER, "RENDER_LAYER", ICON_RENDERLAYERS, "Render Layers", "Render Layers"}, - {BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"}, - {BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"}, - {BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Constraints"}, - {BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifiers", "Modifiers"}, - {BCONTEXT_DATA, "DATA", 0, "Data", "Data"}, - {BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone"}, - {BCONTEXT_BONE_CONSTRAINT, "BONE_CONSTRAINT", ICON_CONSTRAINT, "Bone Constraints", "Bone Constraints"}, - {BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material"}, - {BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"}, - {BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"}, - {BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"}, - {0, NULL, 0, NULL, NULL} - }; - static EnumPropertyItem align_items[] = { {BUT_HORIZONTAL, "HORIZONTAL", 0, "Horizontal", ""}, {BUT_VERTICAL, "VERTICAL", 0, "Vertical", ""}, @@ -2099,7 +2170,7 @@ static void rna_def_space_buttons(BlenderRNA *brna) prop = RNA_def_property(srna, "context", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mainb"); RNA_def_property_enum_items(prop, buttons_context_items); - RNA_def_property_enum_funcs(prop, NULL, "rna_SpaceProperties_context_set", NULL); + RNA_def_property_enum_funcs(prop, NULL, "rna_SpaceProperties_context_set", "rna_SpaceProperties_context_itemf"); RNA_def_property_ui_text(prop, "Context", "Type of active data to display and edit"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, NULL); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 347c57f9044..f34366a23c7 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -339,9 +339,9 @@ static bAddon *rna_userdef_addon_new(void) return bext; } -static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *bext_ptr) +static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *path_cmp_ptr) { - bAddon *bext = bext_ptr->data; + bAddon *bext = path_cmp_ptr->data; if (BLI_findindex(&U.addons, bext) == -1) { BKE_report(reports, RPT_ERROR, "Addon is no longer valid"); return; @@ -353,7 +353,26 @@ static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *bext_ptr) } BLI_freelinkN(&U.addons, bext); - RNA_POINTER_INVALIDATE(bext_ptr); + RNA_POINTER_INVALIDATE(path_cmp_ptr); +} + +static bPathCompare *rna_userdef_pathcompare_new(void) +{ + bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); + BLI_addtail(&U.autoexec_paths, path_cmp); + return path_cmp; +} + +static void rna_userdef_pathcompare_remove(ReportList *reports, PointerRNA *path_cmp_ptr) +{ + bPathCompare *path_cmp = path_cmp_ptr->data; + if (BLI_findindex(&U.autoexec_paths, path_cmp) == -1) { + BKE_report(reports, RPT_ERROR, "Addon is no longer valid"); + return; + } + + BLI_freelinkN(&U.autoexec_paths, path_cmp); + RNA_POINTER_INVALIDATE(path_cmp_ptr); } static void rna_userdef_temp_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) @@ -2733,6 +2752,25 @@ static void rna_def_userdef_addon(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_Addon_preferences_get", NULL, NULL, NULL); } +static void rna_def_userdef_pathcompare(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "PathCompare", NULL); + RNA_def_struct_sdna(srna, "bPathCompare"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Path Compare", "Match paths against this value"); + + prop = RNA_def_property(srna, "path", PROP_STRING, PROP_DIRPATH); + RNA_def_property_ui_text(prop, "Path", ""); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "use_glob", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_PATHCMP_GLOB); + RNA_def_property_ui_text(prop, "Use Wildcard", "Enable wildcard globbing"); +} + static void rna_def_userdef_addon_pref(BlenderRNA *brna) { StructRNA *srna; @@ -4027,6 +4065,32 @@ static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cpro RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } +static void rna_def_userdef_autoexec_path_collection(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "PathCompareCollection"); + srna = RNA_def_struct(brna, "PathCompareCollection", NULL); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Paths Compare", "Collection of paths"); + + func = RNA_def_function(srna, "new", "rna_userdef_pathcompare_new"); + RNA_def_function_flag(func, FUNC_NO_SELF); + RNA_def_function_ui_description(func, "Add a new addon"); + /* return type */ + parm = RNA_def_pointer(func, "pathcmp", "PathCompare", "", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_userdef_pathcompare_remove"); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove path"); + parm = RNA_def_pointer(func, "pathcmp", "PathCompare", "", ""); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); +} + void RNA_def_userdef(BlenderRNA *brna) { StructRNA *srna; @@ -4074,6 +4138,11 @@ void RNA_def_userdef(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Addon", ""); rna_def_userdef_addon_collection(brna, prop); + prop = RNA_def_property(srna, "autoexec_paths", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "autoexec_paths", NULL); + RNA_def_property_struct_type(prop, "PathCompare"); + RNA_def_property_ui_text(prop, "Autoexec Paths", ""); + rna_def_userdef_autoexec_path_collection(brna, prop); /* nested structs */ prop = RNA_def_property(srna, "view", PROP_POINTER, PROP_NONE); @@ -4113,6 +4182,7 @@ void RNA_def_userdef(BlenderRNA *brna) rna_def_userdef_system(brna); rna_def_userdef_addon(brna); rna_def_userdef_addon_pref(brna); + rna_def_userdef_pathcompare(brna); } diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 6bf3beec57b..b70ab7c15f2 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -955,7 +955,7 @@ static int operator_execute(bContext *C, wmOperator *op) } /* same as execute() but no return value */ -static int operator_check(bContext *C, wmOperator *op) +static bool operator_check(bContext *C, wmOperator *op) { extern FunctionRNA rna_Operator_check_func; @@ -963,7 +963,7 @@ static int operator_check(bContext *C, wmOperator *op) ParameterList list; FunctionRNA *func; void *ret; - int result; + bool result; RNA_pointer_create(NULL, op->type->ext.srna, op, &opr); func = &rna_Operator_check_func; /* RNA_struct_find_function(&opr, "check"); */ @@ -973,7 +973,7 @@ static int operator_check(bContext *C, wmOperator *op) op->type->ext.call(C, &opr, func, &list); RNA_parameter_get_lookup(&list, "result", &ret); - result = *(int *)ret; + result = (*(int *)ret) != 0; RNA_parameter_list_free(&list); diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index d877932b81d..e37fc56d08c 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -49,7 +49,7 @@ #include "DNA_object_types.h" -static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Object *UNUSED(ob)) +static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd) { DerivedMesh *result; BMesh *bm; @@ -97,7 +97,8 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj result = CDDM_from_bmesh(bm, TRUE); BM_mesh_free(bm); - + + result->dirty |= DM_DIRTY_NORMALS; return result; } @@ -119,25 +120,16 @@ static void copyData(ModifierData *md, ModifierData *target) temd->flags = emd->flags; } -static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd, - Object *ob, DerivedMesh *dm) -{ - if (!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))) - return dm; - - return doEdgeSplit(dm, emd, ob); -} - -static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, +static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), DerivedMesh *dm, ModifierApplyFlag UNUSED(flag)) { DerivedMesh *result; EdgeSplitModifierData *emd = (EdgeSplitModifierData *) md; - result = edgesplitModifier_do(emd, ob, derivedData); + if (!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))) + return dm; - if (result != derivedData) - result->dirty |= DM_DIRTY_NORMALS; + result = doEdgeSplit(dm, emd); return result; } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 189c30b02e8..72b54e2f1f7 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -112,6 +112,7 @@ bool WM_is_draw_triple(struct wmWindow *win); /* files */ +void WM_file_autoexec_init(const char *filepath); void WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports); void WM_autosave_init(struct wmWindowManager *wm); void WM_recover_last_session(struct bContext *C, struct ReportList *reports); @@ -193,7 +194,7 @@ int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const str int WM_operator_confirm (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); /* invoke callback, file selector "filepath" unset + exec */ int WM_operator_filesel (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); -int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format); +bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format); /* poll callback, context checks */ int WM_operator_winactive (struct bContext *C); /* invoke callback, exec + redo popup */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index cb060077166..cd3899897a1 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -531,7 +531,7 @@ typedef struct wmOperatorType { * is changed. It can correct its own properties or report errors for * invalid settings in exceptional cases. * Boolean return value, True denotes a change has been made and to redraw */ - int (*check)(struct bContext *, struct wmOperator *); + bool (*check)(struct bContext *, struct wmOperator *); /* for modal temporary operators, initially invoke is called. then * any further events are handled in modal. if the operation is diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index b6aecf120cc..f4b50667b2f 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -70,6 +70,7 @@ #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" +#include "BKE_autoexec.h" #include "BKE_blender.h" #include "BKE_context.h" #include "BKE_depsgraph.h" @@ -364,6 +365,21 @@ static int wm_read_exotic(Scene *UNUSED(scene), const char *name) return retval; } +void WM_file_autoexec_init(const char *filepath) +{ + if (G.f & G_SCRIPT_OVERRIDE_PREF) { + return; + } + + if (G.f & G_SCRIPT_AUTOEXEC) { + char path[FILE_MAX]; + BLI_split_dir_part(filepath, path, sizeof(path)); + if (BKE_autoexec_match(path)) { + G.f &= ~G_SCRIPT_AUTOEXEC; + } + } +} + void WM_file_read(bContext *C, const char *filepath, ReportList *reports) { int retval; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 3d4bd2a1bc6..e71be6052d0 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -60,6 +60,7 @@ #include "BLO_readfile.h" +#include "BKE_autoexec.h" #include "BKE_blender.h" #include "BKE_brush.h" #include "BKE_context.h" @@ -1038,7 +1039,7 @@ int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *UNUSED(event } } -int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format) +bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format) { PropertyRNA *prop; char filepath[FILE_MAX]; @@ -1868,6 +1869,47 @@ static void WM_OT_save_homefile(wmOperatorType *ot) ot->poll = WM_operator_winactive; } +static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ + bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); + BLI_addtail(&U.autoexec_paths, path_cmp); + return OPERATOR_FINISHED; +} + +static void WM_OT_userpref_autoexec_path_add(wmOperatorType *ot) +{ + ot->name = "Add Autoexec Path"; + ot->idname = "WM_OT_userpref_autoexec_path_add"; + + ot->exec = wm_userpref_autoexec_add_exec; + ot->poll = WM_operator_winactive; + + ot->flag = OPTYPE_INTERNAL; +} + +static int wm_userpref_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op) +{ + const int index = RNA_int_get(op->ptr, "index"); + bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index); + if (path_cmp) { + BLI_freelinkN(&U.autoexec_paths, path_cmp); + } + return OPERATOR_FINISHED; +} + +static void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot) +{ + ot->name = "Remove Autoexec Path"; + ot->idname = "WM_OT_userpref_autoexec_path_remove"; + + ot->exec = wm_userpref_autoexec_remove_exec; + ot->poll = WM_operator_winactive; + + ot->flag = OPTYPE_INTERNAL; + + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); +} + static void WM_OT_save_userpref(wmOperatorType *ot) { ot->name = "Save User Settings"; @@ -1916,6 +1958,12 @@ static void WM_OT_read_factory_settings(wmOperatorType *ot) /* *************** open file **************** */ +/* currently fits in a pointer */ +struct FileRuntime { + bool is_untrusted; +}; + + static void open_set_load_ui(wmOperator *op, bool use_prefs) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "load_ui"); @@ -1960,6 +2008,7 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U RNA_string_set(op->ptr, "filepath", openname); open_set_load_ui(op, true); open_set_use_scripts(op, true); + op->customdata = NULL; WM_event_add_fileselect(C, op); @@ -1990,11 +2039,65 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op) /* do it before for now, but is this correct with multiple windows? */ WM_event_add_notifier(C, NC_WINDOW, NULL); + /* autoexec is already set correctly for invoke() for exec() though we need to initialize */ + if (!RNA_struct_property_is_set(op->ptr, "use_scripts")) { + WM_file_autoexec_init(path); + } WM_file_read(C, path, op->reports); - + return OPERATOR_FINISHED; } +static bool wm_open_mainfile_check(bContext *UNUSED(C), wmOperator *op) +{ + struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_scripts"); + bool is_untrusted = false; + char path[FILE_MAX]; + char *lslash; + + RNA_string_get(op->ptr, "filepath", path); + + /* get the dir */ + lslash = (char *)BLI_last_slash(path); + if (lslash) *(lslash + 1) = '\0'; + + if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) { + if (BKE_autoexec_match(path) == true) { + RNA_property_boolean_set(op->ptr, prop, false); + is_untrusted = true; + } + } + + if (file_info) { + file_info->is_untrusted = is_untrusted; + } + + return is_untrusted; +} + +static void wm_open_mainfile_ui(bContext *UNUSED(C), wmOperator *op) +{ + struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; + uiLayout *layout = op->layout; + uiLayout *col = op->layout; + const char *autoexec_text = NULL; + + uiItemR(layout, op->ptr, "load_ui", 0, NULL, ICON_NONE); + + col = uiLayoutColumn(layout, false); + if (file_info->is_untrusted) { + autoexec_text = "Trusted Source [Untrusted Path]"; + uiLayoutSetActive(col, false); + uiLayoutSetEnabled(col, false); + } + else { + autoexec_text = "Trusted Source"; + } + + uiItemR(col, op->ptr, "use_scripts", 0, autoexec_text, ICON_NONE); +} + static void WM_OT_open_mainfile(wmOperatorType *ot) { ot->name = "Open Blender File"; @@ -2003,6 +2106,8 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) ot->invoke = wm_open_mainfile_invoke; ot->exec = wm_open_mainfile_exec; + ot->check = wm_open_mainfile_check; + ot->ui = wm_open_mainfile_ui; /* ommit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_OPENFILE, @@ -2233,6 +2338,7 @@ void WM_recover_last_session(bContext *C, ReportList *reports) WM_event_add_notifier(C, NC_WINDOW, NULL); /* load file */ + WM_file_autoexec_init(filename); WM_file_read(C, filename, reports); G.fileflags &= ~G_FILE_RECOVER; @@ -2279,6 +2385,7 @@ static int wm_recover_auto_save_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_WINDOW, NULL); /* load file */ + WM_file_autoexec_init(path); WM_file_read(C, path, op->reports); G.fileflags &= ~G_FILE_RECOVER; @@ -2400,7 +2507,7 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) } /* function used for WM_OT_save_mainfile too */ -static int blend_save_check(bContext *UNUSED(C), wmOperator *op) +static bool blend_save_check(bContext *UNUSED(C), wmOperator *op) { char filepath[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filepath); @@ -4044,6 +4151,8 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_read_factory_settings); WM_operatortype_append(WM_OT_save_homefile); WM_operatortype_append(WM_OT_save_userpref); + WM_operatortype_append(WM_OT_userpref_autoexec_path_add); + WM_operatortype_append(WM_OT_userpref_autoexec_path_remove); WM_operatortype_append(WM_OT_window_fullscreen_toggle); WM_operatortype_append(WM_OT_quit_blender); WM_operatortype_append(WM_OT_open_mainfile); @@ -4101,13 +4210,12 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_SELECT); -#if 0 /* Durien guys like this :S */ + /* left mouse shift for deselect too */ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_SHIFT, 0, GESTURE_MODAL_DESELECT); WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_SHIFT, 0, GESTURE_MODAL_NOP); -#else + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_DESELECT); // default 2.4x WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, 0, 0, GESTURE_MODAL_NOP); // default 2.4x -#endif WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, 0, 0, GESTURE_MODAL_NOP); @@ -4175,21 +4283,22 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) /* items for modal map */ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, GESTURE_MODAL_CANCEL); + /* Note: cancel only on press otherwise you cannot map this to RMB-gesture */ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, GESTURE_MODAL_CANCEL); - - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_BEGIN); - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_SELECT); WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_SELECT); -#if 0 /* Durian guys like this */ + /* allow shift leftclick for deselect too */ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_SHIFT, 0, GESTURE_MODAL_BEGIN); WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_SHIFT, 0, GESTURE_MODAL_DESELECT); -#else + + /* any unhandled leftclick release handles select */ + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_BEGIN); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_SELECT); + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_BEGIN); WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, 0, 0, GESTURE_MODAL_DESELECT); -#endif - + /* assign map to operators */ WM_modalkeymap_assign(keymap, "ACTION_OT_select_border"); WM_modalkeymap_assign(keymap, "ANIM_OT_channels_select_border"); diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 7c744d10d63..8ff4ec445ea 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -488,18 +488,16 @@ elseif(WIN32) ) if(WITH_PYTHON) - set_lib_path(PYLIB "python") - string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) install( - FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}.dll + FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll DESTINATION ${TARGETDIR} CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel ) install( - FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll + FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll DESTINATION ${TARGETDIR} CONFIGURATIONS Debug ) diff --git a/source/creator/creator.c b/source/creator/creator.c index 302467c6b3d..817bc4fcf60 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1262,6 +1262,7 @@ static int load_file(int UNUSED(argc), const char **argv, void *data) * a file - this should do everything a 'load file' does */ ReportList reports; BKE_reports_init(&reports, RPT_PRINT); + WM_file_autoexec_init(filename); WM_file_read(C, filename, &reports); BKE_reports_clear(&reports); } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 3abc129521e..f02e842ad2e 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -521,10 +521,23 @@ void KX_KetsjiEngine::EndFrame() RenderDebugProperties(); } - m_average_framerate = m_logger->GetAverage(); - if (m_average_framerate < 1e-6) - m_average_framerate = 1e-6; - m_average_framerate = 1.0/m_average_framerate; + double tottime = m_logger->GetAverage(), time; + if (tottime < 1e-6) + tottime = 1e-6; + +#ifdef WITH_PYTHON + for (int i = tc_first; i < tc_numCategories; ++i) { + time = m_logger->GetAverage((KX_TimeCategory)i); + PyObject *val = PyTuple_New(2); + PyTuple_SetItem(val, 0, PyFloat_FromDouble(time*1000.f)); + PyTuple_SetItem(val, 1, PyFloat_FromDouble(time/tottime * 100.f)); + + PyDict_SetItemString(m_pyprofiledict, m_profileLabels[i], val); + Py_DECREF(val); + } +#endif + + m_average_framerate = 1.0/tottime; // Go to next profiling measurement, time spend after this call is shown in the next frame. m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds()); @@ -1526,15 +1539,6 @@ void KX_KetsjiEngine::RenderDebugProperties() m_rendertools->RenderBox2D(xcoord + (int)(2.2 * profile_indent), ycoord, m_canvas->GetWidth(), m_canvas->GetHeight(), time/tottime); ycoord += const_ysize; - -#ifdef WITH_PYTHON - PyObject *val = PyTuple_New(2); - PyTuple_SetItem(val, 0, PyFloat_FromDouble(time*1000.f)); - PyTuple_SetItem(val, 1, PyFloat_FromDouble(time/tottime * 100.f)); - - PyDict_SetItemString(m_pyprofiledict, m_profileLabels[j], val); - Py_DECREF(val); -#endif } } // Add the ymargin for titles below the other section of debug info @@ -1645,10 +1649,10 @@ void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overla } else { if (overlay) { - m_addingOverlayScenes.insert(scenename); + m_addingOverlayScenes.push_back(scenename); } else { - m_addingBackgroundScenes.insert(scenename); + m_addingBackgroundScenes.push_back(scenename); } } } @@ -1660,7 +1664,7 @@ void KX_KetsjiEngine::RemoveScene(const STR_String& scenename) { if (FindScene(scenename)) { - m_removingScenes.insert(scenename); + m_removingScenes.push_back(scenename); } else { @@ -1675,7 +1679,7 @@ void KX_KetsjiEngine::RemoveScheduledScenes() { if (m_removingScenes.size()) { - set<STR_String>::iterator scenenameit; + vector<STR_String>::iterator scenenameit; for (scenenameit=m_removingScenes.begin();scenenameit != m_removingScenes.end();scenenameit++) { STR_String scenename = *scenenameit; @@ -1721,7 +1725,7 @@ KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename) void KX_KetsjiEngine::AddScheduledScenes() { - set<STR_String>::iterator scenenameit; + vector<STR_String>::iterator scenenameit; if (m_addingOverlayScenes.size()) { @@ -1757,7 +1761,7 @@ void KX_KetsjiEngine::AddScheduledScenes() void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene) { - m_replace_scenes.insert(std::make_pair(oldscene,newscene)); + m_replace_scenes.push_back(std::make_pair(oldscene,newscene)); } // replace scene is not the same as removing and adding because the @@ -1768,7 +1772,7 @@ void KX_KetsjiEngine::ReplaceScheduledScenes() { if (m_replace_scenes.size()) { - set<pair<STR_String,STR_String> >::iterator scenenameit; + vector<pair<STR_String,STR_String> >::iterator scenenameit; for (scenenameit = m_replace_scenes.begin(); scenenameit != m_replace_scenes.end(); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 0d7e41d7568..3cba3558db3 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -41,7 +41,6 @@ #include "KX_Python.h" #include "KX_WorldInfo.h" #include <vector> -#include <set> class KX_TimeCategoryLogger; @@ -88,13 +87,13 @@ private: class KX_Dome* m_dome; // dome stereo mode /** Lists of scenes scheduled to be removed at the end of the frame. */ - std::set<STR_String> m_removingScenes; + std::vector<STR_String> m_removingScenes; /** Lists of overley scenes scheduled to be added at the end of the frame. */ - std::set<STR_String> m_addingOverlayScenes; + std::vector<STR_String> m_addingOverlayScenes; /** Lists of background scenes scheduled to be added at the end of the frame. */ - std::set<STR_String> m_addingBackgroundScenes; + std::vector<STR_String> m_addingBackgroundScenes; /** Lists of scenes scheduled to be replaced at the end of the frame. */ - std::set<std::pair<STR_String,STR_String> > m_replace_scenes; + std::vector<std::pair<STR_String,STR_String> > m_replace_scenes; /* The current list of scenes. */ KX_SceneList m_scenes; |