diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2014-10-23 17:12:28 +0400 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2014-10-23 17:12:28 +0400 |
commit | 9ff1ebed52e0f858a395eeea4caf89304e068b2d (patch) | |
tree | b05d0f4b229de61b088a128ad412dd7bba347928 /source/blender/blenkernel/intern | |
parent | a2ed11c6eeab5fab8cb81e32e1c68fdafdd5dbbc (diff) | |
parent | eaaeae469968c5c78a5d7e6d202f1af00b382a79 (diff) |
Merge remote-tracking branch 'origin/master' into soc-2014-fluid
Conflicts:
.gitignore
intern/cycles/CMakeLists.txt
source/blender/blenkernel/intern/smoke.c
source/blender/python/intern/bpy_interface.c
source/creator/CMakeLists.txt
Diffstat (limited to 'source/blender/blenkernel/intern')
90 files changed, 5018 insertions, 2487 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 6cda0a1bc33..623fb50b62c 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -119,7 +119,7 @@ static void _ehash_insert(EHash *eh, EHEntry *entry) eh->buckets[hash] = entry; eh->numEntries++; - if (eh->numEntries > (numBuckets * 3)) { + if (UNLIKELY(eh->numEntries > (numBuckets * 3))) { EHEntry **oldBuckets = eh->buckets; eh->curSize = kHashSizes[++eh->curSizeIdx]; @@ -1274,7 +1274,7 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV CCGFace *f = NULL, *fNew; int j, k, topologyChanged = 0; - if (numVerts > ss->lenTempArrays) { + if (UNLIKELY(numVerts > ss->lenTempArrays)) { ss->lenTempArrays = (numVerts < ss->lenTempArrays * 2) ? ss->lenTempArrays * 2 : numVerts; ss->tempVerts = MEM_reallocN(ss->tempVerts, sizeof(*ss->tempVerts) * ss->lenTempArrays); ss->tempEdges = MEM_reallocN(ss->tempEdges, sizeof(*ss->tempEdges) * ss->lenTempArrays); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 5339c3fc5d5..81c03d8081b 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -37,12 +37,14 @@ #include "DNA_cloth_types.h" #include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "BLI_blenlib.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_linklist.h" @@ -70,11 +72,10 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); #include "BLI_sys_types.h" /* for intptr_t support */ -#include "GL/glew.h" - #include "GPU_buffers.h" #include "GPU_draw.h" #include "GPU_extensions.h" +#include "GPU_glew.h" #include "GPU_material.h" /* very slow! enable for testing only! */ @@ -501,11 +502,36 @@ void DM_update_materials(DerivedMesh *dm, Object *ob) dm->mat = MEM_callocN(totmat * sizeof(*dm->mat), "DerivedMesh.mat"); - for (i = 1; i < totmat; i++) { - dm->mat[i] = give_current_material(ob, i); + /* we leave last material as empty - rationale here is being able to index + * the materials by using the mf->mat_nr directly and leaving the last + * material as NULL in case no materials exist on mesh, so indexing will not fail */ + for (i = 0; i < totmat - 1; i++) { + dm->mat[i] = give_current_material(ob, i + 1); } } +MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr) +{ + MTFace *tf_base; + + BLI_assert(mat_nr < dm->totmat); + + if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot && + dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname) + { + tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, + dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname); + /* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material + * texture slot.*/ + if (!tf_base) + tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE); + } + else { + tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE); + } + + return tf_base; +} void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) { @@ -615,7 +641,8 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) MEM_freeN(me->mselect); } - *me = tmp; + /* skip the listbase */ + MEMCPY_STRUCT_OFS(me, &tmp, id.prev); } void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb) @@ -1107,7 +1134,7 @@ static void weightpaint_color(unsigned char r_col[4], DMWeightColorInfo *dm_wcin static void calc_weightpaint_vert_color( unsigned char r_col[4], - MDeformVert *dv, + const MDeformVert *dv, DMWeightColorInfo *dm_wcinfo, const int defbase_tot, const int defbase_act, const bool *defbase_sel, const int defbase_sel_tot, @@ -1122,7 +1149,7 @@ static void calc_weightpaint_vert_color( bool was_a_nonzero = false; unsigned int i; - MDeformWeight *dw = dv->dw; + const MDeformWeight *dw = dv->dw; for (i = dv->totweight; i != 0; i--, dw++) { /* in multipaint, get the average if auto normalize is inactive * get the sum if it is active */ @@ -1213,14 +1240,15 @@ static void calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const d } } else { - int col_i; + unsigned char col[4]; if (draw_flag & (CALC_WP_GROUP_USER_ACTIVE | CALC_WP_GROUP_USER_ALL)) { - col_i = 0; + copy_v3_v3_char((char *)col, dm_wcinfo->alert_color); + col[3] = 255; } else { - weightpaint_color((unsigned char *)&col_i, dm_wcinfo, 0.0f); + weightpaint_color(col, dm_wcinfo, 0.0f); } - fill_vn_i((int *)r_wtcol_v, numVerts, col_i); + fill_vn_i((int *)r_wtcol_v, numVerts, *((int *)col)); } } @@ -1994,9 +2022,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D previewmd = modifiers_getLastPreview(scene, md, required_mode); /* even if the modifier doesn't need the data, to make a preview it may */ if (previewmd) { - if (do_mod_wmcol) { - previewmask = CD_MASK_MDEFORMVERT; - } + previewmask = CD_MASK_MDEFORMVERT; } } @@ -2472,6 +2498,28 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em) return getEditDerivedBMesh(em, obedit, NULL); } +/***/ + +/* get derived mesh from an object, using editbmesh if available. */ +DerivedMesh *object_get_derived_final(Object *ob, const bool for_render) +{ + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + + if (for_render) { + /* TODO(sergey): use proper derived render here in the future. */ + return ob->derivedFinal; + } + + if (em) { + DerivedMesh *dm = em->derivedFinal; + return dm; + } + + return ob->derivedFinal; +} + + /* UNUSED */ #if 0 @@ -2532,6 +2580,44 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) #endif +/* same as above but for vert coords */ +typedef struct { + float (*vertexcos)[3]; + BLI_bitmap *vertex_visit; +} MappedUserData; + +static void make_vertexcos__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +{ + MappedUserData *mappedData = (MappedUserData *)userData; + + if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) { + /* we need coord from prototype vertex, not from copies, + * assume they stored in the beginning of vertex array stored in DM + * (mirror modifier for eg does this) */ + copy_v3_v3(mappedData->vertexcos[index], co); + BLI_BITMAP_ENABLE(mappedData->vertex_visit, index); + } +} + +void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int totcos) +{ + if (dm->foreachMappedVert) { + MappedUserData userData; + memset(r_cos, 0, sizeof(*r_cos) * totcos); + userData.vertexcos = r_cos; + userData.vertex_visit = BLI_BITMAP_NEW(totcos, "vertexcos flags"); + dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP); + MEM_freeN(userData.vertex_visit); + } + else { + int i; + for (i = 0; i < totcos; i++) { + dm->getVertCo(dm, i, r_cos[i]); + } + } +} + /* ******************* GLSL ******************** */ typedef struct { @@ -3089,7 +3175,7 @@ static void navmesh_drawColored(DerivedMesh *dm) static void navmesh_DM_drawFacesTex(DerivedMesh *dm, DMSetDrawOptionsTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag UNUSED(flag)) { (void) setDrawOptions; (void) compareDrawOptions; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 3219219bee5..c6dcca576fb 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -315,7 +315,7 @@ bActionGroup *action_groups_add_new(bAction *act, const char name[]) void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve) { /* sanity checks */ - if (ELEM3(NULL, act, agrp, fcurve)) + if (ELEM(NULL, act, agrp, fcurve)) return; /* if no channels anywhere, just add to two lists at the same time */ @@ -417,7 +417,7 @@ void action_groups_remove_channel(bAction *act, FCurve *fcu) bActionGroup *BKE_action_group_find_name(bAction *act, const char name[]) { /* sanity checks */ - if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0)) + if (ELEM(NULL, act, act->groups.first, name) || (name[0] == 0)) return NULL; /* do string comparisons */ @@ -526,7 +526,7 @@ bPoseChannel *BKE_pose_channel_active(Object *ob) bArmature *arm = (ob) ? ob->data : NULL; bPoseChannel *pchan; - if (ELEM3(NULL, ob, ob->pose, arm)) { + if (ELEM(NULL, ob, ob->pose, arm)) { return NULL; } @@ -952,52 +952,52 @@ void framechange_poses_clear_unkeyed(void) /* ************************** Bone Groups ************************** */ -/* Adds a new bone-group */ -void BKE_pose_add_group(Object *ob) +/* Adds a new bone-group (name may be NULL) */ +bActionGroup *BKE_pose_add_group(bPose *pose, const char *name) { - bPose *pose = (ob) ? ob->pose : NULL; bActionGroup *grp; - if (ELEM(NULL, ob, ob->pose)) - return; + if (!name) { + name = DATA_("Group"); + } grp = MEM_callocN(sizeof(bActionGroup), "PoseGroup"); - BLI_strncpy(grp->name, DATA_("Group"), sizeof(grp->name)); + BLI_strncpy(grp->name, name, sizeof(grp->name)); BLI_addtail(&pose->agroups, grp); - BLI_uniquename(&pose->agroups, grp, DATA_("Group"), '.', offsetof(bActionGroup, name), sizeof(grp->name)); + BLI_uniquename(&pose->agroups, grp, name, '.', offsetof(bActionGroup, name), sizeof(grp->name)); pose->active_group = BLI_countlist(&pose->agroups); + + return grp; } -/* Remove the active bone-group */ -void BKE_pose_remove_group(Object *ob) +/* Remove the given bone-group (expects 'virtual' index (+1 one, used by active_group etc.)) + * index might be invalid ( < 1), in which case it will be find from grp. */ +void BKE_pose_remove_group(bPose *pose, bActionGroup *grp, const int index) { - bPose *pose = (ob) ? ob->pose : NULL; - bActionGroup *grp = NULL; bPoseChannel *pchan; + int idx = index; - /* sanity checks */ - if (ELEM(NULL, ob, pose)) - return; - if (pose->active_group <= 0) - return; + if (idx < 1) { + idx = BLI_findindex(&pose->agroups, grp) + 1; + } - /* get group to remove */ - grp = BLI_findlink(&pose->agroups, pose->active_group - 1); - if (grp) { - /* adjust group references (the trouble of using indices!): - * - firstly, make sure nothing references it - * - also, make sure that those after this item get corrected - */ - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - if (pchan->agrp_index == pose->active_group) - pchan->agrp_index = 0; - else if (pchan->agrp_index > pose->active_group) - pchan->agrp_index--; - } - - /* now, remove it from the pose */ - BLI_freelinkN(&pose->agroups, grp); + BLI_assert(idx > 0); + + /* adjust group references (the trouble of using indices!): + * - firstly, make sure nothing references it + * - also, make sure that those after this item get corrected + */ + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->agrp_index == idx) + pchan->agrp_index = 0; + else if (pchan->agrp_index > idx) + pchan->agrp_index--; + } + + /* now, remove it from the pose */ + BLI_freelinkN(&pose->agroups, grp); + if (pose->active_group >= idx) { pose->active_group--; if (pose->active_group < 0 || BLI_listbase_is_empty(&pose->agroups)) { pose->active_group = 0; @@ -1005,6 +1005,18 @@ void BKE_pose_remove_group(Object *ob) } } +/* Remove the indexed bone-group (expects 'virtual' index (+1 one, used by active_group etc.)) */ +void BKE_pose_remove_group_index(bPose *pose, const int index) +{ + bActionGroup *grp = NULL; + + /* get group to remove */ + grp = BLI_findlink(&pose->agroups, index - 1); + if (grp) { + BKE_pose_remove_group(pose, grp, index); + } +} + /* ************** F-Curve Utilities for Actions ****************** */ /* Check if the given action has any keyframes */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 4cce69dc824..aff99d3e1bf 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -125,12 +125,13 @@ void animviz_free_motionpath(bMotionPath *mpath) /* ------------------- */ -/* Setup motion paths for the given data - * - Only used when explicitly calculating paths on bones which may/may not be consider already +/** + * Setup motion paths for the given data. + * \note Only used when explicitly calculating paths on bones which may/may not be consider already * - * < scene: current scene (for frame ranges, etc.) - * < ob: object to add paths for (must be provided) - * < pchan: posechannel to add paths for (optional; if not provided, object-paths are assumed) + * \param scene Current scene (for frame ranges, etc.) + * \param ob Object to add paths for (must be provided) + * \param pchan Posechannel to add paths for (optional; if not provided, object-paths are assumed) */ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Object *ob, bPoseChannel *pchan) { @@ -512,7 +513,7 @@ void calc_curvepath(Object *ob, ListBase *nurbs) dist = (float *)MEM_mallocN(sizeof(float) * (tot + 1), "calcpathdist"); /* all lengths in *dist */ - bevp = bevpfirst = (BevPoint *)(bl + 1); + bevp = bevpfirst = bl->bevpoints; fp = dist; *fp = 0.0f; for (a = 0; a < tot; a++) { diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 6a9c4c851b2..2fb832dc72d 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -51,18 +51,23 @@ #include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" #include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_nla.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_library.h" #include "BKE_report.h" +#include "BKE_texture.h" #include "RNA_access.h" @@ -244,7 +249,7 @@ void BKE_free_animdata(ID *id) } } -/* Freeing -------------------------------------------- */ +/* Copying -------------------------------------------- */ /* Make a copy of the given AnimData - to be used when copying datablocks */ AnimData *BKE_copy_animdata(AnimData *adt, const bool do_action) @@ -381,10 +386,12 @@ void BKE_relink_animdata(AnimData *adt) /* Sub-ID Regrouping ------------------------------------------- */ -/* helper heuristic for determining if a path is compatible with the basepath - * < path: (str) full RNA-path from some data (usually an F-Curve) to compare - * < basepath: (str) shorter path fragment to look for - * > returns (bool) whether there is a match +/** + * Helper heuristic for determining if a path is compatible with the basepath + * + * \param path Full RNA-path from some data (usually an F-Curve) to compare + * \param basepath Shorter path fragment to look for + * \return Whether there is a match */ static bool animpath_matches_basepath(const char path[], const char basepath[]) { @@ -403,7 +410,7 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha FCurve *fcu, *fcn = NULL; /* sanity checks */ - if (ELEM3(NULL, srcAct, dstAct, basepath)) { + if (ELEM(NULL, srcAct, dstAct, basepath)) { if (G.debug & G_DEBUG) { printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n", (void *)srcAct, (void *)dstAct, (void *)basepath); @@ -549,6 +556,74 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths } } +/** + * Temporary wrapper for driver operators for buttons to make it easier to create + * such drivers by rerouting all paths through the active object instead so that + * they will get picked up by the dependency system. + * + * \param C Context pointer - for getting active data + * \param[in,out] ptr RNA pointer for property's datablock. May be modified as result of path remapping. + * \param prop RNA definition of property to add for + * \return MEM_alloc'd string representing the path to the property from the given #PointerRNA + */ +char *BKE_animdata_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *prop, char *base_path) +{ + ID *id = (ID *)ptr->id.data; + ScrArea *sa = CTX_wm_area(C); + + /* get standard path which may be extended */ + char *basepath = base_path ? base_path : RNA_path_from_ID_to_property(ptr, prop); + char *path = basepath; /* in case no remapping is needed */ + + /* Remapping will only be performed in the Properties Editor, as only this + * restricts the subspace of options to the 'active' data (a manageable state) + */ + /* TODO: watch out for pinned context? */ + if ((sa) && (sa->spacetype == SPACE_BUTS)) { + Object *ob = CTX_data_active_object(C); + + if (ob && id) { + /* only id-types which can be remapped to go through objects should be considered */ + switch (GS(id->name)) { + case ID_TE: /* textures */ + { + Material *ma = give_current_material(ob, ob->actcol); + Tex *tex = give_current_material_texture(ma); + + /* assumes: texture will only be shown if it is active material's active texture it's ok */ + if ((ID *)tex == id) { + char name_esc_ma[(sizeof(ma->id.name) - 2) * 2]; + char name_esc_tex[(sizeof(tex->id.name) - 2) * 2]; + + BLI_strescape(name_esc_ma, ma->id.name + 2, sizeof(name_esc_ma)); + BLI_strescape(name_esc_tex, tex->id.name + 2, sizeof(name_esc_tex)); + + /* create new path */ + // TODO: use RNA path functions to construct step by step instead? + // FIXME: maybe this isn't even needed anymore... + path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", + name_esc_ma, name_esc_tex, basepath); + + /* free old one */ + if (basepath != base_path) + MEM_freeN(basepath); + } + break; + } + } + + /* fix RNA pointer, as we've now changed the ID root by changing the paths */ + if (basepath != path) { + /* rebase provided pointer so that it starts from object... */ + RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr); + } + } + } + + /* the path should now have been corrected for use */ + return path; +} + /* Path Validation -------------------------------------------- */ /* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */ @@ -984,8 +1059,8 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha AnimData *adt = BKE_animdata_from_id(id); \ NtId_Type *ntp = (NtId_Type *)id; \ if (ntp->nodetree) { \ - AnimData *adt2 = BKE_animdata_from_id((ID *)ntp); \ - BKE_animdata_fix_paths_rename((ID *)ntp, adt2, ref_id, prefix, oldName, newName, 0, 0, 1); \ + AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \ + BKE_animdata_fix_paths_rename((ID *)ntp->nodetree, adt2, ref_id, prefix, oldName, newName, 0, 0, 1); \ } \ BKE_animdata_fix_paths_rename(id, adt, ref_id, prefix, oldName, newName, 0, 0, 1); \ } (void)0 @@ -1060,7 +1135,7 @@ KS_Path *BKE_keyingset_find_path(KeyingSet *ks, ID *id, const char group_name[], KS_Path *ksp; /* sanity checks */ - if (ELEM3(NULL, ks, rna_path, id)) + if (ELEM(NULL, ks, rna_path, id)) return NULL; /* loop over paths in the current KeyingSet, finding the first one where all settings match @@ -1166,7 +1241,7 @@ KS_Path *BKE_keyingset_add_path(KeyingSet *ks, ID *id, const char group_name[], /* just copy path info */ /* TODO: should array index be checked too? */ - ksp->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); + ksp->rna_path = BLI_strdup(rna_path); ksp->array_index = array_index; /* store flags */ @@ -2232,9 +2307,12 @@ void nladata_flush_channels(ListBase *channels) /* ---------------------- */ -/* NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels" - * ! This is exported so that keyframing code can use this for make use of it for anim layers support - * > echannels: (list<NlaEvalChannels>) evaluation channels with calculated values +/** + * NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels" + * + * \note This is exported so that keyframing code can use this for make use of it for anim layers support + * + * \param[out] echannels Evaluation channels with calculated values */ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData *adt, float ctime) { @@ -2333,6 +2411,17 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData /* 3. free temporary evaluation data that's not used elsewhere */ BLI_freelistN(&estrips); + + /* Tag ID as updated so render engines will recognize changes in data + * which is animated but doesn't have actions. + */ + if (ptr->id.data != NULL) { + ID *id = ptr->id.data; + if (!(id->flag & LIB_ANIM_NO_RECALC)) { + id->flag |= LIB_ID_RECALC; + DAG_id_type_tag(G.main, GS(id->name)); + } + } } /* NLA Evaluation function (mostly for use through do_animdata) @@ -2387,7 +2476,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) /* Overview of how this system works: * 1) Depsgraph sorts data as necessary, so that data is in an order that means - * that all dependencies are resolved before dependants. + * that all dependencies are resolved before dependents. * 2) All normal animation is evaluated, so that drivers have some basis values to * work with * a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index fda252e81fd..bb05b5de8a6 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -505,7 +505,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB invert_m3_m3(imat3, mat3); mul_m3_m3m3(mat3, result, imat3); /* the matrix transforming vec_roll to desired roll */ - roll1 = (float)atan2(mat3[2][0], mat3[2][2]); + roll1 = atan2f(mat3[2][0], mat3[2][2]); } } else { @@ -543,7 +543,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB invert_m3_m3(imat3, mat3); mul_m3_m3m3(mat3, imat3, result); /* the matrix transforming vec_roll to desired roll */ - roll2 = (float)atan2(mat3[2][0], mat3[2][2]); + roll2 = atan2f(mat3[2][0], mat3[2][2]); /* and only now negate handle */ mul_v3_fl(h2, -hlength2); @@ -574,7 +574,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB if (do_scale) { /* correct for scaling when this matrix is used in scaled space */ - mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL); + mul_m4_series(result_array[a].mat, iscalemat, result_array[a].mat, scalemat); } } } @@ -622,8 +622,7 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info invert_m4_m4(tmat, b_bone_rest[a].mat); - mul_serie_m4(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat, - NULL, NULL, NULL); + mul_m4_series(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat); if (use_quaternion) mat4_to_dquat(&b_bone_dual_quats[a], bone->arm_mat, b_bone_mats[a + 1].mat); @@ -1042,7 +1041,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float if (!use_quaternion) /* quaternion already is scale corrected */ mul_m3_fl(smat, armature_weight / contrib); - mul_serie_m3(defMats[i], tmpmat, pre, smat, post, NULL, NULL, NULL, NULL); + mul_m3_series(defMats[i], post, smat, pre, tmpmat); } } @@ -1482,17 +1481,14 @@ void mat3_to_vec_roll(float mat[3][3], float r_vec[3], float *r_roll) * M* = 1 / (x^2 + z^2) * │ │ * └ -2 * x * z, x^2 - z^2 ┘ */ -void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]) +void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float mat[3][3]) { #define THETA_THRESHOLD_NEGY 1.0e-9f #define THETA_THRESHOLD_NEGY_CLOSE 1.0e-5f - float nor[3]; float theta; float rMatrix[3][3], bMatrix[3][3]; - normalize_v3_v3(nor, vec); - theta = 1.0f + nor[1]; /* With old algo, 1.0e-13f caused T23954 and T31333, 1.0e-6f caused T27675 and T30438, @@ -1543,6 +1539,13 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]) #undef THETA_THRESHOLD_NEGY_CLOSE } +void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]) +{ + float nor[3]; + + normalize_v3_v3(nor, vec); + vec_roll_to_mat3_normalized(nor, roll, mat); +} /* recursive part, calculates restposition of entire tree of children */ /* used by exiting editmode too */ @@ -1877,7 +1880,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos */ /* only happens on reload file, but violates depsgraph still... fix! */ - if (ELEM3(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { + if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { BKE_displist_make_curveTypes(scene, ikData->tar, 0); /* path building may fail in EditMode after removing verts [#33268]*/ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 8b87f5b0cea..adfe43cb2a3 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -80,6 +80,7 @@ #include "BKE_sound.h" #include "RE_pipeline.h" +#include "RE_render_ext.h" #include "BLF_api.h" @@ -119,6 +120,7 @@ void free_blender(void) DAG_exit(); BKE_brush_system_exit(); + RE_exit_texture_rng(); BLI_callback_global_finalize(); @@ -170,7 +172,7 @@ static void clear_global(void) static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const char *path_src) { strcpy(path_dst, path_src); - BLI_clean(path_dst); + BLI_path_native_slash(path_dst); return !STREQ(path_dst, path_src); } @@ -182,7 +184,7 @@ static void clean_paths(Main *main) BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL); for (scene = main->scene.first; scene; scene = scene->id.next) { - BLI_clean(scene->r.pic); + BLI_path_native_slash(scene->r.pic); } } @@ -197,29 +199,38 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath bScreen *curscreen = NULL; Scene *curscene = NULL; int recover; - char mode; - - /* 'u' = undo save, 'n' = no UI load */ - if (BLI_listbase_is_empty(&bfd->main->screen)) mode = 'u'; - else if (G.fileflags & G_FILE_NO_UI) mode = 'n'; - else mode = 0; + enum { + LOAD_UI = 1, + LOAD_UI_OFF, + LOAD_UNDO, + } mode; + + if (BLI_listbase_is_empty(&bfd->main->screen)) { + mode = LOAD_UNDO; + } + else if (G.fileflags & G_FILE_NO_UI) { + mode = LOAD_UI_OFF; + } + else { + mode = LOAD_UI; + } recover = (G.fileflags & G_FILE_RECOVER); /* Free all render results, without this stale data gets displayed after loading files */ - if (mode != 'u') { + if (mode != LOAD_UNDO) { RE_FreeAllRenderResults(); } /* Only make filepaths compatible when loading for real (not undo) */ - if (mode != 'u') { + if (mode != LOAD_UNDO) { clean_paths(bfd->main); } /* XXX here the complex windowmanager matching */ /* no load screens? */ - if (mode) { + if (mode != LOAD_UI) { /* comes from readfile.c */ SWAP(ListBase, G.main->wm, bfd->main->wm); SWAP(ListBase, G.main->screen, bfd->main->screen); @@ -263,7 +274,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath } /* case G_FILE_NO_UI or no screens in file */ - if (mode) { + if (mode != LOAD_UI) { /* leave entire context further unaltered? */ CTX_data_scene_set(C, curscene); } @@ -277,6 +288,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath CTX_wm_area_set(C, NULL); CTX_wm_region_set(C, NULL); CTX_wm_menu_set(C, NULL); + curscene = bfd->curscene; } /* this can happen when active scene was lib-linked, and doesn't exist anymore */ @@ -290,6 +302,9 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath curscene = CTX_data_scene(C); } + BLI_assert(curscene == CTX_data_scene(C)); + + /* special cases, override loaded flags: */ if (G.f != bfd->globalf) { const int flags_keep = (G_SWAP_EXCHANGE | G_SCRIPT_AUTOEXEC | G_SCRIPT_OVERRIDE_PREF); @@ -332,7 +347,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* baseflags, groups, make depsgraph, etc */ /* first handle case if other windows have different scenes visible */ - if (mode == 0) { + if (mode == LOAD_UI) { wmWindowManager *wm = G.main->wm.first; if (wm) { @@ -340,14 +355,14 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath for (win = wm->windows.first; win; win = win->next) { if (win->screen && win->screen->scene) /* zealous check... */ - if (win->screen->scene != CTX_data_scene(C)) + if (win->screen->scene != curscene) BKE_scene_set_background(G.main, win->screen->scene); } } } - BKE_scene_set_background(G.main, CTX_data_scene(C)); + BKE_scene_set_background(G.main, curscene); - if (mode != 'u') { + if (mode != LOAD_UNDO) { IMB_colormanagement_check_file_config(G.main); } @@ -384,6 +399,7 @@ void BKE_userdef_free(void) wmKeyMapItem *kmi; wmKeyMapDiffItem *kmdi; bAddon *addon, *addon_next; + uiFont *font; for (km = U.user_keymaps.first; km; km = km->next) { for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { @@ -413,6 +429,12 @@ void BKE_userdef_free(void) MEM_freeN(addon); } + for (font = U.uifonts.first; font; font = font->next) { + BLF_unload_id(font->blf_id); + } + + BLF_default_set(-1); + BLI_freelistN(&U.autoexec_paths); BLI_freelistN(&U.uistyles); @@ -459,7 +481,9 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports) return (bfd ? retval : BKE_READ_FILE_FAIL); } -int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, ReportList *reports, int update_defaults) +bool BKE_read_file_from_memory( + bContext *C, const void *filebuf, int filelength, + ReportList *reports, bool update_defaults) { BlendFileData *bfd; @@ -476,7 +500,9 @@ int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, } /* memfile is the undo buffer */ -int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *reports) +bool BKE_read_file_from_memfile( + bContext *C, MemFile *memfile, + ReportList *reports) { BlendFileData *bfd; @@ -661,7 +687,7 @@ void BKE_write_undo(bContext *C, const char *name) counter = counter % U.undosteps; BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter); - BLI_make_file_string("/", filepath, BLI_temporary_dir(), numstr); + BLI_make_file_string("/", filepath, BLI_temp_dir_session(), numstr); /* success = */ /* UNUSED */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL); diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index d0883728a71..3cd26dacebd 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -94,7 +94,8 @@ static bool checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), c /* high level function */ void BKE_bpath_missing_files_check(Main *bmain, ReportList *reports) { - BKE_bpath_traverse_main(bmain, checkMissingFiles_visit_cb, BKE_BPATH_TRAVERSE_ABS, reports); + BKE_bpath_traverse_main(bmain, checkMissingFiles_visit_cb, + BKE_BPATH_TRAVERSE_ABS | BKE_BPATH_TRAVERSE_SKIP_PACKED, reports); } typedef struct BPathRemap_Data { @@ -106,7 +107,7 @@ typedef struct BPathRemap_Data { int count_failed; } BPathRemap_Data; -static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char *path_src) +static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src) { BPathRemap_Data *data = (BPathRemap_Data *)userdata; @@ -132,6 +133,7 @@ static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const cha void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports) { BPathRemap_Data data = {NULL}; + const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY; if (basedir[0] == '\0') { printf("%s: basedir='', this is a bug\n", __func__); @@ -141,14 +143,14 @@ void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *re data.basedir = basedir; data.reports = reports; - BKE_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data); + BKE_bpath_traverse_main(bmain, bpath_relative_convert_visit_cb, flag, (void *)&data); BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO, "Total files %d | Changed %d | Failed %d", data.count_tot, data.count_changed, data.count_failed); } -static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char *path_src) +static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src) { BPathRemap_Data *data = (BPathRemap_Data *)userdata; @@ -175,6 +177,7 @@ static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const cha void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports) { BPathRemap_Data data = {NULL}; + const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY; if (basedir[0] == '\0') { printf("%s: basedir='', this is a bug\n", __func__); @@ -184,7 +187,7 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re data.basedir = basedir; data.reports = reports; - BKE_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data); + BKE_bpath_traverse_main(bmain, bpath_absolute_convert_visit_cb, flag, (void *)&data); BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO, "Total files %d | Changed %d | Failed %d", @@ -210,7 +213,7 @@ static int findFileRecursive(char *filename_new, /* file searching stuff */ DIR *dir; struct dirent *de; - struct stat status; + BLI_stat_t status; char path[FILE_MAX]; int size; bool found = false; @@ -421,7 +424,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int Image *ima; ima = (Image *)id; if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) { - if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) { if (!ima->packedfile) { BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); @@ -695,7 +698,7 @@ bool BKE_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *pa /* -------------------------------------------------------------------- */ /** * Backup/Restore/Free functions, - * \note These functions assume the data won't chane order. + * \note These functions assume the data won't change order. */ struct PathStore { diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 967e89e0dd1..ae6ae6087af 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -83,6 +83,7 @@ static void brush_defaults(Brush *brush) brush->plane_trim = 0.5f; brush->clone.alpha = 0.5f; brush->normal_weight = 0.0f; + brush->fill_threshold = 0.2f; brush->flag |= BRUSH_ALPHA_PRESSURE; /* BRUSH PAINT TOOL SETTINGS */ @@ -90,6 +91,8 @@ static void brush_defaults(Brush *brush) brush->rgb[1] = 1.0f; brush->rgb[2] = 1.0f; + zero_v3(brush->secondary_rgb); + /* BRUSH STROKE SETTINGS */ brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN); brush->spacing = 10; /* how far each brush dot should be spaced as a percentage of brush diameter */ @@ -161,6 +164,9 @@ Brush *BKE_brush_copy(Brush *brush) if (brush->mask_mtex.tex) id_us_plus((ID *)brush->mask_mtex.tex); + if (brush->paint_curve) + id_us_plus((ID *)brush->paint_curve); + if (brush->icon_imbuf) brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf); @@ -180,11 +186,9 @@ Brush *BKE_brush_copy(Brush *brush) /* not brush itself */ void BKE_brush_free(Brush *brush) { - if (brush->mtex.tex) - brush->mtex.tex->id.us--; - - if (brush->mask_mtex.tex) - brush->mask_mtex.tex->id.us--; + id_us_min((ID *)brush->mtex.tex); + id_us_min((ID *)brush->mask_mtex.tex); + id_us_min((ID *)brush->paint_curve); if (brush->icon_imbuf) IMB_freeImBuf(brush->icon_imbuf); @@ -192,6 +196,9 @@ void BKE_brush_free(Brush *brush) BKE_previewimg_free(&(brush->preview)); curvemapping_free(brush->curve); + + if (brush->gradient) + MEM_freeN(brush->gradient); } static void extern_local_brush(Brush *brush) @@ -199,6 +206,7 @@ static void extern_local_brush(Brush *brush) id_lib_extern((ID *)brush->mtex.tex); id_lib_extern((ID *)brush->mask_mtex.tex); id_lib_extern((ID *)brush->clone.image); + id_lib_extern((ID *)brush->paint_curve); } void BKE_brush_make_local(Brush *brush) @@ -742,10 +750,23 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); } + CLAMP(intensity, 0.0f, 1.0f); + + switch (br->mask_pressure) { + case BRUSH_MASK_PRESSURE_CUTOFF: + intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f; + break; + case BRUSH_MASK_PRESSURE_RAMP: + intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value); + break; + default: + break; + } + return intensity; } -/* Unified Size and Strength */ +/* Unified Size / Strength / Color */ /* XXX: be careful about setting size and unprojected radius * because they depend on one another @@ -760,6 +781,29 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br, * In any case, a better solution is needed to prevent * inconsistency. */ + +float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb; +} + +float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb; +} + +void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + if (ups->flag & UNIFIED_PAINT_COLOR) + copy_v3_v3(ups->rgb, color); + else + copy_v3_v3(brush->rgb, color); +} + void BKE_brush_size_set(Scene *scene, Brush *brush, int size) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; @@ -886,39 +930,27 @@ void BKE_brush_scale_size(int *r_brush_size, void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2]) { - int use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ? - (brush->jitter_absolute != 0) : (brush->jitter != 0); + float rand_pos[2]; + float spread; + int diameter; - /* jitter-ed brush gives weird and unpredictable result for this - * kinds of stroke, so manually disable jitter usage (sergey) */ - use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0; + do { + rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f; + rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f; + } while (len_squared_v2(rand_pos) > SQUARE(0.5f)); - if (use_jitter) { - float rand_pos[2]; - float spread; - int diameter; - do { - rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f; - rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f; - } while (len_squared_v2(rand_pos) > (0.5f * 0.5f)); - - - if (brush->flag & BRUSH_ABSOLUTE_JITTER) { - diameter = 2 * brush->jitter_absolute; - spread = 1.0; - } - else { - diameter = 2 * BKE_brush_size_get(scene, brush); - spread = brush->jitter; - } - /* find random position within a circle of diameter 1 */ - jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread; - jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread; + if (brush->flag & BRUSH_ABSOLUTE_JITTER) { + diameter = 2 * brush->jitter_absolute; + spread = 1.0; } else { - copy_v2_v2(jitterpos, pos); + diameter = 2 * BKE_brush_size_get(scene, brush); + spread = brush->jitter; } + /* find random position within a circle of diameter 1 */ + jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread; + jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread; } void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mask) diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index f85a91b66cb..4ad577a7bda 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -77,288 +77,6 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con return FLT_MAX; } - -/* - * Function adapted from David Eberly's distance tools (LGPL) - * http://www.geometrictools.com/LibFoundation/Distance/Distance.html - */ -float nearest_point_in_tri_surface_squared( - const float v0[3], const float v1[3], const float v2[3], - const float p[3], int *v, int *e, float nearest[3]) -{ - float diff[3]; - float e0[3]; - float e1[3]; - float A00; - float A01; - float A11; - float B0; - float B1; - float C; - float Det; - float S; - float T; - float sqrDist; - int lv = -1, le = -1; - - sub_v3_v3v3(diff, v0, p); - sub_v3_v3v3(e0, v1, v0); - sub_v3_v3v3(e1, v2, v0); - - A00 = dot_v3v3(e0, e0); - A01 = dot_v3v3(e0, e1); - A11 = dot_v3v3(e1, e1); - B0 = dot_v3v3(diff, e0); - B1 = dot_v3v3(diff, e1); - C = dot_v3v3(diff, diff); - Det = fabsf(A00 * A11 - A01 * A01); - S = A01 * B1 - A11 * B0; - T = A01 * B0 - A00 * B1; - - if (S + T <= Det) { - if (S < 0.0f) { - if (T < 0.0f) { /* Region 4 */ - if (B0 < 0.0f) { - T = 0.0f; - if (-B0 >= A00) { - S = 1.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else { - if (fabsf(A00) > FLT_EPSILON) - S = -B0 / A00; - else - S = 0.0f; - sqrDist = B0 * S + C; - le = 0; - } - } - else { - S = 0.0f; - if (B1 >= 0.0f) { - T = 0.0f; - sqrDist = C; - lv = 0; - } - else if (-B1 >= A11) { - T = 1.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else { - if (fabsf(A11) > FLT_EPSILON) - T = -B1 / A11; - else - T = 0.0f; - sqrDist = B1 * T + C; - le = 1; - } - } - } - else { /* Region 3 */ - S = 0.0f; - if (B1 >= 0.0f) { - T = 0.0f; - sqrDist = C; - lv = 0; - } - else if (-B1 >= A11) { - T = 1.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else { - if (fabsf(A11) > FLT_EPSILON) - T = -B1 / A11; - else - T = 0.0; - sqrDist = B1 * T + C; - le = 1; - } - } - } - else if (T < 0.0f) { /* Region 5 */ - T = 0.0f; - if (B0 >= 0.0f) { - S = 0.0f; - sqrDist = C; - lv = 0; - } - else if (-B0 >= A00) { - S = 1.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else { - if (fabsf(A00) > FLT_EPSILON) - S = -B0 / A00; - else - S = 0.0f; - sqrDist = B0 * S + C; - le = 0; - } - } - else { /* Region 0 */ - /* Minimum at interior lv */ - float invDet; - if (fabsf(Det) > FLT_EPSILON) - invDet = 1.0f / Det; - else - invDet = 0.0f; - S *= invDet; - T *= invDet; - sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) + - T * (A01 * S + A11 * T + 2.0f * B1) + C; - } - } - else { - float tmp0, tmp1, numer, denom; - - if (S < 0.0f) { /* Region 2 */ - tmp0 = A01 + B0; - tmp1 = A11 + B1; - if (tmp1 > tmp0) { - numer = tmp1 - tmp0; - denom = A00 - 2.0f * A01 + A11; - if (numer >= denom) { - S = 1.0f; - T = 0.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else { - if (fabsf(denom) > FLT_EPSILON) - S = numer / denom; - else - S = 0.0f; - T = 1.0f - S; - sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) + - T * (A01 * S + A11 * T + 2.0f * B1) + C; - le = 2; - } - } - else { - S = 0.0f; - if (tmp1 <= 0.0f) { - T = 1.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else if (B1 >= 0.0f) { - T = 0.0f; - sqrDist = C; - lv = 0; - } - else { - if (fabsf(A11) > FLT_EPSILON) - T = -B1 / A11; - else - T = 0.0f; - sqrDist = B1 * T + C; - le = 1; - } - } - } - else if (T < 0.0f) { /* Region 6 */ - tmp0 = A01 + B1; - tmp1 = A00 + B0; - if (tmp1 > tmp0) { - numer = tmp1 - tmp0; - denom = A00 - 2.0f * A01 + A11; - if (numer >= denom) { - T = 1.0f; - S = 0.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else { - if (fabsf(denom) > FLT_EPSILON) - T = numer / denom; - else - T = 0.0f; - S = 1.0f - T; - sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) + - T * (A01 * S + A11 * T + 2.0f * B1) + C; - le = 2; - } - } - else { - T = 0.0f; - if (tmp1 <= 0.0f) { - S = 1.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else if (B0 >= 0.0f) { - S = 0.0f; - sqrDist = C; - lv = 0; - } - else { - if (fabsf(A00) > FLT_EPSILON) - S = -B0 / A00; - else - S = 0.0f; - sqrDist = B0 * S + C; - le = 0; - } - } - } - else { /* Region 1 */ - numer = A11 + B1 - A01 - B0; - if (numer <= 0.0f) { - S = 0.0f; - T = 1.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else { - denom = A00 - 2.0f * A01 + A11; - if (numer >= denom) { - S = 1.0f; - T = 0.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else { - if (fabsf(denom) > FLT_EPSILON) - S = numer / denom; - else - S = 0.0f; - T = 1.0f - S; - sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) + - T * (A01 * S + A11 * T + 2.0f * B1) + C; - le = 2; - } - } - } - } - - /* Account for numerical round-off error */ - if (sqrDist < FLT_EPSILON) - sqrDist = 0.0f; - - { - float w[3], x[3], y[3], z[3]; - copy_v3_v3(w, v0); - copy_v3_v3(x, e0); - mul_v3_fl(x, S); - copy_v3_v3(y, e1); - mul_v3_fl(y, T); - add_v3_v3v3(z, w, x); - add_v3_v3v3(z, z, y); - //sub_v3_v3v3(d, p, z); - copy_v3_v3(nearest, z); - //d = p - ( v0 + S * e0 + T * e1 ); - } - *v = lv; - *e = le; - - return sqrDist; -} - - /* * BVH from meshes callbacks */ @@ -380,9 +98,10 @@ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3 do { float nearest_tmp[3], dist_sq; - int vertex, edge; - - dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp); + + closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2); + dist_sq = len_squared_v3v3(co, nearest_tmp); + if (dist_sq < nearest->dist_sq) { nearest->index = index; nearest->dist_sq = dist_sq; @@ -413,9 +132,10 @@ static void editmesh_faces_nearest_point(void *userdata, int index, const float { float nearest_tmp[3], dist_sq; - int vertex, edge; - dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp); + closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2); + dist_sq = len_squared_v3v3(co, nearest_tmp); + if (dist_sq < nearest->dist_sq) { nearest->index = index; nearest->dist_sq = dist_sq; diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index b20ba40c0dd..1402f62291f 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -201,7 +201,7 @@ void BKE_camera_params_init(CameraParams *params) /* fallback for non camera objects */ params->clipsta = 0.1f; - params->clipsta = 100.0f; + params->clipend = 100.0f; } void BKE_camera_params_from_object(CameraParams *params, Object *ob) @@ -232,7 +232,7 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob) /* lamp object */ Lamp *la = ob->data; float fac = cosf(la->spotsize * 0.5f); - float phi = acos(fac); + float phi = acosf(fac); params->lens = 16.0f * fac / sinf(phi); if (params->lens == 0.0f) @@ -473,7 +473,7 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data) unsigned int i; for (i = 0; i < 4; i++) { - float nd = dist_squared_to_plane_v3(co, data->plane_tx[i]); + float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]); if (nd < data->dist_vals_sq[i]) { data->dist_vals_sq[i] = nd; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 205282c1de7..bfc70c91181 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -34,12 +34,11 @@ * \ingroup bke */ -#include "GL/glew.h" - #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_edgehash.h" #include "BLI_utildefines.h" +#include "BLI_stackdefines.h" #include "BKE_pbvh.h" #include "BKE_cdderivedmesh.h" @@ -50,6 +49,7 @@ #include "BKE_editmesh.h" #include "BKE_curve.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -60,6 +60,7 @@ #include "GPU_buffers.h" #include "GPU_draw.h" #include "GPU_extensions.h" +#include "GPU_glew.h" #include "GPU_material.h" #include <string.h> @@ -551,7 +552,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, MVert *mvert = cddm->mvert; MFace *mface = cddm->mface; const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1; if (cddm->pbvh && cddm->pbvh_draw) { @@ -575,11 +576,16 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES; new_matnr = mface->mat_nr + 1; new_shademodel = (lnors || (mface->flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT; - - if (new_glmode != glmode || new_matnr != matnr || new_shademodel != shademodel) { + + + if ((new_glmode != glmode) || (new_shademodel != shademodel) || + (setMaterial && (new_matnr != matnr))) + { glEnd(); - drawCurrentMat = setMaterial(matnr = new_matnr, NULL); + if (setMaterial) { + drawCurrentMat = setMaterial(matnr = new_matnr, NULL); + } glShadeModel(shademodel = new_shademodel); glBegin(glmode = new_glmode); @@ -597,7 +603,6 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, glNormal3sv((const GLshort *)lnors[0][3]); glVertex3fv(mvert[mface->v4].co); } - lnors++; } else if (shademodel == GL_FLAT) { if (nors) { @@ -635,7 +640,10 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, } } - if (nors) nors += 3; + if (nors) + nors += 3; + if (lnors) + lnors++; } glEnd(); } @@ -661,17 +669,18 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, DMSetDrawOptionsTex drawParams, DMSetDrawOptions drawParamsMapped, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag uvflag) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; MVert *mv = cddm->mvert; - MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE); + const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE); const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); MCol *mcol; int i, orig; int colType, startFace = 0; + bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0; /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); @@ -710,14 +719,35 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, cdDM_update_normals_from_pbvh(dm); if (GPU_buffer_legacy(dm)) { + int mat_nr_cache = -1; + MTFace *tf_base = DM_get_tessface_data_layer(dm, CD_MTFACE); + MTFace *tf_stencil_base = NULL; + MTFace *tf_stencil = NULL; + + if (uvflag & DM_DRAW_USE_TEXPAINT_UV) { + int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE); + tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil); + } + DEBUG_VBO("Using legacy code. cdDM_drawFacesTex_common\n"); for (i = 0; i < dm->numTessFaceData; i++, mf++) { MVert *mvert; DMDrawOption draw_option; unsigned char *cp = NULL; + if (uvflag & DM_DRAW_USE_TEXPAINT_UV) { + if (mf->mat_nr != mat_nr_cache) { + tf_base = DM_paint_uvlayer_active_get(dm, mf->mat_nr); + + mat_nr_cache = mf->mat_nr; + } + } + + tf = tf_base ? tf_base + i : NULL; + tf_stencil = tf_stencil_base ? tf_stencil_base + i : NULL; + if (drawParams) { - draw_option = drawParams(tf ? &tf[i] : NULL, (mcol != NULL), mf->mat_nr); + draw_option = drawParams(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr); } else { if (index_mf_to_mpoly) { @@ -770,21 +800,24 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES); - if (tf) glTexCoord2fv(tf[i].uv[0]); + if (tf) glTexCoord2fv(tf->uv[0]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[0]); if (cp) glColor3ub(cp[3], cp[2], cp[1]); mvert = &mv[mf->v1]; if (lnors) glNormal3sv((const GLshort *)lnors[0][0]); else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); glVertex3fv(mvert->co); - if (tf) glTexCoord2fv(tf[i].uv[1]); + if (tf) glTexCoord2fv(tf->uv[1]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[1]); if (cp) glColor3ub(cp[7], cp[6], cp[5]); mvert = &mv[mf->v2]; if (lnors) glNormal3sv((const GLshort *)lnors[0][1]); else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); glVertex3fv(mvert->co); - if (tf) glTexCoord2fv(tf[i].uv[2]); + if (tf) glTexCoord2fv(tf->uv[2]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[2]); if (cp) glColor3ub(cp[11], cp[10], cp[9]); mvert = &mv[mf->v3]; if (lnors) glNormal3sv((const GLshort *)lnors[0][2]); @@ -792,24 +825,30 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, glVertex3fv(mvert->co); if (mf->v4) { - if (tf) glTexCoord2fv(tf[i].uv[3]); + if (tf) glTexCoord2fv(tf->uv[3]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[3]); if (cp) glColor3ub(cp[15], cp[14], cp[13]); mvert = &mv[mf->v4]; if (lnors) glNormal3sv((const GLshort *)lnors[0][3]); else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); glVertex3fv(mvert->co); } - if (lnors) lnors++; glEnd(); } - if (nors) nors += 3; + if (nors) + nors += 3; + if (lnors) + lnors++; } } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ GPU_vertex_setup(dm); GPU_normal_setup(dm); - GPU_uv_setup(dm); + if (uvflag & DM_DRAW_USE_TEXPAINT_UV) + GPU_texpaint_uv_setup(dm); + else + GPU_uv_setup(dm); if (mcol) { GPU_color_setup(dm, colType); } @@ -829,7 +868,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, next_actualFace = dm->drawObject->triangle_to_mface[i + 1]; if (drawParams) { - draw_option = drawParams(tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr); + draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr); } else { if (index_mf_to_mpoly) { @@ -885,9 +924,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, static void cdDM_drawFacesTex(DerivedMesh *dm, DMSetDrawOptionsTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag uvflag) { - cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); + cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, uvflag); } static void cdDM_drawMappedFaces(DerivedMesh *dm, @@ -901,7 +940,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, MFace *mf = cddm->mface; MCol *mcol; const float *nors = DM_get_tessface_data_layer(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); int colType, useColors = flag & DM_DRAW_USE_COLORS; int i, orig; @@ -973,7 +1012,6 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, glNormal3sv((const GLshort *)lnors[0][3]); glVertex3fv(mv[mf->v4].co); } - lnors++; } else if (!drawSmooth) { if (nors) { @@ -1024,7 +1062,10 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, glDisable(GL_POLYGON_STIPPLE); } - if (nors) nors += 3; + if (nors) + nors += 3; + if (lnors) + lnors++; } } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ @@ -1111,13 +1152,13 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, static void cdDM_drawMappedFacesTex(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag flag) { - cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); + cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag); } -static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, - short (*lnor)[3], int smoothnormal) +static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int vert, + const short (*lnor)[3], const bool smoothnormal) { const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; int b; @@ -1193,11 +1234,11 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, CDDerivedMesh *cddm = (CDDerivedMesh *) dm; GPUVertexAttribs gattribs; DMVertexAttribs attribs; - MVert *mvert = cddm->mvert; - MFace *mface = cddm->mface; + const MVert *mvert = cddm->mvert; + const MFace *mface = cddm->mface; /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ - float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); int a, b, matnr, new_matnr; bool do_draw; int orig; @@ -1236,8 +1277,8 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, glBegin(GL_QUADS); for (a = 0; a < dm->numTessFaceData; a++, mface++) { - const int smoothnormal = lnors || (mface->flag & ME_SMOOTH); - short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL; + const bool smoothnormal = lnors || (mface->flag & ME_SMOOTH); + const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL; new_matnr = mface->mat_nr + 1; if (new_matnr != matnr) { @@ -1282,13 +1323,11 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, glNormal3fv(nor); } } - - if (lnors) { - ln1 = &lnors[0][0]; - ln2 = &lnors[0][1]; - ln3 = &lnors[0][2]; - ln4 = &lnors[0][3]; - lnors++; + else if (lnors) { + ln1 = &lnors[a][0]; + ln2 = &lnors[a][1]; + ln3 = &lnors[a][2]; + ln4 = &lnors[a][3]; } cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, ln1, smoothnormal); @@ -1309,7 +1348,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0; int i; - MFace *mf = mface; + const MFace *mf = mface; GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/ memset(&attribs, 0, sizeof(attribs)); @@ -1533,8 +1572,8 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, DMVertexAttribs attribs; MVert *mvert = cddm->mvert; MFace *mf = cddm->mface; - float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); int a, matnr, new_matnr; int orig; @@ -1569,8 +1608,8 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, glBegin(GL_QUADS); for (a = 0; a < dm->numTessFaceData; a++, mf++) { - const int smoothnormal = lnors || (mf->flag & ME_SMOOTH); - short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL; + const bool smoothnormal = lnors || (mf->flag & ME_SMOOTH); + const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL; /* material */ new_matnr = mf->mat_nr + 1; @@ -1609,13 +1648,11 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, glNormal3fv(nor); } } - - if (lnors) { - ln1 = &lnors[0][0]; - ln2 = &lnors[0][1]; - ln3 = &lnors[0][2]; - ln4 = &lnors[0][3]; - lnors++; + else if (lnors) { + ln1 = &lnors[a][0]; + ln2 = &lnors[a][1]; + ln3 = &lnors[a][2]; + ln4 = &lnors[a][3]; } /* vertices */ @@ -2530,25 +2567,200 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) #if 1 /** + * Poly compare with vtargetmap + * Function used by #CDDM_merge_verts. + * The function compares poly_source after applying vtargetmap, with poly_target. + * The two polys are identical if they share the same vertices in the same order, or in reverse order, + * but starting position loopstart may be different. + * The function is called with direct_reverse=1 for same order (i.e. same normal), + * and may be called again with direct_reverse=-1 for reverse order. + * \return 1 if polys are identical, 0 if polys are different. + */ +static int cddm_poly_compare(MLoop *mloop_array, MPoly *mpoly_source, MPoly *mpoly_target, const int *vtargetmap, const int direct_reverse) +{ + int vert_source, first_vert_source, vert_target; + int i_loop_source; + int i_loop_target, i_loop_target_start, i_loop_target_offset, i_loop_target_adjusted; + bool compare_completed = false; + bool same_loops = false; + + MLoop *mloop_source, *mloop_target; + + BLI_assert(direct_reverse == 1 || direct_reverse == -1); + + i_loop_source = 0; + mloop_source = mloop_array + mpoly_source->loopstart; + vert_source = mloop_source->v; + + if (vtargetmap[vert_source] != -1) { + vert_source = vtargetmap[vert_source]; + } + else { + /* All source loop vertices should be mapped */ + BLI_assert(false); + } + + /* Find same vertex within mpoly_target's loops */ + mloop_target = mloop_array + mpoly_target->loopstart; + for (i_loop_target = 0; i_loop_target < mpoly_target->totloop; i_loop_target++, mloop_target++) { + if (mloop_target->v == vert_source) { + break; + } + } + + /* If same vertex not found, then polys cannot be equal */ + if (i_loop_target >= mpoly_target->totloop) { + return false; + } + + /* Now mloop_source and m_loop_target have one identical vertex */ + /* mloop_source is at position 0, while m_loop_target has advanced to find identical vertex */ + /* Go around the loop and check that all vertices match in same order */ + /* Skipping source loops when consecutive source vertices are mapped to same target vertex */ + + i_loop_target_start = i_loop_target; + i_loop_target_offset = 0; + first_vert_source = vert_source; + + compare_completed = false; + same_loops = false; + + while (!compare_completed) { + + vert_target = mloop_target->v; + + /* First advance i_loop_source, until it points to different vertex, after mapping applied */ + do { + i_loop_source++; + + if (i_loop_source == mpoly_source->totloop) { + /* End of loops for source, must match end of loop for target. */ + if (i_loop_target_offset == mpoly_target->totloop - 1) { + compare_completed = true; + same_loops = true; + break; /* Polys are identical */ + } + else { + compare_completed = true; + same_loops = false; + break; /* Polys are different */ + } + } + + mloop_source++; + vert_source = mloop_source->v; + + if (vtargetmap[vert_source] != -1) { + vert_source = vtargetmap[vert_source]; + } + else { + /* All source loop vertices should be mapped */ + BLI_assert(false); + } + + } while (vert_source == vert_target); + + if (compare_completed) { + break; + } + + /* Now advance i_loop_target as well */ + i_loop_target_offset++; + + if (i_loop_target_offset == mpoly_target->totloop) { + /* End of loops for target only, that means no match */ + /* except if all remaining source vertices are mapped to first target */ + for (; i_loop_source < mpoly_source->totloop; i_loop_source++, mloop_source++) { + vert_source = vtargetmap[mloop_source->v]; + if (vert_source != first_vert_source) { + compare_completed = true; + same_loops = false; + break; + } + } + if (!compare_completed) { + same_loops = true; + } + break; + } + + /* Adjust i_loop_target for cycling around and for direct/reverse order defined by delta = +1 or -1 */ + i_loop_target_adjusted = (i_loop_target_start + direct_reverse * i_loop_target_offset) % mpoly_target->totloop; + if (i_loop_target_adjusted < 0) { + i_loop_target_adjusted += mpoly_target->totloop; + } + mloop_target = mloop_array + mpoly_target->loopstart + i_loop_target_adjusted; + vert_target = mloop_target->v; + + if (vert_target != vert_source) { + same_loops = false; /* Polys are different */ + break; + } + } + return same_loops; +} + +/* Utility stuff for using GHash with polys */ + +typedef struct PolyKey { + int poly_index; /* index of the MPoly within the derived mesh */ + int totloops; /* number of loops in the poly */ + unsigned int hash_sum; /* Sum of all vertices indices */ + unsigned int hash_xor; /* Xor of all vertices indices */ +} PolyKey; + + +static unsigned int poly_gset_hash_fn(const void *key) +{ + const PolyKey *pk = key; + return pk->hash_sum; +} + +static bool poly_gset_compare_fn(const void *k1, const void *k2) +{ + const PolyKey *pk1 = k1; + const PolyKey *pk2 = k2; + if ((pk1->hash_sum == pk2->hash_sum) && + (pk1->hash_xor == pk2->hash_xor) && + (pk1->totloops == pk2->totloops)) + { + /* Equality - note that this does not mean equality of polys */ + return 0; + } + else { + return 1; + } +} + +/** * Merge Verts * + * This frees dm, and returns a new one. + * * \param vtargetmap The table that maps vertices to target vertices. a value of -1 * indicates a vertex is a target, and is to be kept. * This array is aligned with 'dm->numVertData' * - * \param tot_vtargetmap The number of non '-1' values in vtargetmap. - * (not the size ) + * \param tot_vtargetmap The number of non '-1' values in vtargetmap. (not the size) * - * this frees dm, and returns a new one. + * \param merge_mode enum with two modes. + * - #CDDM_MERGE_VERTS_DUMP_IF_MAPPED + * When called by the Mirror Modifier, + * In this mode it skips any faces that have all vertices merged (to avoid creating pairs + * of faces sharing the same set of vertices) + * - #CDDM_MERGE_VERTS_DUMP_IF_EQUAL + * When called by the Array Modifier, + * In this mode, faces where all vertices are merged are double-checked, + * to see whether all target vertices actually make up a poly already. + * Indeed it could be that all of a poly's vertices are merged, + * but merged to vertices that do not make up a single poly, + * in which case the original poly should not be dumped. + * Actually this later behavior could apply to the Mirror Modifier as well, but the additional checks are + * costly and not necessary in the case of mirror, because each vertex is only merged to its own mirror. * - * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. - * - * Note: This function is currently only used by the Mirror modifier, so it - * skips any faces that have all vertices merged (to avoid creating pairs - * of faces sharing the same set of vertices). If used elsewhere, it may - * be necessary to make this functionality optional. + * \note #CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. */ -DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap) +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap, const int merge_mode) { // #define USE_LOOPS CDDerivedMesh *cddm = (CDDerivedMesh *)dm; @@ -2589,16 +2801,19 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int EdgeHash *ehash = BLI_edgehash_new_ex(__func__, totedge); int i, j, c; - - STACK_INIT(oldv); - STACK_INIT(olde); - STACK_INIT(oldl); - STACK_INIT(oldp); - STACK_INIT(mvert); - STACK_INIT(medge); - STACK_INIT(mloop); - STACK_INIT(mpoly); + PolyKey *poly_keys; + GSet *poly_gset = NULL; + + STACK_INIT(oldv, totvert_final); + STACK_INIT(olde, totedge); + STACK_INIT(oldl, totloop); + STACK_INIT(oldp, totpoly); + + STACK_INIT(mvert, totvert_final); + STACK_INIT(medge, totedge); + STACK_INIT(mloop, totloop); + STACK_INIT(mpoly, totpoly); /* fill newl with destination vertex indices */ mv = cddm->mvert; @@ -2631,10 +2846,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int med = cddm->medge; c = 0; for (i = 0; i < totedge; i++, med++) { - - if (LIKELY(med->v1 != med->v2)) { - const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; - const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; + const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + if (LIKELY(v1 != v2)) { void **eh_p = BLI_edgehash_lookup_p(ehash, v1, v2); if (eh_p) { @@ -2653,13 +2867,49 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int } } + if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) { + /* In this mode, we need to determine, whenever a poly' vertices are all mapped */ + /* if the targets already make up a poly, in which case the new poly is dropped */ + /* This poly equality check is rather complex. We use a BLI_ghash to speed it up with a first level check */ + PolyKey *mpgh; + poly_keys = MEM_mallocN(sizeof(PolyKey) * totpoly, __func__); + poly_gset = BLI_gset_new_ex(poly_gset_hash_fn, poly_gset_compare_fn, __func__, totpoly); + /* Duplicates allowed because our compare function is not pure equality */ + BLI_gset_flag_set(poly_gset, GHASH_FLAG_ALLOW_DUPES); + + mp = cddm->mpoly; + mpgh = poly_keys; + for (i = 0; i < totpoly; i++, mp++, mpgh++) { + mpgh->poly_index = i; + mpgh->totloops = mp->totloop; + ml = cddm->mloop + mp->loopstart; + mpgh->hash_sum = mpgh->hash_xor = 0; + for (j = 0; j < mp->totloop; j++, ml++) { + mpgh->hash_sum += ml->v; + mpgh->hash_xor ^= ml->v; + } + BLI_gset_insert(poly_gset, mpgh); + } + + if (cddm->pmap) { + MEM_freeN(cddm->pmap); + MEM_freeN(cddm->pmap_mem); + } + /* Can we optimise by reusing an old pmap ? How do we know an old pmap is stale ? */ + /* When called by MOD_array.c, the cddm has just been created, so it has no valid pmap. */ + BKE_mesh_vert_poly_map_create(&cddm->pmap, &cddm->pmap_mem, + cddm->mpoly, cddm->mloop, + totvert, totpoly, totloop); + } /* done preparing for fast poly compare */ + + mp = cddm->mpoly; for (i = 0; i < totpoly; i++, mp++) { MPoly *mp_new; ml = cddm->mloop + mp->loopstart; - /* skip faces with all vertices merged */ + /* check faces with all vertices merged */ { bool all_vertices_merged = true; @@ -2671,16 +2921,86 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int } if (UNLIKELY(all_vertices_merged)) { - continue; + if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_MAPPED) { + /* In this mode, all vertices merged is enough to dump face */ + continue; + } + else if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) { + /* Additional condition for face dump: target vertices must make up an identical face */ + /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */ + /* (2) second step is thorough but more costly poly compare */ + int i_poly, v_target, v_prev; + bool found = false; + PolyKey pkey; + + /* Use poly_gset for fast (although not 100% certain) identification of same poly */ + /* First, make up a poly_summary structure */ + ml = cddm->mloop + mp->loopstart; + pkey.hash_sum = pkey.hash_xor = 0; + pkey.totloops = 0; + v_prev = vtargetmap[(ml + mp->totloop -1)->v]; /* since it loops around, the prev of first is the last */ + for (j = 0; j < mp->totloop; j++, ml++) { + v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */ + if (v_target == v_prev) { + /* consecutive vertices in loop map to the same target: discard */ + /* but what about last to first ? */ + continue; + } + pkey.hash_sum += v_target; + pkey.hash_xor ^= v_target; + pkey.totloops++; + v_prev = v_target; + } + if (BLI_gset_haskey(poly_gset, &pkey)) { + + /* There might be a poly that matches this one. + * We could just leave it there and say there is, and do a "continue". + * ... but we are checking whether there is an exact poly match. + * It's not so costly in terms of CPU since it's very rare, just a lot of complex code. + */ + + /* Consider current loop again */ + ml = cddm->mloop + mp->loopstart; + /* Consider the target of the loop's first vert */ + v_target = vtargetmap[ml->v]; + /* Now see if v_target belongs to a poly that shares all vertices with source poly, + * in same order, or reverse order */ + + for (i_poly = 0; i_poly < cddm->pmap[v_target].count; i_poly++) { + MPoly *target_poly = cddm->mpoly + *(cddm->pmap[v_target].indices + i_poly); + + if (cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, +1) || + cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1)) + { + found = true; + break; + } + } + if (found) { + /* Current poly's vertices are mapped to a poly that is strictly identical */ + /* Current poly is dumped */ + continue; + } + } + } } } + + /* Here either the poly's vertices were not all merged + * or they were all merged, but targets do not make up an identical poly, + * the poly is retained. + */ ml = cddm->mloop + mp->loopstart; c = 0; for (j = 0; j < mp->totloop; j++, ml++) { + unsigned int v1, v2; + med = cddm->medge + ml->e; - if (LIKELY(med->v1 != med->v2)) { + v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; + v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + if (LIKELY(v1 != v2)) { #ifdef USE_LOOPS newl[j + mp->loopstart] = STACK_SIZE(mloop); #endif @@ -2693,13 +3013,28 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int if (UNLIKELY(c == 0)) { continue; } + else if (UNLIKELY(c < 3)) { + STACK_DISCARD(oldl, c); + STACK_DISCARD(mloop, c); + continue; + } + mp_new = STACK_PUSH_RET_PTR(mpoly); *mp_new = *mp; mp_new->totloop = c; + BLI_assert(mp_new->totloop >= 3); mp_new->loopstart = STACK_SIZE(mloop) - c; STACK_PUSH(oldp, i); + } /* end of the loop that tests polys */ + + + if (poly_gset) { + // printf("hash quality %.6f\n", BLI_gset_calc_quality(poly_gset)); + + BLI_gset_free(poly_gset, NULL); + MEM_freeN(poly_keys); } /*create new cddm*/ @@ -2761,16 +3096,6 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int MEM_freeN(oldl); MEM_freeN(oldp); - STACK_FREE(oldv); - STACK_FREE(olde); - STACK_FREE(oldl); - STACK_FREE(oldp); - - STACK_FREE(mvert); - STACK_FREE(medge); - STACK_FREE(mloop); - STACK_FREE(mpoly); - BLI_edgehash_free(ehash, NULL); /*free old derivedmesh*/ @@ -2794,15 +3119,15 @@ void CDDM_calc_edges_tessface(DerivedMesh *dm) eh = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(numFaces)); for (i = 0; i < numFaces; i++, mf++) { - BLI_edgeset_reinsert(eh, mf->v1, mf->v2); - BLI_edgeset_reinsert(eh, mf->v2, mf->v3); + BLI_edgeset_add(eh, mf->v1, mf->v2); + BLI_edgeset_add(eh, mf->v2, mf->v3); if (mf->v4) { - BLI_edgeset_reinsert(eh, mf->v3, mf->v4); - BLI_edgeset_reinsert(eh, mf->v4, mf->v1); + BLI_edgeset_add(eh, mf->v3, mf->v4); + BLI_edgeset_add(eh, mf->v4, mf->v1); } else { - BLI_edgeset_reinsert(eh, mf->v3, mf->v1); + BLI_edgeset_add(eh, mf->v3, mf->v1); } } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index f5c7f9e4501..aacf02555d4 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -228,7 +228,7 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, int moving) ClothVertex *verts = cloth->verts; MFace *mfaces; float co[12], co_moving[12]; - int ret = 0; + bool ret = false; if (!bvhtree) return; @@ -1323,14 +1323,14 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) /* insert other near springs in edgeset AFTER bending springs are calculated (for selfcolls) */ for (i = 0; i < numedges; i++) { /* struct springs */ - BLI_edgeset_reinsert(edgeset, medge[i].v1, medge[i].v2); + BLI_edgeset_add(edgeset, medge[i].v1, medge[i].v2); } for (i = 0; i < numfaces; i++) { /* edge springs */ if (mface[i].v4) { - BLI_edgeset_reinsert(edgeset, mface[i].v1, mface[i].v3); + BLI_edgeset_add(edgeset, mface[i].v1, mface[i].v3); - BLI_edgeset_reinsert(edgeset, mface[i].v2, mface[i].v4); + BLI_edgeset_add(edgeset, mface[i].v2, mface[i].v4); } } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index cedd9eae597..2f600935b1e 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -110,7 +110,7 @@ void bvhtree_update_from_mvert(BVHTree *bvhtree, MFace *faces, int numfaces, MVe int i; MFace *mfaces = faces; float co[12], co_moving[12]; - int ret = 0; + bool ret = false; if ( !bvhtree ) return; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index c6d07a959d1..a63e06c7cb8 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -577,14 +577,14 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr) /* store first and last handle for extrapolation, unit length */ cuma->ext_in[0] = bezt[0].vec[0][0] - bezt[0].vec[1][0]; cuma->ext_in[1] = bezt[0].vec[0][1] - bezt[0].vec[1][1]; - range = sqrt(cuma->ext_in[0] * cuma->ext_in[0] + cuma->ext_in[1] * cuma->ext_in[1]); + range = sqrtf(cuma->ext_in[0] * cuma->ext_in[0] + cuma->ext_in[1] * cuma->ext_in[1]); cuma->ext_in[0] /= range; cuma->ext_in[1] /= range; a = cuma->totpoint - 1; cuma->ext_out[0] = bezt[a].vec[1][0] - bezt[a].vec[2][0]; cuma->ext_out[1] = bezt[a].vec[1][1] - bezt[a].vec[2][1]; - range = sqrt(cuma->ext_out[0] * cuma->ext_out[0] + cuma->ext_out[1] * cuma->ext_out[1]); + range = sqrtf(cuma->ext_out[0] * cuma->ext_out[0] + cuma->ext_out[1] * cuma->ext_out[1]); cuma->ext_out[0] /= range; cuma->ext_out[1] /= range; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 52cfa92ceaf..8a5d313e3fb 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -185,6 +185,10 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) /* calculate delta of constraints evaluation */ invert_m4_m4(imat, cob->startmat); + /* XXX This would seem to be in wrong order. However, it does not work in 'right' order - would be nice to + * understand why premul is needed here instead of usual postmul? + * In any case, we **do not get a delta** here (e.g. startmat & matrix having same location, still gives + * a 'delta' with non-null translation component :/ ).*/ mul_m4_m4m4(delta, cob->matrix, imat); /* copy matrices back to source */ @@ -1158,7 +1162,6 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) { Curve *cu = ct->tar->data; float vec[4], dir[3], radius; - float totmat[4][4] = MAT4_UNITY; float curvetime; unit_m4(ct->matrix); @@ -1206,6 +1209,9 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra } if (where_on_path(ct->tar, curvetime, vec, dir, (data->followflag & FOLLOWPATH_FOLLOW) ? quat : NULL, &radius, NULL) ) { /* quat_pt is quat or NULL*/ + float totmat[4][4]; + unit_m4(totmat); + if (data->followflag & FOLLOWPATH_FOLLOW) { #if 0 float x1, q[4]; @@ -2611,6 +2617,8 @@ static void stretchto_new_data(void *cdata) data->plane = 0; data->orglength = 0.0; data->bulge = 1.0; + data->bulge_max = 1.0f; + data->bulge_min = 1.0f; } static void stretchto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) @@ -2656,7 +2664,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t if (VALID_CONS_TARGET(ct)) { float size[3], scale[3], vec[3], xx[3], zz[3], orth[3]; float totmat[3][3]; - float dist; + float dist, bulge; /* store scaling before destroying obmat */ mat4_to_size(size, cob->matrix); @@ -2674,7 +2682,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t /* vec[2] /= size[2];*/ /* dist = normalize_v3(vec);*/ - + dist = len_v3v3(cob->matrix[3], ct->matrix[3]); /* Only Y constrained object axis scale should be used, to keep same length when scaling it. */ dist /= size[1]; @@ -2682,23 +2690,49 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t /* data->orglength==0 occurs on first run, and after 'R' button is clicked */ if (data->orglength == 0) data->orglength = dist; - if (data->bulge == 0) - data->bulge = 1.0; - + scale[1] = dist / data->orglength; + + bulge = powf(data->orglength / dist, data->bulge); + + if (bulge > 1.0f) { + if (data->flag & STRETCHTOCON_USE_BULGE_MAX) { + float bulge_max = max_ff(data->bulge_max, 1.0f); + float hard = min_ff(bulge, bulge_max); + + float range = bulge_max - 1.0f; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (0.5f * M_PI); + + bulge = interpf(soft, hard, data->bulge_smooth); + } + } + if (bulge < 1.0f) { + if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { + float bulge_min = CLAMPIS(data->bulge_max, 0.0f, 1.0f); + float hard = max_ff(bulge, bulge_min); + + float range = 1.0f - bulge_min; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (0.5f * M_PI); + + bulge = interpf(soft, hard, data->bulge_smooth); + } + } + switch (data->volmode) { /* volume preserving scaling */ case VOLUME_XZ: - scale[0] = 1.0f - sqrtf(data->bulge) + sqrtf(data->bulge * (data->orglength / dist)); + scale[0] = sqrtf(bulge); scale[2] = scale[0]; break; case VOLUME_X: - scale[0] = 1.0f + data->bulge * (data->orglength / dist - 1); + scale[0] = bulge; scale[2] = 1.0; break; case VOLUME_Z: scale[0] = 1.0; - scale[2] = 1.0f + data->bulge * (data->orglength / dist - 1); + scale[2] = bulge; break; /* don't care for volume */ case NO_VOLUME: @@ -3039,11 +3073,12 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) { float obmat[4][4], ownLoc[3]; float curveMin[3], curveMax[3]; - float targetMatrix[4][4] = MAT4_UNITY; + float targetMatrix[4][4]; copy_m4_m4(obmat, cob->matrix); copy_v3_v3(ownLoc, obmat[3]); + unit_m4(targetMatrix); INIT_MINMAX(curveMin, curveMax); /* XXX - don't think this is good calling this here - campbell */ BKE_object_minmax(ct->tar, curveMin, curveMax, true); @@ -3267,7 +3302,9 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t to_max = data->to_max_scale; for (i = 0; i < 3; i++) { /* multiply with original scale (so that it can still be scaled) */ - size[i] *= to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); + /* size[i] *= to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); */ + /* Stay absolute, else it breaks existing rigs... sigh. */ + size[i] = to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); } break; case TRANS_ROTATION: @@ -3370,7 +3407,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra unit_m4(ct->matrix); if (target != NULL) { - space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat); + BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->obmat); switch (scon->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: @@ -3392,7 +3429,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra break; } - space_transform_apply(&transform, co); + BLI_space_transform_apply(&transform, co); BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData); @@ -3400,7 +3437,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra if (dist != 0.0f) { interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist) / dist); /* linear interpolation */ } - space_transform_invert(&transform, co); + BLI_space_transform_invert(&transform, co); break; } case MOD_SHRINKWRAP_PROJECT: @@ -3587,7 +3624,7 @@ static void damptrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t cross_v3_v3v3(raxis, obvec, tarvec); rangle = dot_v3v3(obvec, tarvec); - rangle = acos(max_ff(-1.0f, min_ff(1.0f, rangle))); + rangle = acosf(max_ff(-1.0f, min_ff(1.0f, rangle))); /* construct rotation matrix from the axis-angle rotation found above * - this call takes care to make sure that the axis provided is a unit vector first @@ -3904,7 +3941,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, imat); invert_m4(imat); - mul_serie_m4(cob->matrix, obmat, mat, imat, NULL, NULL, NULL, NULL, NULL); + mul_m4_series(cob->matrix, obmat, mat, imat); translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); } else { @@ -3938,19 +3975,31 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (len > FLT_EPSILON) { CameraParams params; + int width, height; float pos[2], rmat[4][4]; + BKE_movieclip_get_size(clip, NULL, &width, &height); + marker = BKE_tracking_marker_get(track, framenr); add_v2_v2v2(pos, marker->pos, track->offset); + if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) { + /* Undistortion need to happen in pixel space. */ + pos[0] *= width; + pos[1] *= height; + + BKE_tracking_undistort_v2(tracking, pos, pos); + + /* Normalize pixel coordinates back. */ + pos[0] /= width; + pos[1] /= height; + } + /* aspect correction */ if (data->frame_method != FOLLOWTRACK_FRAME_STRETCH) { - int width, height; float w_src, h_src, w_dst, h_dst, asp_src, asp_dst; - BKE_movieclip_get_size(clip, NULL, &width, &height); - /* apply clip display aspect */ w_src = width * clip->aspx; h_src = height * clip->aspy; @@ -4182,7 +4231,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase invert_m4_m4(imat, mat); - mul_serie_m4(cob->matrix, cammat, imat, camimat, parmat, obmat, NULL, NULL, NULL); + mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat); } } } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 89ba2e9d68b..de285f87444 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -48,7 +48,6 @@ #include "BKE_context.h" #include "BKE_main.h" #include "BKE_screen.h" -#include "BKE_freestyle.h" #include "RNA_access.h" @@ -290,7 +289,7 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res return done; /* we check recursion to ensure that we do not get infinite - * loops requesting data from ourselfs in a context callback */ + * loops requesting data from ourselves in a context callback */ /* Ok, this looks evil... * if (ret) done = -(-ret | -done); @@ -1091,16 +1090,3 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_pose_bones", list); } - -FreestyleLineStyle *CTX_data_linestyle_from_scene(Scene *scene) -{ - SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleConfig *config = &actsrl->freestyleConfig; - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); - - if (lineset) { - return lineset->linestyle; - } - - return NULL; -} diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 3fde1cdd710..911bb19a594 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -40,7 +40,6 @@ #include "BLI_utildefines.h" #include "BLI_math.h" -#include "BLI_bitmap.h" #include "BKE_crazyspace.h" #include "BKE_DerivedMesh.h" @@ -49,11 +48,6 @@ #include "BKE_mesh.h" #include "BKE_editmesh.h" -typedef struct { - float (*vertexcos)[3]; - BLI_bitmap *vertex_visit; -} MappedUserData; - BLI_INLINE void tan_calc_quat_v3( float r_quat[4], const float co_1[3], const float co_2[3], const float co_3[3]) @@ -88,20 +82,6 @@ static void set_crazy_vertex_quat( sub_qt_qtqt(r_quat, q2, q1); } -static void make_vertexcos__mapFunc(void *userData, int index, const float co[3], - const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) -{ - MappedUserData *mappedData = (MappedUserData *)userData; - - if (BLI_BITMAP_GET(mappedData->vertex_visit, index) == 0) { - /* we need coord from prototype vertex, not from copies, - * assume they stored in the beginning of vertex array stored in DM - * (mirror modifier for eg does this) */ - copy_v3_v3(mappedData->vertexcos[index], co); - BLI_BITMAP_SET(mappedData->vertex_visit, index); - } -} - static int modifiers_disable_subsurf_temporary(Object *ob) { ModifierData *md; @@ -124,8 +104,6 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3] DerivedMesh *dm; float (*vertexcos)[3]; int nverts = me->edit_btmesh->bm->totvert; - BLI_bitmap *vertex_visit; - MappedUserData userData; /* disable subsurf temporal, get mapped cos, and enable it */ if (modifiers_disable_subsurf_temporary(obedit)) { @@ -134,22 +112,17 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3] } /* now get the cage */ - dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); + vertexcos = MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map"); - vertexcos = MEM_callocN(sizeof(*vertexcos) * nverts, "vertexcos map"); - vertex_visit = BLI_BITMAP_NEW(nverts, "vertexcos flags"); + dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); - userData.vertexcos = vertexcos; - userData.vertex_visit = vertex_visit; - dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP); + mesh_get_mapped_verts_coords(dm, vertexcos, nverts); dm->release(dm); /* set back the flag, no new cage needs to be built, transform does it */ modifiers_disable_subsurf_temporary(obedit); - MEM_freeN(vertex_visit); - return vertexcos; } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 14fd44e594a..ca58035d638 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -52,6 +52,7 @@ #include "BKE_animsys.h" #include "BKE_curve.h" +#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_font.h" #include "BKE_global.h" @@ -642,8 +643,9 @@ void BKE_nurb_test2D(Nurb *nu) } } -/* if use_radius is truth, minmax will take points' radius into account, - * which will make boundbox closer to bevelled curve. +/** + * if use_radius is truth, minmax will take points' radius into account, + * which will make boundbox closer to beveled curve. */ void BKE_nurb_minmax(Nurb *nu, bool use_radius, float min[3], float max[3]) { @@ -717,7 +719,7 @@ void BKE_nurb_bezierPoints_add(Nurb *nu, int number) BezTriple *bezt; int i; - nu->bezt = MEM_recallocN(nu->bp, (nu->pntsu + number) * sizeof(BezTriple)); + nu->bezt = MEM_recallocN(nu->bezt, (nu->pntsu + number) * sizeof(BezTriple)); for (i = 0, bezt = &nu->bezt[nu->pntsu]; i < number; i++, bezt++) { bezt->radius = 1.0f; @@ -1085,12 +1087,6 @@ void BKE_nurb_makeFaces(Nurb *nu, float *coord_array, int rowstride, int resolu, sum = (float *)MEM_callocN(sizeof(float) * len, "makeNurbfaces1"); - len = totu * totv; - if (len == 0) { - MEM_freeN(sum); - return; - } - bp = nu->bp; i = nu->pntsu * nu->pntsv; ratcomp = 0; @@ -1193,6 +1189,8 @@ void BKE_nurb_makeFaces(Nurb *nu, float *coord_array, int rowstride, int resolu, } } + zero_v3(in); + /* one! (1.0) real point now */ fp = sum; for (j = jsta; j <= jen; j++) { @@ -1307,6 +1305,8 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float * } } + zero_v3(coord_fp); + /* one! (1.0) real point */ fp = sum; bp = nu->bp + istart - 1; @@ -1473,7 +1473,7 @@ float *BKE_curve_surf_make_orco(Object *ob) } else { int size = (nu->pntsu * resolu) * (nu->pntsv * resolv) * 3 * sizeof(float); - float *_tdata = MEM_callocN(size, "temp data"); + float *_tdata = MEM_mallocN(size, "temp data"); float *tdata = _tdata; BKE_nurb_makeFaces(nu, tdata, 0, resolu, resolv); @@ -1676,7 +1676,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, } else if (cu->ext2 == 0.0f) { dl = MEM_callocN(sizeof(DispList), "makebevelcurve2"); - dl->verts = MEM_mallocN(2 * 3 * sizeof(float), "makebevelcurve2"); + dl->verts = MEM_mallocN(2 * sizeof(float[3]), "makebevelcurve2"); BLI_addtail(disp, dl); dl->type = DL_SEGM; dl->parts = 1; @@ -1693,7 +1693,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, nr = 4 + 2 * cu->bevresol; dl = MEM_callocN(sizeof(DispList), "makebevelcurve p1"); - dl->verts = MEM_mallocN(nr * 3 * sizeof(float), "makebevelcurve p1"); + dl->verts = MEM_mallocN(nr * sizeof(float[3]), "makebevelcurve p1"); BLI_addtail(disp, dl); dl->type = DL_POLY; dl->parts = 1; @@ -1725,7 +1725,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, nr = 3 + 2 * cu->bevresol; dl = MEM_callocN(sizeof(DispList), "makebevelcurve p1"); - dl->verts = MEM_mallocN(nr * 3 * sizeof(float), "makebevelcurve p1"); + dl->verts = MEM_mallocN(nr * sizeof(float[3]), "makebevelcurve p1"); BLI_addtail(disp, dl); dl->type = DL_SEGM; dl->parts = 1; @@ -1751,7 +1751,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, nr = 2; dl = MEM_callocN(sizeof(DispList), "makebevelcurve p2"); - dl->verts = MEM_callocN(nr * 3 * sizeof(float), "makebevelcurve p2"); + dl->verts = MEM_mallocN(nr * sizeof(float[3]), "makebevelcurve p2"); BLI_addtail(disp, dl); dl->type = DL_SEGM; dl->parts = 1; @@ -1783,7 +1783,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, nr = 3 + 2 * cu->bevresol; dl = MEM_callocN(sizeof(DispList), "makebevelcurve p3"); - dl->verts = MEM_mallocN(nr * 3 * sizeof(float), "makebevelcurve p3"); + dl->verts = MEM_mallocN(nr * sizeof(float[3]), "makebevelcurve p3"); BLI_addtail(disp, dl); dl->type = DL_SEGM; dl->flag = DL_FRONT_CURVE; @@ -1855,7 +1855,7 @@ static bool bevelinside(BevList *bl1, BevList *bl2) /* take first vertex of possible hole */ - bevp = (BevPoint *)(bl2 + 1); + bevp = bl2->bevpoints; hvec1[0] = bevp->vec[0]; hvec1[1] = bevp->vec[1]; hvec1[2] = 0.0; @@ -1865,7 +1865,7 @@ static bool bevelinside(BevList *bl1, BevList *bl2) /* test it with all edges of potential surounding poly */ /* count number of transitions left-right */ - bevp = (BevPoint *)(bl1 + 1); + bevp = bl1->bevpoints; nr = bl1->nr; prevbevp = bevp + (nr - 1); @@ -2051,7 +2051,7 @@ static void bevel_list_calc_bisect(BevList *bl) bool is_cyclic = bl->poly != -1; if (is_cyclic) { - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; nr = bl->nr; @@ -2065,7 +2065,7 @@ static void bevel_list_calc_bisect(BevList *bl) * of direction for this guys. */ - bevp0 = (BevPoint *)(bl + 1); + bevp0 = bl->bevpoints; bevp1 = bevp0 + 1; bevp2 = bevp1 + 1; @@ -2086,7 +2086,7 @@ static void bevel_list_flip_tangents(BevList *bl) BevPoint *bevp2, *bevp1, *bevp0; int nr; - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; @@ -2107,7 +2107,7 @@ static void bevel_list_apply_tilt(BevList *bl) int nr; float q[4]; - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); nr = bl->nr; @@ -2131,7 +2131,7 @@ static void bevel_list_smooth(BevList *bl, int smooth_iter) int a; for (a = 0; a < smooth_iter; a++) { - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; @@ -2177,7 +2177,7 @@ static void bevel_list_smooth(BevList *bl, int smooth_iter) static void make_bevel_list_3D_zup(BevList *bl) { - BevPoint *bevp = (BevPoint *)(bl + 1); + BevPoint *bevp = bl->bevpoints; int nr = bl->nr; bevel_list_calc_bisect(bl); @@ -2212,7 +2212,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl) bevel_list_calc_bisect(bl); - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; @@ -2250,7 +2250,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl) BevPoint *bevp_last; - bevp_first = (BevPoint *)(bl + 1); + bevp_first = bl->bevpoints; bevp_first += bl->nr - 1; bevp_last = bevp_first; bevp_last--; @@ -2278,7 +2278,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl) if (angle_normalized_v3v3(bevp_first->dir, cross_tmp) < DEG2RADF(90.0f)) angle = -angle; - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; @@ -2300,11 +2300,11 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl) * using it's own direction, which might not correspond * the twist of neighbor point. */ - bevp1 = (BevPoint *)(bl + 1); + bevp1 = bl->bevpoints; bevp0 = bevp1 + 1; minimum_twist_between_two_points(bevp1, bevp0); - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; minimum_twist_between_two_points(bevp1, bevp0); @@ -2322,7 +2322,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) bevel_list_flip_tangents(bl); /* correct the tangents */ - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; @@ -2340,7 +2340,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) /* now for the real twist calc */ - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; @@ -2387,7 +2387,7 @@ static void make_bevel_list_segment_3D(BevList *bl) { float q[4]; - BevPoint *bevp2 = (BevPoint *)(bl + 1); + BevPoint *bevp2 = bl->bevpoints; BevPoint *bevp1 = bevp2 + 1; /* simple quat/dir */ @@ -2406,7 +2406,7 @@ static void make_bevel_list_segment_3D(BevList *bl) /* only for 2 points */ static void make_bevel_list_segment_2D(BevList *bl) { - BevPoint *bevp2 = (BevPoint *)(bl + 1); + BevPoint *bevp2 = bl->bevpoints; BevPoint *bevp1 = bevp2 + 1; const float x1 = bevp1->vec[0] - bevp2->vec[0]; @@ -2429,13 +2429,13 @@ static void make_bevel_list_2D(BevList *bl) int nr; if (bl->poly != -1) { - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; bevp1 = bevp2 + (bl->nr - 1); bevp0 = bevp1 - 1; nr = bl->nr; } else { - bevp0 = (BevPoint *)(bl + 1); + bevp0 = bl->bevpoints; bevp1 = bevp0 + 1; bevp2 = bevp1 + 1; @@ -2467,16 +2467,16 @@ static void make_bevel_list_2D(BevList *bl) float angle; /* first */ - bevp = (BevPoint *)(bl + 1); - angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0; + bevp = bl->bevpoints; + angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)(M_PI / 2.0f); bevp->sina = sinf(angle); bevp->cosa = cosf(angle); vec_to_quat(bevp->quat, bevp->dir, 5, 1); /* last */ - bevp = (BevPoint *)(bl + 1); + bevp = bl->bevpoints; bevp += (bl->nr - 1); - angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0; + angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)(M_PI / 2.0f); bevp->sina = sinf(angle); bevp->cosa = cosf(angle); vec_to_quat(bevp->quat, bevp->dir, 5, 1); @@ -2489,7 +2489,7 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl) BPoint *first_bp = nu->bp, *last_bp = nu->bp + (nu->pntsu - 1); BevPoint *first_bevp, *last_bevp; - first_bevp = (BevPoint *)(bl + 1); + first_bevp = bl->bevpoints; last_bevp = first_bevp + (bl->nr - 1); sub_v3_v3v3(first_bevp->dir, (first_bp + 1)->vec, first_bp->vec); @@ -2500,29 +2500,53 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl) } } +void BKE_curve_bevelList_free(ListBase *bev) +{ + BevList *bl, *blnext; + for (bl = bev->first; bl != NULL; bl = blnext) { + blnext = bl->next; + if (bl->seglen != NULL) { + MEM_freeN(bl->seglen); + } + if (bl->segbevcount != NULL) { + MEM_freeN(bl->segbevcount); + } + MEM_freeN(bl); + } + bev->first = bev->last = NULL; +} + void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) { /* * - convert all curves to polys, with indication of resol and flags for double-vertices * - possibly; do a smart vertice removal (in case Nurb) - * - separate in individual blicks with BoundBox + * - separate in individual blocks with BoundBox * - AutoHole detection */ - Curve *cu; + + /* this function needs an object, because of tflag and upflag */ + Curve *cu = ob->data; Nurb *nu; BezTriple *bezt, *prevbezt; BPoint *bp; BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; + const float treshold = 0.00001f; float min, inp; + float *seglen; struct BevelSort *sortdata, *sd, *sd1; - int a, b, nr, poly, resolu = 0, len = 0; + int a, b, nr, poly, resolu = 0, len = 0, segcount; + int *segbevcount; bool do_tilt, do_radius, do_weight; bool is_editmode = false; ListBase *bev; - /* this function needs an object, because of tflag and upflag */ - cu = ob->data; + /* segbevcount alsp requires seglen. */ + const bool need_seglen = + ELEM(cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) || + ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE); + bev = &ob->curve_cache->bev; @@ -2531,7 +2555,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* STEP 1: MAKE POLYS */ - BLI_freelistN(&(ob->curve_cache->bev)); + BKE_curve_bevelList_free(&ob->curve_cache->bev); nu = nurbs->first; if (cu->editnurb && ob->type != OB_FONT) { is_editmode = 1; @@ -2561,17 +2585,26 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) else resolu = nu->resolu; + segcount = SEGMENTSU(nu); + if (nu->type == CU_POLY) { len = nu->pntsu; bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2"); + if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { + bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList2_seglen"); + bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList2_segbevcount"); + } BLI_addtail(bev, bl); bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; bl->nr = len; bl->dupe_nr = 0; bl->charidx = nu->charidx; - bevp = (BevPoint *)(bl + 1); + bevp = bl->bevpoints; + bevp->offset = 0; bp = nu->bp; + seglen = bl->seglen; + segbevcount = bl->segbevcount; while (len--) { copy_v3_v3(bevp->vec, bp->vec); @@ -2579,8 +2612,19 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) bevp->radius = bp->radius; bevp->weight = bp->weight; bevp->split_tag = true; - bevp++; bp++; + if (seglen != NULL && len != 0) { + *seglen = len_v3v3(bevp->vec, bp->vec); + bevp++; + bevp->offset = *seglen; + if (*seglen > treshold) *segbevcount = 1; + else *segbevcount = 0; + seglen++; + segbevcount++; + } + else { + bevp++; + } } if ((nu->flagu & CU_NURB_CYCLIC) == 0) { @@ -2589,13 +2633,27 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) } else if (nu->type == CU_BEZIER) { /* in case last point is not cyclic */ - len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1; + len = segcount * resolu + 1; + bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints"); + if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { + bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelBPoints_seglen"); + bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelBPoints_segbevcount"); + } BLI_addtail(bev, bl); bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; bl->charidx = nu->charidx; - bevp = (BevPoint *)(bl + 1); + + bevp = bl->bevpoints; + seglen = bl->seglen; + segbevcount = bl->segbevcount; + + bevp->offset = 0; + if (seglen != NULL) { + *seglen = 0; + *segbevcount = 0; + } a = nu->pntsu - 1; bezt = nu->bezt; @@ -2611,6 +2669,8 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) sub_v3_v3v3(bevp->dir, prevbezt->vec[2], prevbezt->vec[1]); normalize_v3(bevp->dir); + BLI_assert(segcount >= a); + while (a--) { if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { @@ -2623,6 +2683,14 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) bevp++; bl->nr++; bl->dupe_nr = 1; + if (seglen != NULL) { + *seglen = len_v3v3(prevbezt->vec[1], bezt->vec[1]); + bevp->offset = *seglen; + seglen++; + /* match segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (bevp->offset > treshold) *segbevcount = 1; + segbevcount++; + } } else { /* always do all three, to prevent data hanging around */ @@ -2660,8 +2728,28 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) else if (prevbezt->h2 == 0 || prevbezt->h2 == HD_VECT) bevp->split_tag = true; } + + /* seglen */ + if (seglen != NULL) { + *seglen = 0; + *segbevcount = 0; + for (j = 0; j < resolu; j++) { + bevp0 = bevp; + bevp++; + bevp->offset = len_v3v3(bevp0->vec, bevp->vec); + /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (bevp->offset > treshold) { + *seglen += bevp->offset; + *segbevcount += 1; + } + } + seglen++; + segbevcount++; + } + else { + bevp += resolu; + } bl->nr += resolu; - bevp += resolu; } prevbezt = bezt; bezt++; @@ -2681,15 +2769,22 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) } else if (nu->type == CU_NURBS) { if (nu->pntsv == 1) { - len = (resolu * SEGMENTSU(nu)); + len = (resolu * segcount); bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3"); + if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { + bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList3_seglen"); + bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList3_segbevcount"); + } BLI_addtail(bev, bl); bl->nr = len; bl->dupe_nr = 0; bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; bl->charidx = nu->charidx; - bevp = (BevPoint *)(bl + 1); + + bevp = bl->bevpoints; + seglen = bl->seglen; + segbevcount = bl->segbevcount; BKE_nurb_makeCurve(nu, &bevp->vec[0], do_tilt ? &bevp->alfa : NULL, @@ -2697,6 +2792,31 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) do_weight ? &bevp->weight : NULL, resolu, sizeof(BevPoint)); + /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (seglen != NULL) { + nr = segcount; + bevp0 = bevp; + bevp++; + while (nr) { + int j; + *seglen = 0; + *segbevcount = 0; + /* We keep last bevel segment zero-length. */ + for (j = 0; j < ((nr == 1) ? (resolu - 1) : resolu); j++) { + bevp->offset = len_v3v3(bevp0->vec, bevp->vec); + if (bevp->offset > treshold) { + *seglen += bevp->offset; + *segbevcount += 1; + } + bevp0 = bevp; + bevp++; + } + seglen++; + segbevcount++; + nr--; + } + } + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { bevlist_firstlast_direction_calc_from_bpoint(nu, bl); } @@ -2712,20 +2832,29 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) bool is_cyclic = bl->poly != -1; nr = bl->nr; if (is_cyclic) { - bevp1 = (BevPoint *)(bl + 1); + bevp1 = bl->bevpoints; bevp0 = bevp1 + (nr - 1); } else { - bevp0 = (BevPoint *)(bl + 1); + bevp0 = bl->bevpoints; + bevp0->offset = 0; bevp1 = bevp0 + 1; } nr--; while (nr--) { - if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) { - if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) { - if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) { - bevp0->dupe_tag = true; - bl->dupe_nr++; + if (seglen != NULL) { + if (fabsf(bevp1->offset) < treshold) { + bevp0->dupe_tag = true; + bl->dupe_nr++; + } + } + else { + if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) { + if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) { + if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) { + bevp0->dupe_tag = true; + bl->dupe_nr++; + } } } } @@ -2742,11 +2871,13 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */ blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4"); memcpy(blnew, bl, sizeof(BevList)); + blnew->segbevcount = bl->segbevcount; + blnew->seglen = bl->seglen; blnew->nr = 0; BLI_remlink(bev, bl); BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */ - bevp0 = (BevPoint *)(bl + 1); - bevp1 = (BevPoint *)(blnew + 1); + bevp0 = bl->bevpoints; + bevp1 = blnew->bevpoints; nr = bl->nr; while (nr--) { if (bevp0->dupe_tag == 0) { @@ -2782,7 +2913,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) if (bl->poly > 0) { min = 300000.0; - bevp = (BevPoint *)(bl + 1); + bevp = bl->bevpoints; nr = bl->nr; while (nr--) { if (min > bevp->vec[0]) { @@ -2794,14 +2925,14 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) sd->bl = bl; sd->left = min; - bevp = (BevPoint *)(bl + 1); + bevp = bl->bevpoints; if (bevp1 == bevp) bevp0 = bevp + (bl->nr - 1); else bevp0 = bevp1 - 1; bevp = bevp + (bl->nr - 1); if (bevp1 == bevp) - bevp2 = (BevPoint *)(bl + 1); + bevp2 = bl->bevpoints; else bevp2 = bevp1 + 1; @@ -2840,7 +2971,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) for (a = 0; a < poly; a++, sd++) { if (sd->bl->hole == sd->dir) { bl = sd->bl; - bevp1 = (BevPoint *)(bl + 1); + bevp1 = bl->bevpoints; bevp2 = bevp1 + (bl->nr - 1); nr = bl->nr / 2; while (nr--) { @@ -2859,7 +2990,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* 2D Curves */ for (bl = bev->first; bl; bl = bl->next) { if (bl->nr < 2) { - BevPoint *bevp = (BevPoint *)(bl + 1); + BevPoint *bevp = bl->bevpoints; unit_qt(bevp->quat); } else if (bl->nr == 2) { /* 2 pnt, treat separate */ @@ -2874,7 +3005,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* 3D Curves */ for (bl = bev->first; bl; bl = bl->next) { if (bl->nr < 2) { - BevPoint *bevp = (BevPoint *)(bl + 1); + BevPoint *bevp = bl->bevpoints; unit_qt(bevp->quat); } else if (bl->nr == 2) { /* 2 pnt, treat separate */ @@ -3072,7 +3203,13 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n madd_v3_v3v3fl(p2_h2, p2, dvec_b, 1.0f / 3.0f); } - if (skip_align || (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) { + if (skip_align || + /* when one handle is free, alignming makes no sense, see: T35952 */ + (ELEM(HD_FREE, bezt->h1, bezt->h2)) || + /* also when no handles are aligned, skip this step */ + (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && + !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) + { /* handles need to be updated during animation and applying stuff like hooks, * but in such situations it's quite difficult to distinguish in which order * align handles should be aligned so skip them for now */ @@ -3081,13 +3218,11 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n len_a = len_v3v3(p2, p2_h1); len_b = len_v3v3(p2, p2_h2); - if (is_fcurve == false) { - if (len_a == 0.0f) - len_a = 1.0f; - if (len_b == 0.0f) - len_b = 1.0f; - len_ratio = len_a / len_b; - } + + if (len_a == 0.0f) len_a = 1.0f; + if (len_b == 0.0f) len_b = 1.0f; + + len_ratio = len_a / len_b; if (bezt->f1 & SELECT) { /* order of calculation */ if (ELEM(bezt->h2, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) { /* aligned */ @@ -3172,6 +3307,31 @@ void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */ calchandlesNurb_intern(nu, false); } +/** + * Workaround #BKE_nurb_handles_calc logic + * that makes unselected align to the selected handle. + */ +static void nurbList_handles_swap_select(Nurb *nu) +{ + BezTriple *bezt; + int i; + + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if ((bezt->f1 & SELECT) != (bezt->f3 & SELECT)) { + bezt->f1 ^= SELECT; + bezt->f3 ^= SELECT; + } + } +} + +/* internal use only (weak) */ +static void nurb_handles_calc__align_selected(Nurb *nu) +{ + nurbList_handles_swap_select(nu); + BKE_nurb_handles_calc(nu); + nurbList_handles_swap_select(nu); +} + /* similar to BKE_nurb_handle_calc but for curves and * figures out the previous and next for us */ void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt) @@ -3369,7 +3529,9 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) } bezt++; } - BKE_nurb_handles_calc(nu); + + /* like BKE_nurb_handles_calc but moves selected */ + nurb_handles_calc__align_selected(nu); } nu = nu->next; } @@ -3413,7 +3575,9 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) bezt++; } - BKE_nurb_handles_calc(nu); + + /* like BKE_nurb_handles_calc but moves selected */ + nurb_handles_calc__align_selected(nu); } } } @@ -3829,6 +3993,9 @@ bool BKE_nurb_order_clamp_v(struct Nurb *nu) return changed; } +/** + * \note caller must ensure active vertex remains valid. + */ bool BKE_nurb_type_convert(Nurb *nu, const short type, const bool use_handles) { BezTriple *bezt; @@ -3980,7 +4147,7 @@ ListBase *BKE_curve_nurbs_get(Curve *cu) void BKE_curve_nurb_active_set(Curve *cu, Nurb *nu) { if (nu == NULL) { - cu->actnu = -1; + cu->actnu = CU_ACT_NONE; } else { ListBase *nurbs = BKE_curve_editNurbs_get(cu); @@ -4010,13 +4177,18 @@ void BKE_curve_nurb_vert_active_set(Curve *cu, Nurb *nu, void *vert) if (nu) { BKE_curve_nurb_active_set(cu, nu); - if (nu->type == CU_BEZIER) { - BLI_assert(ARRAY_HAS_ITEM((BezTriple *)vert, nu->bezt, nu->pntsu)); - cu->actvert = (BezTriple *)vert - nu->bezt; + if (vert) { + if (nu->type == CU_BEZIER) { + BLI_assert(ARRAY_HAS_ITEM((BezTriple *)vert, nu->bezt, nu->pntsu)); + cu->actvert = (BezTriple *)vert - nu->bezt; + } + else { + BLI_assert(ARRAY_HAS_ITEM((BPoint *)vert, nu->bp, nu->pntsu * nu->pntsv)); + cu->actvert = (BPoint *)vert - nu->bp; + } } else { - BLI_assert(ARRAY_HAS_ITEM((BPoint *)vert, nu->bp, nu->pntsu * nu->pntsv)); - cu->actvert = (BPoint *)vert - nu->bp; + cu->actvert = CU_ACT_NONE; } } else { @@ -4139,7 +4311,50 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3]) return false; } -void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys) + +void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit_scale) +{ + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int i; + + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + i = nu->pntsu; + for (bezt = nu->bezt; i--; bezt++) { + mul_m4_v3(mat, bezt->vec[0]); + mul_m4_v3(mat, bezt->vec[1]); + mul_m4_v3(mat, bezt->vec[2]); + bezt->radius *= unit_scale; + } + BKE_nurb_handles_calc(nu); + } + else { + i = nu->pntsu * nu->pntsv; + for (bp = nu->bp; i--; bp++) + mul_m4_v3(mat, bp->vec); + } + } + + if (do_keys && cu->key) { + KeyBlock *kb; + for (kb = cu->key->block.first; kb; kb = kb->next) { + float *fp = kb->data; + for (i = kb->totelem; i--; fp += 3) { + mul_m4_v3(mat, fp); + } + } + } +} + +void BKE_curve_transform(Curve *cu, float mat[4][4], bool do_keys) +{ + float unit_scale = mat4_to_scale(mat); + BKE_curve_transform_ex(cu, mat, do_keys, unit_scale); +} + +void BKE_curve_translate(Curve *cu, float offset[3], bool do_keys) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); Nurb *nu; @@ -4226,10 +4441,49 @@ void BKE_curve_material_index_clear(Curve *cu) } } +int BKE_curve_material_index_validate(Curve *cu) +{ + const int curvetype = BKE_curve_type_get(cu); + bool is_valid = true; + + if (curvetype == OB_FONT) { + CharInfo *info = cu->strinfo; + const int max_idx = max_ii(0, cu->totcol); /* OB_FONT use 1 as first mat index, not 0!!! */ + int i; + for (i = cu->len_wchar - 1; i >= 0; i--, info++) { + if (info->mat_nr > max_idx) { + info->mat_nr = 0; + is_valid = false; + } + } + } + else { + Nurb *nu; + const int max_idx = max_ii(0, cu->totcol - 1); + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->mat_nr > max_idx) { + nu->mat_nr = 0; + if (curvetype == OB_CURVE) { + nu->charidx = 0; + } + is_valid = false; + } + } + } + + if (!is_valid) { + DAG_id_tag_update(&cu->id, OB_RECALC_DATA); + return true; + } + else { + return false; + } +} + void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect) { - r_rect->xmin = (cu->xof * cu->fsize) + tb->x; - r_rect->ymax = (cu->yof * cu->fsize) + tb->y + cu->fsize; + r_rect->xmin = cu->xof + tb->x; + r_rect->ymax = cu->yof + tb->y + cu->fsize; r_rect->xmax = r_rect->xmin + tb->w; r_rect->ymin = r_rect->ymax - tb->h; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index fd4350123b4..7684c5a3a42 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -129,21 +129,24 @@ typedef struct LayerTypeInfo { void (*set_default)(void *data, int count); /** functions necessary for geometry collapse */ - bool (*equal)(void *data1, void *data2); + bool (*equal)(const void *data1, const void *data2); void (*multiply)(void *data, float fac); void (*initminmax)(void *min, void *max); - void (*add)(void *data1, void *data2); - void (*dominmax)(void *data1, void *min, void *max); - void (*copyvalue)(void *source, void *dest); + void (*add)(void *data1, const void *data2); + void (*dominmax)(const void *data1, void *min, void *max); + void (*copyvalue)(const void *source, void *dest); /** a function to read data from a cdf file */ int (*read)(CDataFile *cdf, void *data, int count); /** a function to write data to a cdf file */ - int (*write)(CDataFile *cdf, void *data, int count); + int (*write)(CDataFile *cdf, const void *data, int count); /** a function to determine file size */ - size_t (*filesize)(CDataFile *cdf, void *data, int count); + size_t (*filesize)(CDataFile *cdf, const void *data, int count); + + /** a function to determine max allowed number of layers, should be NULL or return -1 if no limit */ + int (*layers_max)(void); } LayerTypeInfo; static void layerCopy_mdeformvert(const void *source, void *dest, @@ -379,6 +382,11 @@ static void layerDefault_tface(void *data, int count) tf[i] = default_tf; } +static int layerMaxNum_tface(void) +{ + return MAX_MTFACE; +} + static void layerCopy_propFloat(const void *source, void *dest, int count) { @@ -552,9 +560,9 @@ static int layerRead_mdisps(CDataFile *cdf, void *data, int count) return 1; } -static int layerWrite_mdisps(CDataFile *cdf, void *data, int count) +static int layerWrite_mdisps(CDataFile *cdf, const void *data, int count) { - MDisps *d = data; + const MDisps *d = data; int i; for (i = 0; i < count; ++i) { @@ -567,9 +575,9 @@ static int layerWrite_mdisps(CDataFile *cdf, void *data, int count) return 1; } -static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count) +static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), const void *data, int count) { - MDisps *d = data; + const MDisps *d = data; size_t size = 0; int i; @@ -612,9 +620,10 @@ static void layerFree_grid_paint_mask(void *data, int count, int UNUSED(size)) } /* --------- */ -static void layerCopyValue_mloopcol(void *source, void *dest) +static void layerCopyValue_mloopcol(const void *source, void *dest) { - MLoopCol *m1 = source, *m2 = dest; + const MLoopCol *m1 = source; + MLoopCol *m2 = dest; m2->r = m1->r; m2->g = m1->g; @@ -622,9 +631,9 @@ static void layerCopyValue_mloopcol(void *source, void *dest) m2->a = m1->a; } -static bool layerEqual_mloopcol(void *data1, void *data2) +static bool layerEqual_mloopcol(const void *data1, const void *data2) { - MLoopCol *m1 = data1, *m2 = data2; + const MLoopCol *m1 = data1, *m2 = data2; float r, g, b, a; r = m1->r - m2->r; @@ -645,9 +654,10 @@ static void layerMultiply_mloopcol(void *data, float fac) m->a = (float)m->a * fac; } -static void layerAdd_mloopcol(void *data1, void *data2) +static void layerAdd_mloopcol(void *data1, const void *data2) { - MLoopCol *m = data1, *m2 = data2; + MLoopCol *m = data1; + const MLoopCol *m2 = data2; m->r += m2->r; m->g += m2->g; @@ -655,9 +665,9 @@ static void layerAdd_mloopcol(void *data1, void *data2) m->a += m2->a; } -static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax) +static void layerDoMinMax_mloopcol(const void *data, void *vmin, void *vmax) { - MLoopCol *m = data; + const MLoopCol *m = data; MLoopCol *min = vmin, *max = vmax; if (m->r < min->r) min->r = m->r; @@ -743,16 +753,22 @@ static void layerInterp_mloopcol(void **sources, const float *weights, mc->a = (int)col.a; } -static void layerCopyValue_mloopuv(void *source, void *dest) +static int layerMaxNum_mloopcol(void) { - MLoopUV *luv1 = source, *luv2 = dest; + return MAX_MCOL; +} + +static void layerCopyValue_mloopuv(const void *source, void *dest) +{ + const MLoopUV *luv1 = source; + MLoopUV *luv2 = dest; copy_v2_v2(luv2->uv, luv1->uv); } -static bool layerEqual_mloopuv(void *data1, void *data2) +static bool layerEqual_mloopuv(const void *data1, const void *data2) { - MLoopUV *luv1 = data1, *luv2 = data2; + const MLoopUV *luv1 = data1, *luv2 = data2; return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f; } @@ -771,16 +787,18 @@ static void layerInitMinMax_mloopuv(void *vmin, void *vmax) INIT_MINMAX2(min->uv, max->uv); } -static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) +static void layerDoMinMax_mloopuv(const void *data, void *vmin, void *vmax) { - MLoopUV *min = vmin, *max = vmax, *luv = data; + const MLoopUV *luv = data; + MLoopUV *min = vmin, *max = vmax; minmax_v2v2_v2(min->uv, max->uv, luv->uv); } -static void layerAdd_mloopuv(void *data1, void *data2) +static void layerAdd_mloopuv(void *data1, const void *data2) { - MLoopUV *l1 = data1, *l2 = data2; + MLoopUV *l1 = data1; + const MLoopUV *l2 = data2; add_v2_v2(l1->uv, l2->uv); } @@ -815,16 +833,17 @@ static void layerInterp_mloopuv(void **sources, const float *weights, } /* origspace is almost exact copy of mloopuv's, keep in sync */ -static void layerCopyValue_mloop_origspace(void *source, void *dest) +static void layerCopyValue_mloop_origspace(const void *source, void *dest) { - OrigSpaceLoop *luv1 = source, *luv2 = dest; + const OrigSpaceLoop *luv1 = source; + OrigSpaceLoop *luv2 = dest; copy_v2_v2(luv2->uv, luv1->uv); } -static bool layerEqual_mloop_origspace(void *data1, void *data2) +static bool layerEqual_mloop_origspace(const void *data1, const void *data2) { - OrigSpaceLoop *luv1 = data1, *luv2 = data2; + const OrigSpaceLoop *luv1 = data1, *luv2 = data2; return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f; } @@ -843,16 +862,18 @@ static void layerInitMinMax_mloop_origspace(void *vmin, void *vmax) INIT_MINMAX2(min->uv, max->uv); } -static void layerDoMinMax_mloop_origspace(void *data, void *vmin, void *vmax) +static void layerDoMinMax_mloop_origspace(const void *data, void *vmin, void *vmax) { - OrigSpaceLoop *min = vmin, *max = vmax, *luv = data; + const OrigSpaceLoop *luv = data; + OrigSpaceLoop *min = vmin, *max = vmax; minmax_v2v2_v2(min->uv, max->uv, luv->uv); } -static void layerAdd_mloop_origspace(void *data1, void *data2) +static void layerAdd_mloop_origspace(void *data1, const void *data2) { - OrigSpaceLoop *l1 = data1, *l2 = data2; + OrigSpaceLoop *l1 = data1; + const OrigSpaceLoop *l2 = data2; add_v2_v2(l1->uv, l2->uv); } @@ -1085,12 +1106,12 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 4: CD_MFACE */ {sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL, NULL}, /* 5: CD_MTFACE */ - {sizeof(MTFace), "MTFace", 1, N_("UVMap"), layerCopy_tface, NULL, - layerInterp_tface, layerSwap_tface, layerDefault_tface}, + {sizeof(MTFace), "MTFace", 1, N_("UVMap"), layerCopy_tface, NULL, layerInterp_tface, layerSwap_tface, + layerDefault_tface, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface}, /* 6: CD_MCOL */ /* 4 MCol structs per face */ {sizeof(MCol) * 4, "MCol", 4, N_("Col"), NULL, NULL, layerInterp_mcol, - layerSwap_mcol, layerDefault_mcol}, + layerSwap_mcol, layerDefault_mcol, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_mloopcol}, /* 7: CD_ORIGINDEX */ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_origindex}, /* 8: CD_NORMAL */ @@ -1111,15 +1132,16 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(float) * 3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 15: CD_MTEXPOLY */ /* note, when we expose the UV Map / TexFace split to the user, change this back to face Texture */ - {sizeof(MTexPoly), "MTexPoly", 1, N_("UVMap") /* "Face Texture" */, NULL, NULL, NULL, NULL, NULL}, + {sizeof(MTexPoly), "MTexPoly", 1, N_("UVMap") /* "Face Texture" */, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface}, /* 16: CD_MLOOPUV */ {sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap"), NULL, NULL, layerInterp_mloopuv, NULL, NULL, layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv, - layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv}, + layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv, NULL, NULL, NULL, layerMaxNum_tface}, /* 17: CD_MLOOPCOL */ {sizeof(MLoopCol), "MLoopCol", 1, N_("Col"), NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, - layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol, NULL, NULL, NULL, layerMaxNum_mloopcol}, /* 18: CD_TANGENT */ {sizeof(float) * 4 * 4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 19: CD_MDISPS */ @@ -1311,7 +1333,8 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, /*const LayerTypeInfo *typeInfo;*/ CustomDataLayer *layer, *newlayer; void *data; - int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0; + int i, type, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0; + int number = 0, maxnumber = -1; bool changed = false; for (i = 0; i < source->totlayer; ++i) { @@ -1322,6 +1345,7 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, if (type != lasttype) { number = 0; + maxnumber = CustomData_layertype_layers_max(type); lastactive = layer->active; lastrender = layer->active_rnd; lastclone = layer->active_clone; @@ -1334,6 +1358,7 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, if (lastflag & CD_FLAG_NOCOPY) continue; else if (!(mask & CD_TYPE_AS_MASK(type))) continue; + else if ((maxnumber != -1) && (number >= maxnumber)) continue; else if (CustomData_get_layer_named(dest, type, layer->name)) continue; switch (alloctype) { @@ -2546,12 +2571,12 @@ void CustomData_bmesh_free_block(CustomData *data, void **block) /** * Same as #CustomData_bmesh_free_block but zero the memory rather then freeing. */ -void CustomData_bmesh_free_block_data(CustomData *data, void **block) +void CustomData_bmesh_free_block_data(CustomData *data, void *block) { const LayerTypeInfo *typeInfo; int i; - if (*block == NULL) + if (block == NULL) return; for (i = 0; i < data->totlayer; ++i) { @@ -2560,13 +2585,13 @@ void CustomData_bmesh_free_block_data(CustomData *data, void **block) if (typeInfo->free) { int offset = data->layers[i].offset; - typeInfo->free((char *)*block + offset, 1, typeInfo->size); + typeInfo->free((char *)block + offset, 1, typeInfo->size); } } } if (data->totsize) - memset(*block, 0, data->totsize); + memset(block, 0, data->totsize); } static void CustomData_bmesh_alloc_block(CustomData *data, void **block) @@ -2661,7 +2686,7 @@ void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) return (char *)block + data->layers[n].offset; } -bool CustomData_layer_has_math(struct CustomData *data, int layer_n) +bool CustomData_layer_has_math(const struct CustomData *data, int layer_n) { const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layer_n].type); @@ -2674,7 +2699,7 @@ bool CustomData_layer_has_math(struct CustomData *data, int layer_n) return false; } -bool CustomData_layer_has_interp(struct CustomData *data, int layer_n) +bool CustomData_layer_has_interp(const struct CustomData *data, int layer_n) { const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layer_n].type); @@ -2685,7 +2710,7 @@ bool CustomData_layer_has_interp(struct CustomData *data, int layer_n) return false; } -bool CustomData_has_math(struct CustomData *data) +bool CustomData_has_math(const struct CustomData *data) { int i; @@ -2700,7 +2725,7 @@ bool CustomData_has_math(struct CustomData *data) } /* a non bmesh version would have to check layer->data */ -bool CustomData_bmesh_has_free(struct CustomData *data) +bool CustomData_bmesh_has_free(const struct CustomData *data) { const LayerTypeInfo *typeInfo; int i; @@ -2716,7 +2741,7 @@ bool CustomData_bmesh_has_free(struct CustomData *data) return false; } -bool CustomData_has_interp(struct CustomData *data) +bool CustomData_has_interp(const struct CustomData *data) { int i; @@ -2732,7 +2757,7 @@ bool CustomData_has_interp(struct CustomData *data) /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to * another, while not overwriting anything else (e.g. flags)*/ -void CustomData_data_copy_value(int type, void *source, void *dest) +void CustomData_data_copy_value(int type, const void *source, void *dest) { const LayerTypeInfo *typeInfo = layerType_getInfo(type); @@ -2744,7 +2769,7 @@ void CustomData_data_copy_value(int type, void *source, void *dest) memcpy(dest, source, typeInfo->size); } -bool CustomData_data_equals(int type, void *data1, void *data2) +bool CustomData_data_equals(int type, const void *data1, const void *data2) { const LayerTypeInfo *typeInfo = layerType_getInfo(type); @@ -2762,7 +2787,7 @@ void CustomData_data_initminmax(int type, void *min, void *max) } -void CustomData_data_dominmax(int type, void *data, void *min, void *max) +void CustomData_data_dominmax(int type, const void *data, void *min, void *max) { const LayerTypeInfo *typeInfo = layerType_getInfo(type); @@ -2780,7 +2805,7 @@ void CustomData_data_multiply(int type, void *data, float fac) } -void CustomData_data_add(int type, void *data1, void *data2) +void CustomData_data_add(int type, void *data1, const void *data2) { const LayerTypeInfo *typeInfo = layerType_getInfo(type); @@ -3031,6 +3056,24 @@ bool CustomData_layertype_is_singleton(int type) return typeInfo->defaultname == NULL; } +/** + * \return Maximum number of layers of given \a type, -1 means 'no limit'. + */ +int CustomData_layertype_layers_max(const int type) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + /* Same test as for singleton above. */ + if (typeInfo->defaultname == NULL) { + return 1; + } + else if (typeInfo->layers_max == NULL) { + return -1; + } + + return typeInfo->layers_max(); +} + static bool CustomData_is_property_layer(int type) { if ((type == CD_PROP_FLT) || (type == CD_PROP_INT) || (type == CD_PROP_STR)) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index d072088ac8e..528ff2d7b19 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -559,7 +559,7 @@ void defgroup_unique_name(bDeformGroup *dg, Object *ob) static bool is_char_sep(const char c) { - return ELEM4(c, '.', ' ', '-', '_'); + return ELEM(c, '.', ' ', '-', '_'); } /* based on BLI_split_dirfile() / os.path.splitext(), "a.b.c" -> ("a.b", ".c") */ @@ -614,6 +614,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ char replace[MAX_VGROUP_NAME] = ""; /* The replacement string */ char number[MAX_VGROUP_NAME] = ""; /* The number extension string */ char *index = NULL; + bool is_set = false; /* always copy the name, since this can be called with an uninitialized string */ BLI_strncpy(name, from_name, MAX_VGROUP_NAME); @@ -640,6 +641,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ /* first case; separator . - _ with extensions r R l L */ if (is_char_sep(name[len - 2])) { + is_set = true; switch (name[len - 1]) { case 'l': prefix[len - 1] = 0; @@ -657,10 +659,14 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ prefix[len - 1] = 0; strcpy(replace, "L"); break; + default: + is_set = false; } } + /* case; beginning with r R l L, with separator after it */ - else if (is_char_sep(name[1])) { + if (!is_set && is_char_sep(name[1])) { + is_set = true; switch (name[0]) { case 'l': strcpy(replace, "r"); @@ -682,40 +688,43 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ BLI_strncpy(suffix, name + 1, sizeof(suffix)); prefix[0] = 0; break; + default: + is_set = false; } } - else if (len > 5) { + + if (!is_set && len > 5) { /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */ - index = BLI_strcasestr(prefix, "right"); - if (index == prefix || index == prefix + len - 5) { - if (index[0] == 'r') + if (((index = BLI_strcasestr(prefix, "right")) == prefix) || + (index == prefix + len - 5)) + { + is_set = true; + if (index[0] == 'r') { strcpy(replace, "left"); + } else { - if (index[1] == 'I') - strcpy(replace, "LEFT"); - else - strcpy(replace, "Left"); + strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left"); } *index = 0; BLI_strncpy(suffix, index + 5, sizeof(suffix)); } - else { - index = BLI_strcasestr(prefix, "left"); - if (index == prefix || index == prefix + len - 4) { - if (index[0] == 'l') - strcpy(replace, "right"); - else { - if (index[1] == 'E') - strcpy(replace, "RIGHT"); - else - strcpy(replace, "Right"); - } - *index = 0; - BLI_strncpy(suffix, index + 4, sizeof(suffix)); + else if (((index = BLI_strcasestr(prefix, "left")) == prefix) || + (index == prefix + len - 4)) + { + is_set = true; + if (index[0] == 'l') { + strcpy(replace, "right"); + } + else { + strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right"); } + *index = 0; + BLI_strncpy(suffix, index + 4, sizeof(suffix)); } } + (void)is_set; /* quiet warning */ + BLI_snprintf(name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number); } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 21579098266..44a0b93fc01 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -59,8 +59,10 @@ #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" +#include "BKE_anim.h" #include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_DerivedMesh.h" #include "BKE_effect.h" #include "BKE_fcurve.h" #include "BKE_global.h" @@ -73,12 +75,15 @@ #include "BKE_mball.h" #include "BKE_modifier.h" #include "BKE_object.h" +#include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_tracking.h" +#include "GPU_buffers.h" + #include "atomic_ops.h" #include "depsgraph_private.h" @@ -524,7 +529,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (ct->tar->type == OB_MESH) node3->customdata_mask |= CD_MASK_MDEFORMVERT; } - else if (ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) + else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name); else dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name); @@ -688,6 +693,29 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper"); } if (ob->type == OB_FONT) { + /* Really rather dirty hack. needs to support font family to work + * reliably on render export. + * + * This totally mimics behavior of regular verts duplication with + * parenting. The only tricky thing here is to get list of objects + * used for the custom "font". + * + * This shouldn't harm so much because this code only runs on DAG + * rebuild and this feature is not that commonly used. + * + * - sergey - + */ + if (cu->family[0] != '\n') { + ListBase *duplilist; + DupliObject *dob; + duplilist = object_duplilist(G.main->eval_ctx, scene, ob); + for (dob = duplilist->first; dob; dob = dob->next) { + node2 = dag_get_node(dag, dob->ob); + dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font"); + } + free_object_duplilist(duplilist); + } + if (cu->textoncurve) { node2 = dag_get_node(dag, cu->textoncurve); /* Text on curve requires path to be evaluated for the target curve. */ @@ -803,7 +831,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O continue; /* special case for camera tracking -- it doesn't use targets to define relations */ - if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { + if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { int depends_on_camera = 0; if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) { @@ -843,7 +871,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name); else { - if (ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { + if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name); if (obt->type == OB_MESH) node2->customdata_mask |= CD_MASK_MDEFORMVERT; @@ -1386,7 +1414,7 @@ static bool check_object_needs_evaluation(Object *object) if (object->type == OB_MESH) { return object->derivedFinal == NULL; } - else if (ELEM5(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { return object->curve_cache == NULL; } @@ -1400,7 +1428,7 @@ static bool check_object_tagged_for_update(Object *object) return true; } - if (ELEM6(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { ID *data_id = object->data; return (data_id->flag & (LIB_ID_RECALC_DATA | LIB_ID_RECALC)) != 0; } @@ -1747,7 +1775,8 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) } /* node was checked to have lasttime != curtime, and is of type ID_OB */ -static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, int curtime, int reset) +static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, + int curtime, unsigned int lay, bool reset) { DagAdjList *itA; Object *ob; @@ -1761,14 +1790,17 @@ static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, int if (reset || (ob->recalc & OB_RECALC_ALL)) { if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) { - ob->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &ob->id); + /* Don't tag nodes which are on invisible layer. */ + if (itA->node->lay & lay) { + ob->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &ob->id); + } } - flush_pointcache_reset(bmain, scene, itA->node, curtime, 1); + flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true); } else - flush_pointcache_reset(bmain, scene, itA->node, curtime, 0); + flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false); } } } @@ -1885,10 +1917,12 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho lib_id_recalc_data_tag(bmain, &ob->id); } - flush_pointcache_reset(bmain, sce, itA->node, lasttime, 1); + flush_pointcache_reset(bmain, sce, itA->node, lasttime, + lay, true); } else - flush_pointcache_reset(bmain, sce, itA->node, lasttime, 0); + flush_pointcache_reset(bmain, sce, itA->node, lasttime, + lay, false); } } } @@ -1983,7 +2017,7 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob) if (cti) { /* special case for camera tracking -- it doesn't use targets to define relations */ - if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { + if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { ob->recalc |= OB_RECALC_OB; } else if (cti->get_constraint_targets) { @@ -2272,7 +2306,7 @@ static void dag_group_on_visible_update(Group *group) group->id.flag |= LIB_DOIT; for (go = group->gobject.first; go; go = go->next) { - if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { go->ob->recalc |= OB_RECALC_DATA; go->ob->id.flag |= LIB_DOIT; lib_id_recalc_tag(G.main, &go->ob->id); @@ -2319,7 +2353,7 @@ void DAG_on_visible_update(Main *bmain, const bool do_time) oblay = (node) ? node->lay : ob->lay; if ((oblay & lay) & ~scene->lay_updated) { - if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { ob->recalc |= OB_RECALC_DATA; lib_id_recalc_tag(bmain, &ob->id); } @@ -2472,6 +2506,15 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); } + if (ELEM(idtype, ID_MA, ID_TE)) { + obt = sce->basact ? sce->basact->object : NULL; + if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) { + BKE_texpaint_slots_refresh_object(sce, obt); + BKE_paint_proj_mesh_data_check(sce, obt, NULL, NULL, NULL, NULL); + GPU_drawobject_free(obt->derivedFinal); + } + } + if (idtype == ID_MC) { MovieClip *clip = (MovieClip *) id; @@ -2481,7 +2524,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) bConstraint *con; for (con = obt->constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, + if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { obt->recalc |= OB_RECALC_OB; @@ -2502,6 +2545,23 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) } } + /* Not pretty to iterate all the nodes here, but it's as good as it + * could be with the current depsgraph design/ + */ + if (idtype == ID_IM) { + FOREACH_NODETREE(bmain, ntree, parent_id) { + if (ntree->type == NTREE_SHADER) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->id == id) { + lib_id_recalc_tag(bmain, &ntree->id); + break; + } + } + } + } FOREACH_NODETREE_END + } + if (idtype == ID_MSK) { if (sce->nodetree) { bNode *node; @@ -2742,7 +2802,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag) if (ob->type == OB_FONT) { Curve *cu = ob->data; - if (ELEM4((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) { + if (ELEM((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) { ob->recalc |= (flag & OB_RECALC_ALL); } } @@ -3106,7 +3166,17 @@ short DAG_get_eval_flags_for_object(Scene *scene, void *object) /* Happens when external render engine exports temporary objects * which are not in the DAG. */ + /* TODO(sergey): Doublecheck objects with Curve Deform exports all fine. */ + + /* TODO(sergey): Weak but currently we can't really access proper DAG from + * the modifiers stack. This is because in most cases modifier is to use + * the foreground scene, but to access evaluation flags we need to know + * active background scene, which we don't know. + */ + if (scene->set) { + return DAG_get_eval_flags_for_object(scene->set, object); + } return 0; } } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 8c21ee15da2..893c69741cd 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -71,8 +71,6 @@ void BKE_displist_elem_free(DispList *dl) if (dl->verts) MEM_freeN(dl->verts); if (dl->nors) MEM_freeN(dl->nors); if (dl->index) MEM_freeN(dl->index); - if (dl->col1) MEM_freeN(dl->col1); - if (dl->col2) MEM_freeN(dl->col2); if (dl->bevelSplitFlag) MEM_freeN(dl->bevelSplitFlag); MEM_freeN(dl); } @@ -124,7 +122,7 @@ bool BKE_displist_has_faces(ListBase *lb) DispList *dl; for (dl = lb->first; dl; dl = dl->next) { - if (ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { + if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { return true; } } @@ -145,8 +143,6 @@ void BKE_displist_copy(ListBase *lbn, ListBase *lb) dln->verts = MEM_dupallocN(dl->verts); dln->nors = MEM_dupallocN(dl->nors); dln->index = MEM_dupallocN(dl->index); - dln->col1 = MEM_dupallocN(dl->col1); - dln->col2 = MEM_dupallocN(dl->col2); if (dl->bevelSplitFlag) dln->bevelSplitFlag = MEM_dupallocN(dl->bevelSplitFlag); @@ -347,7 +343,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, dl = MEM_callocN(sizeof(DispList), "makeDispListbez"); /* len+1 because of 'forward_diff_bezier' function */ - dl->verts = MEM_callocN((len + 1) * 3 * sizeof(float), "dlverts"); + dl->verts = MEM_mallocN((len + 1) * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->parts = 1; dl->nr = len; @@ -401,7 +397,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, len = (resolu * SEGMENTSU(nu)); dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); - dl->verts = MEM_callocN(len * 3 * sizeof(float), "dlverts"); + dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->parts = 1; @@ -418,7 +414,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, else if (nu->type == CU_POLY) { len = nu->pntsu; dl = MEM_callocN(sizeof(DispList), "makeDispListpoly"); - dl->verts = MEM_callocN(len * 3 * sizeof(float), "dlverts"); + dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->parts = 1; dl->nr = len; @@ -657,8 +653,8 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis bevels_to_filledpoly(cu, dispbase); } else { - /* TODO, investigate passing zup instead of NULL */ - BKE_displist_fill(dispbase, dispbase, NULL, false); + const float z_up[3] = {0.0f, 0.0f, 1.0f}; + BKE_displist_fill(dispbase, dispbase, z_up, false); } } @@ -719,21 +715,20 @@ void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object * if (!ob || ob->type != OB_MBALL) return; - if (ob->curve_cache) { - BKE_displist_free(&(ob->curve_cache->disp)); - } - else { - ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); - } + if (ob == BKE_mball_basis_find(scene, ob)) { + if (ob->curve_cache) { + BKE_displist_free(&(ob->curve_cache->disp)); + } + else { + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + } - if (ob->type == OB_MBALL) { - if (ob == BKE_mball_basis_find(scene, ob)) { - BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp); - BKE_mball_texspace_calc(ob); + BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp); + BKE_mball_texspace_calc(ob); - object_deform_mball(ob, &ob->curve_cache->disp); - } + object_deform_mball(ob, &ob->curve_cache->disp); + /* NOP for MBALLs anyway... */ boundbox_displist_object(ob); } } @@ -771,7 +766,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, if (mti->type == eModifierTypeType_Constructive) return pretessellatePoint; - if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { + if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { pretessellatePoint = md; /* this modifiers are moving point of tessellation automatically @@ -1227,7 +1222,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, len = SEGMENTSU(nu) * resolu; dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); - dl->verts = MEM_callocN(len * 3 * sizeof(float), "dlverts"); + dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->parts = 1; @@ -1249,7 +1244,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, len = (nu->pntsu * resolu) * (nu->pntsv * resolv); dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); - dl->verts = MEM_callocN(len * 3 * sizeof(float), "dlverts"); + dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); BLI_addtail(dispbase, dl); dl->col = nu->mat_nr; @@ -1276,6 +1271,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, } if (!for_orco) { + BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase); curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); } @@ -1344,7 +1340,7 @@ static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *disp DispList *dl; dl = MEM_callocN(sizeof(DispList), "makeDispListbev2"); - dl->verts = MEM_mallocN(3 * sizeof(float) * dlb->nr, "dlverts"); + dl->verts = MEM_mallocN(sizeof(float[3]) * dlb->nr, "dlverts"); memcpy(dl->verts, prev_fp, 3 * sizeof(float) * dlb->nr); dl->type = DL_POLY; @@ -1361,47 +1357,85 @@ static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *disp BLI_addtail(dispbase, dl); } +static void calc_bevfac_segment_mapping(BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend) +{ + float normlen, normsum = 0.0f; + float *seglen = bl->seglen; + int *segbevcount = bl->segbevcount; + int bevcount = 0, nr = bl->nr; + + float bev_fl = bevfac * (bl->nr - 1); + *r_bev = (int)bev_fl; + + while (bevcount < nr - 1) { + normlen = *seglen / spline_length; + if (normsum + normlen > bevfac) { + bev_fl = bevcount + (bevfac - normsum) / normlen * *segbevcount; + *r_bev = (int) bev_fl; + *r_blend = bev_fl - *r_bev; + break; + } + normsum += normlen; + bevcount += *segbevcount; + segbevcount++; + seglen++; + } +} -static void calc_bevfac_spline_mapping(BevList *bl, float bevfac, float spline_length, const float *bevp_array, +static void calc_bevfac_spline_mapping(BevList *bl, float bevfac, + float spline_length, int *r_bev, float *r_blend) { - float len = 0.0f; - int i; - for (i = 0; i < bl->nr; i++) { - *r_bev = i; - *r_blend = (bevfac * spline_length - len) / bevp_array[i]; - if (len + bevp_array[i] > bevfac * spline_length) { + const float len_target = bevfac * spline_length; + BevPoint *bevp = bl->bevpoints; + float len_next = 0.0f, len = 0.0f; + int i = 0, nr = bl->nr; + + while (nr--) { + bevp++; + len_next = len + bevp->offset; + if (len_next > len_target) { break; } - len += bevp_array[i]; + len = len_next; + i++; } + + *r_bev = i; + *r_blend = (len_target - len) / bevp->offset; } -static void calc_bevfac_mapping(Curve *cu, BevList *bl, int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend) +static void calc_bevfac_mapping_default(BevList *bl, + int *r_start, float *r_firstblend, + int *r_steps, float *r_lastblend) { - BevPoint *bevp, *bevl; - float l, startf, endf, tmpf = 0.0, sum = 0.0, total_length = 0.0f; - float *bevp_array = NULL; - float *segments = NULL; - int end = 0, i, j, segcount = (int)(bl->nr / cu->resolu); - - if ((cu->bevfac1_mapping != CU_BEVFAC_MAP_RESOLU) || - (cu->bevfac2_mapping != CU_BEVFAC_MAP_RESOLU)) + *r_start = 0; + *r_steps = bl->nr; + *r_firstblend = 1.0f; + *r_lastblend = 1.0f; +} + +static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu, + int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend) +{ + float tmpf, total_length = 0.0f; + int end = 0, i; + + if ((BKE_nurb_check_valid_u(nu) == false) || + /* not essential, but skips unnecessary calculation */ + (min_ff(cu->bevfac1, cu->bevfac2) == 0.0f && + max_ff(cu->bevfac1, cu->bevfac2) == 1.0f)) { - bevp_array = MEM_mallocN(sizeof(*bevp_array) * (bl->nr - 1), "bevp_dists"); - segments = MEM_callocN(sizeof(*segments) * segcount, "bevp_segmentlengths"); - bevp = (BevPoint *)(bl + 1); - bevp++; - for (i = 1, j = 0; i < bl->nr; bevp++, i++) { - sum = 0.0f; - bevl = bevp - 1; - bevp_array[i - 1] = len_v3v3(bevp->vec, bevl->vec); - total_length += bevp_array[i - 1]; - tmpf += bevp_array[i - 1]; - if ((i % cu->resolu) == 0 || (bl->nr - 1) == i) { - segments[j++] = tmpf; - tmpf = 0.0f; - } + calc_bevfac_mapping_default(bl, r_start, r_firstblend, r_steps, r_lastblend); + return; + } + + if (ELEM(cu->bevfac1_mapping, + CU_BEVFAC_MAP_SEGMENT, + CU_BEVFAC_MAP_SPLINE)) + { + for (i = 0; i < SEGMENTSU(nu); i++) { + total_length += bl->seglen[i]; } } @@ -1410,36 +1444,23 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, int *r_start, float *r_f { const float start_fl = cu->bevfac1 * (bl->nr - 1); *r_start = (int)start_fl; - *r_firstblend = 1.0f - (start_fl - (*r_start)); break; } case CU_BEVFAC_MAP_SEGMENT: { - const float start_fl = cu->bevfac1 * (bl->nr - 1); - *r_start = (int)start_fl; - - for (i = 0; i < segcount; i++) { - l = segments[i] / total_length; - if (sum + l > cu->bevfac1) { - startf = i * cu->resolu + (cu->bevfac1 - sum) / l * cu->resolu; - *r_start = (int) startf; - *r_firstblend = 1.0f - (startf - *r_start); - break; - } - sum += l; - } + calc_bevfac_segment_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend); + *r_firstblend = 1.0f - *r_firstblend; break; } case CU_BEVFAC_MAP_SPLINE: { - calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, bevp_array, r_start, r_firstblend); + calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend); *r_firstblend = 1.0f - *r_firstblend; break; } } - sum = 0.0f; switch (cu->bevfac2_mapping) { case CU_BEVFAC_MAP_RESOLU: { @@ -1452,32 +1473,19 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, int *r_start, float *r_f } case CU_BEVFAC_MAP_SEGMENT: { - const float end_fl = cu->bevfac2 * (bl->nr - 1); - end = (int)end_fl; - + calc_bevfac_segment_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend); *r_steps = end - *r_start + 2; - for (i = 0; i < segcount; i++) { - l = segments[i] / total_length; - if (sum + l > cu->bevfac2) { - endf = i * cu->resolu + (cu->bevfac2 - sum) / l * cu->resolu; - end = (int)endf; - *r_lastblend = (endf - end); - *r_steps = end - *r_start + 2; - break; - } - sum += l; - } break; } case CU_BEVFAC_MAP_SPLINE: { - calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, bevp_array, &end, r_lastblend); + calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend); *r_steps = end - *r_start + 2; break; } } - if (end < *r_start) { + if (end < *r_start || (end == *r_start && *r_lastblend < 1.0f - *r_firstblend )) { SWAP(int, *r_start, end); tmpf = *r_lastblend; *r_lastblend = 1.0f - *r_firstblend; @@ -1489,13 +1497,6 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, int *r_start, float *r_f *r_steps = bl->nr - *r_start; *r_lastblend = 1.0f; } - - if (bevp_array) { - MEM_freeN(bevp_array); - } - if (segments) { - MEM_freeN(segments); - } } static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase, @@ -1505,7 +1506,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba Curve *cu = ob->data; /* we do allow duplis... this is only displist on curve level */ - if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; + if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; if (ob->type == OB_SURF) { BKE_displist_make_surf(scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution); @@ -1514,7 +1515,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba ListBase dlbev; ListBase nubase = {NULL, NULL}; - BLI_freelistN(&(ob->curve_cache->bev)); + BKE_curve_bevelList_free(&ob->curve_cache->bev); /* We only re-evlauate path if evaluation is not happening for orco. * If the calculation happens for orco, we should never free data which @@ -1552,15 +1553,15 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba for (; bl && nu; bl = bl->next, nu = nu->next) { DispList *dl; float *data; - BevPoint *bevp; int a; if (bl->nr) { /* blank bevel lists can happen */ /* exception handling; curve without bevel or extrude, with width correction */ if (BLI_listbase_is_empty(&dlbev)) { + BevPoint *bevp; dl = MEM_callocN(sizeof(DispList), "makeDispListbev"); - dl->verts = MEM_callocN(3 * sizeof(float) * bl->nr, "dlverts"); + dl->verts = MEM_mallocN(sizeof(float[3]) * bl->nr, "dlverts"); BLI_addtail(dispbase, dl); if (bl->poly != -1) dl->type = DL_POLY; @@ -1578,7 +1579,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba dl->rt = nu->flag & ~CU_2D; a = dl->nr; - bevp = (BevPoint *)(bl + 1); + bevp = bl->bevpoints; data = dl->verts; while (a--) { data[0] = bevp->vec[0] + widfac * bevp->sina; @@ -1597,13 +1598,25 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba float firstblend = 0.0f, lastblend = 0.0f; int i, start, steps; - calc_bevfac_mapping(cu, bl, &start, &firstblend, &steps, &lastblend); + if (nu->flagu & CU_NURB_CYCLIC) { + calc_bevfac_mapping_default(bl, + &start, &firstblend, &steps, &lastblend); + } + else { + if (fabsf(cu->bevfac2 - cu->bevfac1) < FLT_EPSILON) { + continue; + } + + calc_bevfac_mapping(cu, bl, nu, &start, &firstblend, &steps, &lastblend); + } for (dlb = dlbev.first; dlb; dlb = dlb->next) { + BevPoint *bevp_first, *bevp_last; + BevPoint *bevp; /* for each part of the bevel use a separate displblock */ dl = MEM_callocN(sizeof(DispList), "makeDispListbev1"); - dl->verts = data = MEM_callocN(3 * sizeof(float) * dlb->nr * steps, "dlverts"); + dl->verts = data = MEM_mallocN(sizeof(float[3]) * dlb->nr * steps, "dlverts"); BLI_addtail(dispbase, dl); dl->type = DL_SURF; @@ -1621,11 +1634,13 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba /* CU_2D conflicts with R_NOPUNOFLIP */ dl->rt = nu->flag & ~CU_2D; - dl->bevelSplitFlag = MEM_callocN(sizeof(*dl->col2) * ((steps + 0x1F) >> 5), + dl->bevelSplitFlag = MEM_callocN(sizeof(*dl->bevelSplitFlag) * ((steps + 0x1F) >> 5), "bevelSplitFlag"); /* for each point of poly make a bevel piece */ - bevp = (BevPoint *)(bl + 1) + start; + bevp_first = bl->bevpoints; + bevp_last = &bl->bevpoints[bl->nr - 1]; + bevp = &bl->bevpoints[start]; for (i = start, a = 0; a < steps; i++, bevp++, a++) { float fac = 1.0; float *cur_data = data; @@ -1664,12 +1679,15 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } /* rotate bevel piece and write in data */ - if (a == 0) + if ((a == 0) && (bevp != bevp_last)) { rotateBevelPiece(cu, bevp, bevp + 1, dlb, 1.0f - firstblend, widfac, fac, &data); - else if (a == steps - 1) + } + else if ((a == steps - 1) && (bevp != bevp_first) ) { rotateBevelPiece(cu, bevp, bevp - 1, dlb, 1.0f - lastblend, widfac, fac, &data); - else + } + else { rotateBevelPiece(cu, bevp, NULL, dlb, 0.0f, widfac, fac, &data); + } if (cu->bevobj && (cu->flag & CU_FILL_CAPS) && !(nu->flagu & CU_NURB_CYCLIC)) { if (a == 1) { @@ -1712,8 +1730,10 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } } - if (!for_orco) + if (!for_orco) { + BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase); curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); + } if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) { curve_to_filledpoly(cu, &nubase, dispbase); @@ -1730,7 +1750,7 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco) /* The same check for duplis as in do_makeDispListCurveTypes. * Happens when curve used for constraint/bevel was converted to mesh. * check there is still needed for render displist and orco displists. */ - if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) + if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; BKE_object_free_derived_caches(ob); @@ -1747,10 +1767,11 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco) } void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase, - DerivedMesh **r_dm_final, const bool for_orco, const bool use_render_resolution) + DerivedMesh **r_dm_final, const bool for_orco, + const bool use_render_resolution) { if (ob->curve_cache == NULL) { - ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } do_makeDispListCurveTypes(scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution); @@ -1759,7 +1780,7 @@ void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase * void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase) { if (ob->curve_cache == NULL) { - ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1); @@ -1814,8 +1835,8 @@ void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3]) /* this is confusing, there's also min_max_object, appplying the obmat... */ static void boundbox_displist_object(Object *ob) { - if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - /* Curver's BB is already calculated as a part of modifier stack, + if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + /* Curve's BB is already calculated as a part of modifier stack, * here we only calculate object BB based on final display list. */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 11737bccef2..4719013e2f8 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2942,9 +2942,10 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float c do { float nearest_tmp[3], dist_sq; - int vertex, edge; - - dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp); + + closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2); + dist_sq = len_squared_v3v3(co, nearest_tmp); + if (dist_sq < nearest->dist_sq) { nearest->index = index; nearest->dist_sq = dist_sq; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 99e7282fb79..ce7804d9878 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -41,8 +41,6 @@ * is likely to be a little slow. */ -#include "GL/glew.h" - #include "BLI_math.h" #include "BLI_jitter.h" #include "BLI_bitmap.h" @@ -58,6 +56,7 @@ #include "MEM_guardedalloc.h" #include "GPU_extensions.h" +#include "GPU_glew.h" extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ @@ -911,7 +910,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm, static void emDM_drawFacesTex(DerivedMesh *dm, DMSetDrawOptionsTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag UNUSED(flag)) { emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); } @@ -919,7 +918,7 @@ static void emDM_drawFacesTex(DerivedMesh *dm, static void emDM_drawMappedFacesTex(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag UNUSED(flag)) { emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); } @@ -2283,8 +2282,8 @@ static void cage_mapped_verts_callback(void *userData, int index, const float co { struct CageUserData *data = userData; - if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_GET(data->visit_bitmap, index))) { - BLI_BITMAP_SET(data->visit_bitmap, index); + if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) { + BLI_BITMAP_ENABLE(data->visit_bitmap, index); copy_v3_v3(data->cos_cage[index], co); } } diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c index 76ea340ecbd..442ab26ffc8 100644 --- a/source/blender/blenkernel/intern/editmesh_bvh.c +++ b/source/blender/blenkernel/intern/editmesh_bvh.c @@ -53,13 +53,17 @@ struct BMBVHTree { int flag; }; -BMBVHTree *BKE_bmbvh_new_from_editmesh(BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free) +BMBVHTree *BKE_bmbvh_new_from_editmesh( + BMEditMesh *em, int flag, + const float (*cos_cage)[3], const bool cos_cage_free) { return BKE_bmbvh_new(em->bm, em->looptris, em->tottri, flag, cos_cage, cos_cage_free); } -BMBVHTree *BKE_bmbvh_new(BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, const float (*cos_cage)[3], -const bool cos_cage_free) +BMBVHTree *BKE_bmbvh_new_ex( + BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, + const float (*cos_cage)[3], const bool cos_cage_free, + bool (*test_fn)(BMFace *, void *user_data), void *user_data) { /* could become argument */ const float epsilon = FLT_EPSILON * 2.0f; @@ -69,6 +73,10 @@ const bool cos_cage_free) int i; int tottri; + /* avoid testing every tri */ + BMFace *f_test, *f_test_prev; + bool test_fn_ret; + /* BKE_editmesh_tessface_calc() must be called already */ BLI_assert(looptris_tot != 0 || bm->totface == 0); @@ -83,18 +91,22 @@ const bool cos_cage_free) bmtree->cos_cage_free = cos_cage_free; bmtree->flag = flag; - if (flag & (BMBVH_RESPECT_SELECT)) { + if (test_fn) { + /* callback must do... */ + BLI_assert(!(flag & (BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN))); + + f_test_prev = NULL; + test_fn_ret = false; + tottri = 0; for (i = 0; i < looptris_tot; i++) { - if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) { - tottri++; + f_test = looptris[i][0]->f; + if (f_test != f_test_prev) { + test_fn_ret = test_fn(f_test, user_data); + f_test_prev = f_test; } - } - } - else if (flag & (BMBVH_RESPECT_HIDDEN)) { - tottri = 0; - for (i = 0; i < looptris_tot; i++) { - if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) { + + if (test_fn_ret) { tottri++; } } @@ -105,17 +117,19 @@ const bool cos_cage_free) bmtree->tree = BLI_bvhtree_new(tottri, epsilon, 8, 8); - for (i = 0; i < looptris_tot; i++) { + f_test_prev = NULL; + test_fn_ret = false; - if (flag & BMBVH_RESPECT_SELECT) { + for (i = 0; i < looptris_tot; i++) { + if (test_fn) { /* note, the arrays wont align now! take care */ - if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) { - continue; + f_test = looptris[i][0]->f; + if (f_test != f_test_prev) { + test_fn_ret = test_fn(f_test, user_data); + f_test_prev = f_test; } - } - else if (flag & BMBVH_RESPECT_HIDDEN) { - /* note, the arrays wont align now! take care */ - if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) { + + if (!test_fn_ret) { continue; } } @@ -139,6 +153,38 @@ const bool cos_cage_free) return bmtree; } +static bool bm_face_is_select(BMFace *f, void *UNUSED(user_data)) +{ + return (BM_elem_flag_test(f, BM_ELEM_SELECT) != 0); +} + +static bool bm_face_is_not_hidden(BMFace *f, void *UNUSED(user_data)) +{ + return (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == 0); +} + +BMBVHTree *BKE_bmbvh_new( + BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, + const float (*cos_cage)[3], const bool cos_cage_free) +{ + bool (*test_fn)(BMFace *, void *user_data); + + if (flag & BMBVH_RESPECT_SELECT) { + test_fn = bm_face_is_select; + } + else if (flag & BMBVH_RESPECT_HIDDEN) { + test_fn = bm_face_is_not_hidden; + } + else { + test_fn = NULL; + } + + flag &= ~(BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN); + + return BKE_bmbvh_new_ex(bm, looptris, looptris_tot, flag, cos_cage, cos_cage_free, test_fn, NULL); +} + + void BKE_bmbvh_free(BMBVHTree *bmtree) { BLI_bvhtree_free(bmtree->tree); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e28152dbc1a..ced9da8d0b1 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -630,8 +630,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin } else { /* use center of object for distance calculus */ - Object *ob = eff->ob; - Object obcopy = *ob; + const Object *ob = eff->ob; /* use z-axis as normal*/ normalize_v3_v3(efd->nor, ob->obmat[2]); @@ -654,8 +653,6 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin if (real_velocity) copy_v3_v3(efd->vel, eff->velocity); - *eff->ob = obcopy; - efd->size = 0.0f; ret = 1; @@ -875,7 +872,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected case PFIELD_HARMONIC: mul_v3_fl(force, -strength * efd->falloff); copy_v3_v3(temp, point->vel); - mul_v3_fl(temp, -damp * 2.0f * (float)sqrt(fabs(strength)) * point->vel_to_sec); + mul_v3_fl(temp, -damp * 2.0f * sqrtf(fabsf(strength)) * point->vel_to_sec); add_v3_v3(force, temp); break; case PFIELD_CHARGE: @@ -935,7 +932,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected if (pd->flag & PFIELD_DO_LOCATION) { madd_v3_v3fl(total_force, force, 1.0f/point->vel_to_sec); - if (ELEM3(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) { + if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) { madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff); } } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 65b9d2159df..e90a0891436 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -55,6 +55,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_object.h" @@ -276,7 +277,7 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, int matches = 0; /* sanity checks */ - if (ELEM4(NULL, dst, src, dataPrefix, dataName)) + if (ELEM(NULL, dst, src, dataPrefix, dataName)) return 0; else if ((dataPrefix[0] == 0) || (dataName[0] == 0)) return 0; @@ -310,19 +311,35 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, bool *r_driven) { + return rna_get_fcurve_context_ui(NULL, ptr, prop, rnaindex, action, r_driven); +} + +FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, + bAction **action, bool *r_driven) +{ FCurve *fcu = NULL; + PointerRNA tptr = *ptr; *r_driven = false; /* there must be some RNA-pointer + property combon */ - if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) { - AnimData *adt = BKE_animdata_from_id(ptr->id.data); - char *path; + if (prop && tptr.id.data && RNA_property_animateable(&tptr, prop)) { + AnimData *adt = BKE_animdata_from_id(tptr.id.data); + int step = C ? 2 : 1; /* Always 1 in case we have no context (can't check in 'ancestors' of given RNA ptr). */ + char *path = NULL; + + if (!adt && C) { + path = BKE_animdata_driver_path_hack(C, &tptr, prop, NULL); + adt = BKE_animdata_from_id(tptr.id.data); + step--; + } - if (adt) { + while (adt && step--) { if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) { /* XXX this function call can become a performance bottleneck */ - path = RNA_path_from_ID_to_property(ptr, prop); + if (step) { + path = RNA_path_from_ID_to_property(&tptr, prop); + } if (path) { /* animation takes priority over drivers */ @@ -337,13 +354,25 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction *r_driven = true; } - if (fcu && action) + if (fcu && action) { *action = adt->action; - - MEM_freeN(path); + break; + } + else if (step) { + char *tpath = BKE_animdata_driver_path_hack(C, &tptr, prop, path); + if (tpath && tpath != path) { + MEM_freeN(path); + path = tpath; + adt = BKE_animdata_from_id(tptr.id.data); + } + else { + adt = NULL; + } + } } } } + MEM_SAFE_FREE(path); } return fcu; @@ -469,7 +498,7 @@ static short get_fcurve_end_keyframes(FCurve *fcu, BezTriple **first, BezTriple } /* find last selected */ - bezt = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, sizeof(BezTriple), fcu->totvert); + bezt = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, fcu->totvert); for (i = 0; i < fcu->totvert; bezt--, i++) { if (BEZSELECTED(bezt)) { *last = bezt; @@ -481,7 +510,7 @@ static short get_fcurve_end_keyframes(FCurve *fcu, BezTriple **first, BezTriple else { /* just full array */ *first = fcu->bezt; - *last = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, sizeof(BezTriple), fcu->totvert); + *last = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, fcu->totvert); found = true; } @@ -522,17 +551,28 @@ bool calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, floa /* only loop over keyframes to find extents for values if needed */ if (ymin || ymax) { - BezTriple *bezt; + BezTriple *bezt, *prevbezt = NULL; - for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) { - if ((do_sel_only == false) || BEZSELECTED(bezt)) { + for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) { + if ((do_sel_only == false) || BEZSELECTED(bezt)) { + /* keyframe itself */ + yminv = min_ff(yminv, bezt->vec[1][1]); + ymaxv = max_ff(ymaxv, bezt->vec[1][1]); + if (include_handles) { - yminv = min_ffff(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]); - ymaxv = max_ffff(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]); - } - else { - yminv = min_ff(yminv, bezt->vec[1][1]); - ymaxv = max_ff(ymaxv, bezt->vec[1][1]); + /* left handle - only if applicable + * NOTE: for the very first keyframe, the left handle actually has no bearings on anything + */ + if (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)) { + yminv = min_ff(yminv, bezt->vec[0][1]); + ymaxv = max_ff(ymaxv, bezt->vec[0][1]); + } + + /* right handle - only if applicable */ + if (bezt->ipo == BEZT_IPO_BEZ) { + yminv = min_ff(yminv, bezt->vec[2][1]); + ymaxv = max_ff(ymaxv, bezt->vec[2][1]); + } } foundvert = true; @@ -2050,8 +2090,14 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime /* evaltime occurs somewhere in the middle of the curve */ bool exact = false; - /* - use binary search to find appropriate keyframes */ - a = binarysearch_bezt_index_ex(bezts, evaltime, fcu->totvert, 0.001, &exact); + /* Use binary search to find appropriate keyframes... + * + * The threshold here has the following constraints: + * - 0.001 is too coarse -> We get artifacts with 2cm driver movements at 1BU = 1m (see T40332) + * - 0.00001 is too fine -> Weird errors, like selecting the wrong keyframe range (see T39207), occur. + * This lower bound was established in b888a32eee8147b028464336ad2404d8155c64dd + */ + a = binarysearch_bezt_index_ex(bezts, evaltime, fcu->totvert, 0.0001, &exact); if (G.debug & G_DEBUG) printf("eval fcurve '%s' - %f => %d/%d, %d\n", fcu->rna_path, evaltime, a, fcu->totvert, exact); if (exact) { diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index ef861e2844c..8d4bb7ec058 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -312,10 +312,10 @@ static void build_underline(Curve *cu, ListBase *nubase, const rctf *rect, bp = (BPoint *)MEM_callocN(4 * sizeof(BPoint), "underline_bp"); - copy_v4_fl4(bp[0].vec, rect->xmin, (rect->ymin + yofs), 0.0f, 1.0f); - copy_v4_fl4(bp[1].vec, rect->xmax, (rect->ymin + yofs), 0.0f, 1.0f); - copy_v4_fl4(bp[2].vec, rect->xmax, (rect->ymax + yofs), 0.0f, 1.0f); - copy_v4_fl4(bp[3].vec, rect->xmin, (rect->ymax + yofs), 0.0f, 1.0f); + copy_v4_fl4(bp[0].vec, rect->xmin, (rect->ymax + yofs), 0.0f, 1.0f); + copy_v4_fl4(bp[1].vec, rect->xmax, (rect->ymax + yofs), 0.0f, 1.0f); + copy_v4_fl4(bp[2].vec, rect->xmax, (rect->ymin + yofs), 0.0f, 1.0f); + copy_v4_fl4(bp[3].vec, rect->xmin, (rect->ymin + yofs), 0.0f, 1.0f); nu2->bp = bp; BLI_addtail(nubase, nu2); @@ -484,26 +484,53 @@ int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end) { Curve *cu = ob->data; EditFont *ef = cu->editfont; + int start, end, direction; if ((ob->type != OB_FONT) || (ef == NULL)) return 0; + BLI_assert(ef->len >= 0); BLI_assert(ef->selstart >= 0 && ef->selstart <= ef->len + 1); - BLI_assert(ef->selend >= 0 && ef->selend <= ef->len + 1); + BLI_assert(ef->selend >= 0 && ef->selend <= ef->len); BLI_assert(ef->pos >= 0 && ef->pos <= ef->len); - if (ef->selstart == 0) return 0; + if (ef->selstart == 0) { + return 0; + } + if (ef->selstart <= ef->selend) { - *r_start = ef->selstart - 1; - *r_end = ef->selend - 1; - return 1; + start = ef->selstart - 1; + end = ef->selend - 1; + direction = 1; + } + else { + start = ef->selend; + end = ef->selstart - 2; + direction = -1; + } + + if (start == end + 1) { + return 0; } else { - *r_start = ef->selend; - *r_end = ef->selstart - 2; - return -1; + BLI_assert(start < end + 1); + *r_start = start; + *r_end = end; + return direction; } } +void BKE_vfont_select_clamp(Object *ob) +{ + Curve *cu = ob->data; + EditFont *ef = cu->editfont; + + BLI_assert((ob->type == OB_FONT) && ef); + + CLAMP_MAX(ef->pos, ef->len); + CLAMP_MAX(ef->selstart, ef->len + 1); + CLAMP_MAX(ef->selend, ef->len); +} + static float char_width(Curve *cu, VChar *che, CharInfo *info) { /* The character wasn't found, propably ascii = 0, then the width shall be 0 as well */ @@ -518,6 +545,24 @@ static float char_width(Curve *cu, VChar *che, CharInfo *info) } } +static void textbox_scale(TextBox *tb_dst, const TextBox *tb_src, float scale) +{ + tb_dst->x = tb_src->x * scale; + tb_dst->y = tb_src->y * scale; + tb_dst->w = tb_src->w * scale; + tb_dst->h = tb_src->h * scale; +} + +/** + * Used for storing per-line data for alignment & wrapping. + */ +struct TempLineInfo { + float x_min; /* left margin */ + float x_max; /* right margin */ + int char_nr; /* number of characters */ + int wspace_nr; /* number of whitespaces of line */ +}; + bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase, const wchar_t **r_text, int *r_text_len, bool *r_text_free, struct CharTrans **r_chartransdata) @@ -528,18 +573,25 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase VFont *vfont, *oldvfont; VFontData *vfd = NULL; CharInfo *info = NULL, *custrinfo; - TextBox *tb; + TextBox tb_scale; + bool use_textbox; VChar *che; struct CharTrans *chartransdata = NULL, *ct; - float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4; + struct TempLineInfo *lineinfo; + float *f, xof, yof, xtrax, linedist; float twidth, maxlen = 0; int i, slen, j; int curbox; int selstart, selend; - short cnr = 0, lnr = 0, wsnr = 0; + int cnr = 0, lnr = 0, wsnr = 0; const wchar_t *mem; wchar_t ascii; bool ok = false; + const float xof_scale = cu->xof / cu->fsize; + const float yof_scale = cu->yof / cu->fsize; + +#define MARGIN_X_MIN (xof_scale + tb_scale.x) +#define MARGIN_Y_MIN (yof_scale + tb_scale.y) /* remark: do calculations including the trailing '\0' of a string * because the cursor can be at that location */ @@ -556,9 +608,6 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase /* The VFont Data can not be found */ if (!vfd) return ok; - - if (cu->ulheight == 0.0f) - cu->ulheight = 0.05f; if (ef) { slen = ef->len; @@ -601,25 +650,26 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase ct = chartransdata = MEM_callocN((slen + 1) * sizeof(struct CharTrans), "buildtext"); /* We assume the worst case: 1 character per line (is freed at end anyway) */ - - linedata = MEM_mallocN(sizeof(float) * (slen * 2 + 1), "buildtext2"); - linedata2 = MEM_mallocN(sizeof(float) * (slen * 2 + 1), "buildtext3"); - linedata3 = MEM_callocN(sizeof(float) * (slen * 2 + 1), "buildtext4"); - linedata4 = MEM_callocN(sizeof(float) * (slen * 2 + 1), "buildtext5"); + lineinfo = MEM_mallocN(sizeof(*lineinfo) * (slen * 2 + 1), "lineinfo"); linedist = cu->linedist; - xof = cu->xof + (cu->tb[0].x / cu->fsize); - yof = cu->yof + (cu->tb[0].y / cu->fsize); + curbox = 0; + textbox_scale(&tb_scale, &cu->tb[curbox], 1.0f / cu->fsize); + use_textbox = (tb_scale.w != 0.0f); + + + xof = MARGIN_X_MIN; + yof = MARGIN_Y_MIN; xtrax = 0.5f * cu->spacing - 0.5f; oldvfont = NULL; - for (i = 0; i < slen; i++) custrinfo[i].flag &= ~(CU_CHINFO_WRAP | CU_CHINFO_SMALLCAPS_CHECK); + for (i = 0; i < slen; i++) { + custrinfo[i].flag &= ~(CU_CHINFO_WRAP | CU_CHINFO_SMALLCAPS_CHECK); + } - tb = &(cu->tb[0]); - curbox = 0; for (i = 0; i <= slen; i++) { makebreak: /* Characters in the list */ @@ -645,6 +695,7 @@ makebreak: if (!vfd) { MEM_freeN(chartransdata); chartransdata = NULL; + MEM_freeN(lineinfo); goto finally; } @@ -679,12 +730,12 @@ makebreak: twidth = char_width(cu, che, info); /* Calculate positions */ - if ((tb->w != 0.0f) && + if ((tb_scale.w != 0.0f) && (ct->dobreak == 0) && - (((xof - (tb->x / cu->fsize) + twidth) * cu->fsize) > tb->w + cu->xof * cu->fsize)) + (((xof - tb_scale.x) + twidth) > xof_scale + tb_scale.w)) { // fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]); - for (j = i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak == 0); j--) { + for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) { if (mem[j] == ' ' || mem[j] == '-') { ct -= (i - (j - 1)); cnr -= (i - (j - 1)); @@ -709,7 +760,7 @@ makebreak: } } - if (ascii == '\n' || ascii == '\r' || ascii == 0 || ct->dobreak) { + if (ascii == '\n' || ascii == 0 || ct->dobreak) { ct->xof = xof; ct->yof = yof; ct->linenr = lnr; @@ -717,30 +768,33 @@ makebreak: yof -= linedist; - maxlen = max_ff(maxlen, (xof - tb->x / cu->fsize)); - linedata[lnr] = xof - tb->x / cu->fsize; - linedata2[lnr] = cnr; - linedata3[lnr] = tb->w / cu->fsize; - linedata4[lnr] = wsnr; - - if ((tb->h != 0.0f) && - ((-(yof - (tb->y / cu->fsize))) > ((tb->h / cu->fsize) - (linedist * cu->fsize)) - cu->yof) && - (cu->totbox > (curbox + 1)) ) + lineinfo[lnr].x_min = (xof - xtrax) - tb_scale.x; + lineinfo[lnr].x_max = tb_scale.w; + lineinfo[lnr].char_nr = cnr; + lineinfo[lnr].wspace_nr = wsnr; + + CLAMP_MIN(maxlen, lineinfo[lnr].x_min); + + if ((tb_scale.h != 0.0f) && + (cu->totbox > (curbox + 1)) && + ((-(yof - tb_scale.y)) > (tb_scale.h - (linedist * cu->fsize)) - yof_scale)) { maxlen = 0; - tb++; curbox++; - yof = cu->yof + tb->y / cu->fsize; + + textbox_scale(&tb_scale, &cu->tb[curbox], 1.0f / cu->fsize); + + yof = MARGIN_Y_MIN; } /* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */ #if 0 - if (ascii == '\n' || ascii == '\r') - xof = cu->xof; + if (ascii == '\n') + xof = xof_scale; else - xof = cu->xof + (tb->x / cu->fsize); + xof = MARGIN_X_MIN; #else - xof = cu->xof + (tb->x / cu->fsize); + xof = MARGIN_X_MIN; #endif lnr++; cnr = 0; @@ -754,9 +808,9 @@ makebreak: ct->linenr = lnr; ct->charnr = cnr++; - tabfac = (xof - cu->xof + 0.01f); + tabfac = (xof - MARGIN_X_MIN + 0.01f); tabfac = 2.0f * ceilf(tabfac / 2.0f); - xof = cu->xof + tabfac; + xof = MARGIN_X_MIN + tabfac; } else { EditFontSelBox *sb = NULL; @@ -798,68 +852,88 @@ makebreak: for (i = 0; i <= slen; i++) { ascii = mem[i]; ct = &chartransdata[i]; - if (ascii == '\n' || ascii == '\r' || ct->dobreak) cu->lines++; + if (ascii == '\n' || ct->dobreak) cu->lines++; } - /* linedata is now: width of line - * linedata2 is now: number of characters - * linedata3 is now: maxlen of that line - * linedata4 is now: number of whitespaces of line */ + /* linedata is now: width of line */ if (cu->spacemode != CU_LEFT) { ct = chartransdata; if (cu->spacemode == CU_RIGHT) { - for (i = 0; i < lnr; i++) linedata[i] = linedata3[i] - linedata[i]; + struct TempLineInfo *li; + + for (i = 0, li = lineinfo; i < lnr; i++, li++) { + li->x_min = (li->x_max - li->x_min) + xof_scale; + } + for (i = 0; i <= slen; i++) { - ct->xof += linedata[ct->linenr]; + ct->xof += lineinfo[ct->linenr].x_min; ct++; } } else if (cu->spacemode == CU_MIDDLE) { - for (i = 0; i < lnr; i++) linedata[i] = (linedata3[i] - linedata[i]) / 2; + struct TempLineInfo *li; + + for (i = 0, li = lineinfo; i < lnr; i++, li++) { + li->x_min = ((li->x_max - li->x_min) + xof_scale) / 2.0f; + } + for (i = 0; i <= slen; i++) { - ct->xof += linedata[ct->linenr]; + ct->xof += lineinfo[ct->linenr].x_min; ct++; } } - else if ((cu->spacemode == CU_FLUSH) && (cu->tb[0].w != 0.0f)) { - for (i = 0; i < lnr; i++) - if (linedata2[i] > 1) - linedata[i] = (linedata3[i] - linedata[i]) / (linedata2[i] - 1); + else if ((cu->spacemode == CU_FLUSH) && use_textbox) { + struct TempLineInfo *li; + + for (i = 0, li = lineinfo; i < lnr; i++, li++) { + li->x_min = ((li->x_max - li->x_min) + xof_scale); + + if (li->char_nr > 1) { + li->x_min /= (float)(li->char_nr - 1); + } + } for (i = 0; i <= slen; i++) { - for (j = i; (!ELEM3(mem[j], '\0', '\n', '\r')) && (chartransdata[j].dobreak == 0) && (j < slen); j++) { + for (j = i; (!ELEM(mem[j], '\0', '\n')) && (chartransdata[j].dobreak == 0) && (j < slen); j++) { /* do nothing */ } -// if ((mem[j] != '\r') && (mem[j] != '\n') && (mem[j])) { - ct->xof += ct->charnr * linedata[ct->linenr]; +// if ((mem[j] != '\n') && (mem[j])) { + ct->xof += ct->charnr * lineinfo[ct->linenr].x_min; // } ct++; } } - else if ((cu->spacemode == CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) { + else if ((cu->spacemode == CU_JUSTIFY) && use_textbox) { float curofs = 0.0f; for (i = 0; i <= slen; i++) { - for (j = i; (mem[j]) && (mem[j] != '\n') && - (mem[j] != '\r') && (chartransdata[j].dobreak == 0) && (j < slen); + for (j = i; + (mem[j]) && (mem[j] != '\n') && (chartransdata[j].dobreak == 0) && (j < slen); j++) { /* pass */ } - if ((mem[j] != '\r') && (mem[j] != '\n') && + if ((mem[j] != '\n') && ((chartransdata[j].dobreak != 0))) { - if (mem[i] == ' ') curofs += (linedata3[ct->linenr] - linedata[ct->linenr]) / linedata4[ct->linenr]; + if (mem[i] == ' ') { + struct TempLineInfo *li; + + li = &lineinfo[ct->linenr]; + curofs += ((li->x_max - li->x_min) + xof_scale) / (float)li->wspace_nr; + } ct->xof += curofs; } - if (mem[i] == '\n' || mem[i] == '\r' || chartransdata[i].dobreak) curofs = 0; + if (mem[i] == '\n' || chartransdata[i].dobreak) curofs = 0; ct++; } } } - + + MEM_freeN(lineinfo); + /* TEXT ON CURVE */ /* Note: Only OB_CURVE objects could have a path */ if (cu->textoncurve && cu->textoncurve->type == OB_CURVE) { @@ -1031,11 +1105,6 @@ makebreak: } - MEM_freeN(linedata); - MEM_freeN(linedata2); - MEM_freeN(linedata3); - MEM_freeN(linedata4); - if (mode == FO_SELCHANGE) { MEM_freeN(chartransdata); chartransdata = NULL; @@ -1060,14 +1129,14 @@ makebreak: info->mat_nr = 0; } /* We do not want to see any character for \n or \r */ - if (cha != '\n' && cha != '\r') + if (cha != '\n') buildchar(bmain, cu, r_nubase, cha, info, ct->xof, ct->yof, ct->rot, i); - if ((info->flag & CU_CHINFO_UNDERLINE) && (cha != '\n') && (cha != '\r')) { + if ((info->flag & CU_CHINFO_UNDERLINE) && (cha != '\n')) { float ulwidth, uloverlap = 0.0f; rctf rect; - if ((i < (slen - 1)) && (mem[i + 1] != '\n') && (mem[i + 1] != '\r') && + if ((i < (slen - 1)) && (mem[i + 1] != '\n') && ((mem[i + 1] != ' ') || (custrinfo[i + 1].flag & CU_CHINFO_UNDERLINE)) && ((custrinfo[i + 1].flag & CU_CHINFO_WRAP) == 0)) { @@ -1121,6 +1190,9 @@ finally: } return ok; + +#undef MARGIN_X_MIN +#undef MARGIN_Y_MIN } diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c index 495e99d61af..4aa1b49ea13 100644 --- a/source/blender/blenkernel/intern/freestyle.c +++ b/source/blender/blenkernel/intern/freestyle.c @@ -127,12 +127,13 @@ static FreestyleModuleConfig *alloc_module(void) return (FreestyleModuleConfig *)MEM_callocN(sizeof(FreestyleModuleConfig), "style module configuration"); } -void BKE_freestyle_module_add(FreestyleConfig *config) +FreestyleModuleConfig *BKE_freestyle_module_add(FreestyleConfig *config) { FreestyleModuleConfig *module_conf = alloc_module(); BLI_addtail(&config->modules, (void *)module_conf); module_conf->script = NULL; module_conf->is_displayed = 1; + return module_conf; } static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module) @@ -141,21 +142,30 @@ static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig new_module->is_displayed = module->is_displayed; } -void BKE_freestyle_module_delete(FreestyleConfig *config, FreestyleModuleConfig *module_conf) +bool BKE_freestyle_module_delete(FreestyleConfig *config, FreestyleModuleConfig *module_conf) { + if (BLI_findindex(&config->modules, module_conf) == -1) + return false; BLI_freelinkN(&config->modules, module_conf); + return true; } -void BKE_freestyle_module_move_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf) +bool BKE_freestyle_module_move_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf) { + if (BLI_findindex(&config->modules, module_conf) == -1) + return false; BLI_remlink(&config->modules, module_conf); BLI_insertlinkbefore(&config->modules, module_conf->prev, module_conf); + return true; } -void BKE_freestyle_module_move_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf) +bool BKE_freestyle_module_move_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf) { + if (BLI_findindex(&config->modules, module_conf) == -1) + return false; BLI_remlink(&config->modules, module_conf); BLI_insertlinkafter(&config->modules, module_conf->next, module_conf); + return true; } void BKE_freestyle_lineset_unique_name(FreestyleConfig *config, FreestyleLineSet *lineset) @@ -177,7 +187,7 @@ FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char BLI_addtail(&config->linesets, (void *)lineset); BKE_freestyle_lineset_set_active_index(config, lineset_index); - lineset->linestyle = BKE_new_linestyle("LineStyle", NULL); + lineset->linestyle = BKE_linestyle_new("LineStyle", NULL); lineset->flags |= FREESTYLE_LINESET_ENABLED; lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES | FREESTYLE_SEL_IMAGE_BORDER; lineset->qi = FREESTYLE_QI_VISIBLE; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index c381084cfd2..e226e9d9797 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -506,7 +506,7 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active) bGPDlayer *gpl; /* error checking */ - if (ELEM3(NULL, gpd, gpd->layers.first, active)) + if (ELEM(NULL, gpd, gpd->layers.first, active)) return; /* loop over layers deactivating all */ diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index c987e0b67cb..1b7a03ec80e 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -73,6 +73,8 @@ static IDType idtypes[] = { { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE }, { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE }, { ID_PA, "ParticleSettings", "particles", 0 }, + { ID_PAL, "Palettes", "palettes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_PC, "PaintCurve", "paint_curves", IDTYPE_FLAGS_ISLINKABLE }, { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE }, { ID_SCR, "Screen", "screens", 0 }, { ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */ @@ -84,12 +86,11 @@ static IDType idtypes[] = { { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE }, { ID_WM, "WindowManager", "window_managers", 0 }, }; -static int nidtypes = sizeof(idtypes) / sizeof(idtypes[0]); static IDType *idtype_from_name(const char *str) { - int i = nidtypes; - + int i = ARRAY_SIZE(idtypes); + while (i--) { if (STREQ(str, idtypes[i].name)) { return &idtypes[i]; @@ -100,8 +101,8 @@ static IDType *idtype_from_name(const char *str) } static IDType *idtype_from_code(int code) { - int i = nidtypes; - + int i = ARRAY_SIZE(idtypes); + while (i--) if (code == idtypes[i].code) return &idtypes[i]; @@ -182,5 +183,5 @@ const char *BKE_idcode_to_name_plural(int code) */ int BKE_idcode_iter_step(int *index) { - return (*index < nidtypes) ? idtypes[(*index)++].code : 0; + return (*index < ARRAY_SIZE(idtypes)) ? idtypes[(*index)++].code : 0; } diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index f12a0720692..4dbd15a3774 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -64,7 +64,7 @@ static char idp_size_table[] = { /** \name IDP Array API * \{ */ -#define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i)) +#define GETPROP(prop, i) &(IDP_IDPArray(prop)[i]) /* --------- property array type -------------*/ @@ -251,7 +251,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... */ newsize = newlen; - newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;\ + newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; if (is_grow == false) idp_resize_group_array(prop, newlen, prop->data.pointer); @@ -821,7 +821,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is case IDP_INT: return (IDP_Int(prop1) == IDP_Int(prop2)); case IDP_FLOAT: -#ifdef DEBUG +#if !defined(NDEBUG) && defined(WITH_PYTHON) { float p1 = IDP_Float(prop1); float p2 = IDP_Float(prop2); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 440320e98fe..54f5cb7a68e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -62,6 +62,7 @@ #include "DNA_meshdata_types.h" #include "BLI_blenlib.h" +#include "BLI_math_vector.h" #include "BLI_threads.h" #include "BLI_timecode.h" /* for stamp timecode format */ #include "BLI_utildefines.h" @@ -120,12 +121,12 @@ static unsigned int imagecache_hashhash(const void *key_v) return key->index; } -static int imagecache_hashcmp(const void *a_v, const void *b_v) +static bool imagecache_hashcmp(const void *a_v, const void *b_v) { const ImageCacheKey *a = (ImageCacheKey *) a_v; const ImageCacheKey *b = (ImageCacheKey *) b_v; - return a->index - b->index; + return (a->index != b->index); } static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags) @@ -248,7 +249,7 @@ void BKE_image_de_interlace(Image *ima, int odd) /* ***************** ALLOC & FREE, DATA MANAGING *************** */ -static void image_free_cahced_frames(Image *image) +static void image_free_cached_frames(Image *image) { if (image->cache) { IMB_moviecache_free(image->cache); @@ -256,9 +257,13 @@ static void image_free_cahced_frames(Image *image) } } -static void image_free_buffers(Image *ima) +/** + * Simply free the image data from memory, + * on display the image can load again (except for render buffers). + */ +void BKE_image_free_buffers(Image *ima) { - image_free_cahced_frames(ima); + image_free_cached_frames(ima); if (ima->anim) IMB_free_anim(ima->anim); ima->anim = NULL; @@ -278,7 +283,7 @@ void BKE_image_free(Image *ima) { int a; - image_free_buffers(ima); + BKE_image_free_buffers(ima); if (ima->packedfile) { freePackedFile(ima->packedfile); ima->packedfile = NULL; @@ -361,6 +366,7 @@ Image *BKE_image_copy(Main *bmain, Image *ima) nima->gen_x = ima->gen_x; nima->gen_y = ima->gen_y; nima->gen_type = ima->gen_type; + copy_v4_v4(nima->gen_color, ima->gen_color); nima->animspeed = ima->animspeed; @@ -765,6 +771,7 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei ima->gen_type = gen_type; ima->gen_flag |= (floatbuf ? IMA_GEN_FLOAT : 0); ima->gen_depth = depth; + copy_v4_v4(ima->gen_color, color); ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); @@ -835,8 +842,7 @@ void BKE_image_memorypack(Image *ima) void BKE_image_tag_time(Image *ima) { - if (ima) - ima->lastused = (int)PIL_check_seconds_timer(); + ima->lastused = (int)PIL_check_seconds_timer(); } #if 0 @@ -854,43 +860,6 @@ static void tag_all_images_time() } #endif -void free_old_images(void) -{ - Image *ima; - static int lasttime = 0; - int ctime = (int)PIL_check_seconds_timer(); - - /* - * Run garbage collector once for every collecting period of time - * if textimeout is 0, that's the option to NOT run the collector - */ - if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime) - return; - - /* of course not! */ - if (G.is_rendering) - return; - - lasttime = ctime; - - ima = G.main->image.first; - while (ima) { - if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) { - /* If it's in GL memory, deallocate and set time tag to current time - * This gives textures a "second chance" to be used before dying. */ - if (ima->bindcode || ima->repbind) { - GPU_free_image(ima); - ima->lastused = ctime; - } - /* Otherwise, just kill the buffers */ - else { - image_free_buffers(ima); - } - } - ima = ima->id.next; - } -} - static uintptr_t image_mem_size(Image *image) { uintptr_t size = 0; @@ -1291,7 +1260,7 @@ static bool do_add_image_extension(char *string, const char imtype, const ImageF extension = extension_test; } #endif - else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { + else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { if (!BLI_testextensie(string, extension_test = ".png")) extension = extension_test; } @@ -1934,7 +1903,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) ibuf->ftype = RADHDR; } #endif - else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { + else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { ibuf->ftype = PNG; if (imtype == R_IMF_IMTYPE_PNG) { @@ -2057,7 +2026,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) return(ok); } -/* same as BKE_imbuf_write() but crappy workaround not to perminantly modify +/* same as BKE_imbuf_write() but crappy workaround not to permanently modify * _some_, values in the imbuf */ int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, ImageFormatData *imf, const bool save_copy) @@ -2251,7 +2220,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) switch (signal) { case IMA_SIGNAL_FREE: - image_free_buffers(ima); + BKE_image_free_buffers(ima); if (iuser) iuser->ok = 1; break; @@ -2283,7 +2252,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) #if 0 /* force reload on first use, but not for multilayer, that makes nodes and buttons in ui drawing fail */ if (ima->type != IMA_TYPE_MULTILAYER) - image_free_buffers(ima); + BKE_image_free_buffers(ima); #else /* image buffers for non-sequence multilayer will share buffers with RenderResult, * however sequence multilayer will own buffers. Such logic makes switching from @@ -2292,7 +2261,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) * are nicely detecting anyway, but freeing buffers always here makes multilayer * sequences behave stable */ - image_free_buffers(ima); + BKE_image_free_buffers(ima); #endif ima->ok = 1; @@ -2311,14 +2280,14 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) if (pf) { freePackedFile(ima->packedfile); ima->packedfile = pf; - image_free_buffers(ima); + BKE_image_free_buffers(ima); } else { printf("ERROR: Image not available. Keeping packed image\n"); } } else - image_free_buffers(ima); + BKE_image_free_buffers(ima); if (iuser) iuser->ok = 1; @@ -2336,7 +2305,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } break; case IMA_SIGNAL_COLORMANAGE: - image_free_buffers(ima); + BKE_image_free_buffers(ima); ima->ok = 1; @@ -2474,7 +2443,7 @@ static void image_initialize_after_load(Image *ima, ImBuf *ibuf) else de_interlace_ng(ibuf); } /* timer */ - ima->lastused = clock() / CLOCKS_PER_SEC; + BKE_image_tag_time(ima); ima->ok = IMA_OK_LOADED; @@ -2560,7 +2529,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f * need to ensure there's no image buffers are hanging around * with dead links after freeing the render result. */ - image_free_cahced_frames(ima); + image_free_cached_frames(ima); RE_FreeRenderResult(ima->rr); ima->rr = NULL; } @@ -2656,7 +2625,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) int assign = 0, flag; /* always ensure clean ima */ - image_free_buffers(ima); + BKE_image_free_buffers(ima); /* is there a PackedFile with this image ? */ if (ima->packedfile) { @@ -3030,7 +2999,6 @@ BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser) static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf = NULL; - float color[] = {0, 0, 0, 1}; int frame = 0, index = 0; if (lock_r) @@ -3075,7 +3043,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) if (ima->gen_y == 0) ima->gen_y = 1024; if (ima->gen_depth == 0) ima->gen_depth = 24; ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, ima->gen_depth, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, - color, &ima->colorspace_settings); + ima->gen_color, &ima->colorspace_settings); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); ima->ok = IMA_OK_LOADED; } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index e28fb59cfe6..4cf9d52989f 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1236,7 +1236,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, sub_v3_v3v3(extent, X[s->kl], X[s->ij]); sub_v3_v3v3(vel, V[s->kl], V[s->ij]); dot = dot_v3v3(extent, extent); - length = sqrt(dot); + length = sqrtf(dot); s->flags &= ~CLOTH_SPRING_FLAG_NEEDED; @@ -1432,7 +1432,7 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth; float collfac = 2.0f * clmd->sim_parms->collider_friction; unsigned int v = 0; - unsigned int i = 0; + int i = 0; int j = 0; int k = 0; @@ -1804,6 +1804,7 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo return 1; } + int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { unsigned int i=0; @@ -1888,10 +1889,8 @@ int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase * //if (do_extra_solve) // cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale); - for (i = 0; i < numverts; i++) { - - if (do_extra_solve) { - + if (do_extra_solve) { + for (i = 0; i < numverts; i++) { if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED)) continue; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 7385322ddeb..51cf26063c7 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1308,8 +1308,8 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i * - they were degrees/10 * - we need radians for RNA to do the right thing */ - if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) || - ((icu->blocktype == ID_PO) && ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) ) + if ( ((icu->blocktype == ID_OB) && ELEM(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) || + ((icu->blocktype == ID_PO) && ELEM(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) ) { const float fac = (float)M_PI / 18.0f; //10.0f * M_PI/180.0f; @@ -1341,7 +1341,7 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i DriverVar *dvar = fcu->driver->variables.first; DriverTarget *dtar = &dvar->targets[0]; - if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) { + if (ELEM(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) { const float fac = (float)M_PI / 18.0f; dst->vec[0][0] *= fac; @@ -1388,7 +1388,7 @@ static void ipo_to_animato(ID *id, Ipo *ipo, char actname[], char constname[], S IpoCurve *icu; /* sanity check */ - if (ELEM3(NULL, ipo, anim, drivers)) + if (ELEM(NULL, ipo, anim, drivers)) return; if (G.debug & G_DEBUG) printf("ipo_to_animato\n"); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 0f04c03688c..69b375fba58 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -1558,9 +1558,23 @@ KeyBlock *BKE_keyblock_add(Key *key, const char *name) KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const bool do_force) { KeyBlock *kb = BKE_keyblock_add(key, name); + const float cpos = key->ctime / 100.0f; + /* In case of absolute keys, there is no point in adding more than one key with the same pos. + * Hence only set new keybloc pos to current time if none previous one already use it. + * Now at least people just adding absolute keys without touching to ctime + * won't have to systematically use retiming func (and have ordering issues, too). See T39897. + */ + if (!do_force && (key->type != KEY_RELATIVE)) { + KeyBlock *it_kb; + for (it_kb = key->block.first; it_kb; it_kb = it_kb->next) { + if (it_kb->pos == cpos) { + return kb; + } + } + } if (do_force || (key->type != KEY_RELATIVE)) { - kb->pos = key->ctime / 100.0f; + kb->pos = cpos; BKE_key_sort(key); } @@ -2041,3 +2055,91 @@ void BKE_key_convert_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3]) } } } + +/* ==========================================================*/ + +/** Move shape key from org_index to new_index. Safe, clamps index to valid range, updates reference keys, + * the object's active shape index, the 'frame' value in case of absolute keys, etc. + * Note indices are expected in real values (not 'fake' shapenr +1 ones). + * + * \param org_index if < 0, current object's active shape will be used as skey to move. + * \return true if something was done, else false. + */ +bool BKE_keyblock_move(Object *ob, int org_index, int new_index) +{ + Key *key = BKE_key_from_object(ob); + KeyBlock *kb; + const int act_index = ob->shapenr - 1; + const int totkey = key->totkey; + int i; + bool rev, in_range = false; + + if (org_index < 0) { + org_index = act_index; + } + + CLAMP(new_index, 0, key->totkey - 1); + CLAMP(org_index, 0, key->totkey - 1); + + if (new_index == org_index) { + return false; + } + + rev = ((new_index - org_index) < 0) ? true : false; + + /* We swap 'org' element with its previous/next neighbor (depending on direction of the move) repeatedly, + * until we reach final position. + * This allows us to only loop on the list once! */ + for (kb = (rev ? key->block.last : key->block.first), i = (rev ? totkey - 1 : 0); + kb; + kb = (rev ? kb->prev : kb->next), rev ? i-- : i++) + { + if (i == org_index) { + in_range = true; /* Start list items swapping... */ + } + else if (i == new_index) { + in_range = false; /* End list items swapping. */ + } + + if (in_range) { + KeyBlock *other_kb = rev ? kb->prev : kb->next; + + /* Swap with previous/next list item. */ + BLI_listbase_swaplinks(&key->block, kb, other_kb); + + /* Swap absolute positions. */ + SWAP(float, kb->pos, other_kb->pos); + + kb = other_kb; + } + + /* Adjust relative indices, this has to be done on the whole list! */ + if (kb->relative == org_index) { + kb->relative = new_index; + } + else if (kb->relative < org_index && kb->relative >= new_index) { + /* remove after, insert before this index */ + kb->relative++; + } + else if (kb->relative > org_index && kb->relative <= new_index) { + /* remove before, insert after this index */ + kb->relative--; + } + } + + /* Need to update active shape number if it's affected, same principle as for relative indices above. */ + if (org_index == act_index) { + ob->shapenr = new_index + 1; + } + else if (act_index < org_index && act_index >= new_index) { + ob->shapenr++; + } + else if (act_index > org_index && act_index <= new_index) { + ob->shapenr--; + } + + /* First key is always refkey, matches interface and BKE_key_sort */ + key->refkey = key->block.first; + + return true; +} diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 749e915e5ca..4a413850ec0 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -135,8 +135,7 @@ Lamp *localize_lamp(Lamp *la) Lamp *lan; int a; - lan = BKE_libblock_copy(&la->id); - BLI_remlink(&G.main->lamp, lan); + lan = BKE_libblock_copy_nolib(&la->id, false); for (a = 0; a < MAX_MTEX; a++) { if (lan->mtex[a]) { diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 51fbb86b38e..3f12e3efcc7 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -120,11 +120,11 @@ void BKE_lattice_bitmap_from_flag(Lattice *lt, BLI_bitmap *bitmap, const short f bp = lt->def; for (i = 0; i < tot; i++, bp++) { if ((bp->f1 & flag) && (!respecthide || !bp->hide)) { - BLI_BITMAP_SET(bitmap, i); + BLI_BITMAP_ENABLE(bitmap, i); } else { if (clear) { - BLI_BITMAP_CLEAR(bitmap, i); + BLI_BITMAP_DISABLE(bitmap, i); } } } @@ -626,16 +626,19 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3], short index; const bool is_neg_axis = (axis > 2); - /* to be sure, mostly after file load */ - if (ELEM(NULL, par->curve_cache, par->curve_cache->path)) { + /* to be sure, mostly after file load, also cyclic dependencies */ #ifdef CYCLIC_DEPENDENCY_WORKAROUND + if (par->curve_cache == NULL) { BKE_displist_make_curveTypes(scene, par, false); + } #endif - if (par->curve_cache->path == NULL) { - return 0; // happens on append and cyclic dependencies... - } + + if (par->curve_cache->path == NULL) { + return 0; /* happens on append, cyclic dependencies + * and empty curves + */ } - + /* options */ if (is_neg_axis) { index = axis - 3; @@ -726,7 +729,8 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh Curve *cu; int a; CurveDeform cd; - int use_vgroups; + MDeformVert *dvert = NULL; + int defgrp_index = -1; const bool is_neg_axis = (defaxis > 2); if (cuOb->type != OB_CURVE) @@ -747,75 +751,63 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f; } - /* check whether to use vertex groups (only possible if target is a Mesh) - * we want either a Mesh with no derived data, or derived data with - * deformverts + /* Check whether to use vertex groups (only possible if target is a Mesh or Lattice). + * We want either a Mesh/Lattice with no derived data, or derived data with deformverts. */ - if (target->type == OB_MESH) { - /* if there's derived data without deformverts, don't use vgroups */ - if (dm) { - use_vgroups = (dm->getVertData(dm, 0, CD_MDEFORMVERT) != NULL); - } - else { - Mesh *me = target->data; - use_vgroups = (me->dvert != NULL); + if (vgroup && vgroup[0] && ELEM(target->type, OB_MESH, OB_LATTICE)) { + defgrp_index = defgroup_name_index(target, vgroup); + + if (defgrp_index != -1) { + /* if there's derived data without deformverts, don't use vgroups */ + if (dm) { + dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + } + else if (target->type == OB_LATTICE) { + dvert = ((Lattice *)target->data)->dvert; + } + else { + dvert = ((Mesh *)target->data)->dvert; + } } } - else { - use_vgroups = false; - } - - if (vgroup && vgroup[0] && use_vgroups) { - Mesh *me = target->data; - const int defgrp_index = defgroup_name_index(target, vgroup); - if (defgrp_index != -1 && (me->dvert || dm)) { - MDeformVert *dvert = me->dvert; - float vec[3]; - float weight; - + if (dvert) { + MDeformVert *dvert_iter; + float vec[3]; - if (cu->flag & CU_DEFORM_BOUNDS_OFF) { - dvert = me->dvert; - for (a = 0; a < numVerts; a++, dvert++) { - if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - weight = defvert_find_weight(dvert, defgrp_index); - - if (weight > 0.0f) { - mul_m4_v3(cd.curvespace, vertexCos[a]); - copy_v3_v3(vec, vertexCos[a]); - calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); - interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); - mul_m4_v3(cd.objectspace, vertexCos[a]); - } + if (cu->flag & CU_DEFORM_BOUNDS_OFF) { + for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { + const float weight = defvert_find_weight(dvert_iter, defgrp_index); + + if (weight > 0.0f) { + mul_m4_v3(cd.curvespace, vertexCos[a]); + copy_v3_v3(vec, vertexCos[a]); + calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); + interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); + mul_m4_v3(cd.objectspace, vertexCos[a]); } } - else { - /* set mesh min/max bounds */ - INIT_MINMAX(cd.dmin, cd.dmax); - - for (a = 0; a < numVerts; a++, dvert++) { - if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - - if (defvert_find_weight(dvert, defgrp_index) > 0.0f) { - mul_m4_v3(cd.curvespace, vertexCos[a]); - minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); - } + } + else { + /* set mesh min/max bounds */ + INIT_MINMAX(cd.dmin, cd.dmax); + + for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { + if (defvert_find_weight(dvert_iter, defgrp_index) > 0.0f) { + mul_m4_v3(cd.curvespace, vertexCos[a]); + minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); } - - dvert = me->dvert; - for (a = 0; a < numVerts; a++, dvert++) { - if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - - weight = defvert_find_weight(dvert, defgrp_index); - - if (weight > 0.0f) { - /* already in 'cd.curvespace', prev for loop */ - copy_v3_v3(vec, vertexCos[a]); - calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); - interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); - mul_m4_v3(cd.objectspace, vertexCos[a]); - } + } + + for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { + const float weight = defvert_find_weight(dvert_iter, defgrp_index); + + if (weight > 0.0f) { + /* already in 'cd.curvespace', prev for loop */ + copy_v3_v3(vec, vertexCos[a]); + calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); + interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); + mul_m4_v3(cd.objectspace, vertexCos[a]); } } } @@ -1163,6 +1155,28 @@ void BKE_lattice_center_bounds(Lattice *lt, float cent[3]) mid_v3_v3v3(cent, min, max); } +void BKE_lattice_transform(Lattice *lt, float mat[4][4], bool do_keys) +{ + BPoint *bp = lt->def; + int i = lt->pntsu * lt->pntsv * lt->pntsw; + + while (i--) { + mul_m4_v3(mat, bp->vec); + bp++; + } + + if (do_keys && lt->key) { + KeyBlock *kb; + + for (kb = lt->key->block.first; kb; kb = kb->next) { + float *fp = kb->data; + for (i = kb->totelem; i--; fp += 3) { + mul_m4_v3(mat, fp); + } + } + } +} + void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys) { int i, numVerts; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index fe2d1481581..b49eee3ea22 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -71,6 +71,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_threads.h" #include "BLF_translation.h" #include "BKE_action.h" @@ -103,6 +104,7 @@ #include "BKE_mask.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_packedFile.h" #include "BKE_speaker.h" @@ -381,7 +383,7 @@ bool id_copy(ID *id, ID **newid, bool test) if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id); return true; case ID_LS: - if (!test) *newid = (ID *)BKE_copy_linestyle((FreestyleLineStyle *)id); + if (!test) *newid = (ID *)BKE_linestyle_copy((FreestyleLineStyle *)id); return true; } @@ -514,6 +516,10 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->mask); case ID_LS: return &(mainlib->linestyle); + case ID_PAL: + return &(mainlib->palettes); + case ID_PC: + return &(mainlib->paintcurves); } return NULL; } @@ -595,6 +601,8 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++] = &(main->text); lb[a++] = &(main->sound); lb[a++] = &(main->group); + lb[a++] = &(main->palettes); + lb[a++] = &(main->paintcurves); lb[a++] = &(main->brush); lb[a++] = &(main->script); lb[a++] = &(main->particle); @@ -612,6 +620,8 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a] = NULL; + BLI_assert(a + 1 == MAX_LIBARRAY); + return a; } @@ -730,6 +740,12 @@ static ID *alloc_libblock_notest(short type) case ID_LS: id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style"); break; + case ID_PAL: + id = MEM_callocN(sizeof(Palette), "Palette"); + break; + case ID_PC: + id = MEM_callocN(sizeof(PaintCurve), "Paint Curve"); + break; } return id; } @@ -747,12 +763,14 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name) id = alloc_libblock_notest(type); if (id) { + BKE_main_lock(bmain); BLI_addtail(lb, id); id->us = 1; id->icon_id = 0; *( (short *)id->name) = type; new_id(lb, id, name); /* alphabetic insertion: is in new_id */ + BKE_main_unlock(bmain); } DAG_id_type_tag(bmain, type); return id; @@ -826,6 +844,7 @@ void *BKE_libblock_copy_nolib(ID *id, const bool do_action) id->newid = idn; idn->flag |= LIB_NEW; + idn->us = 1; BKE_libblock_copy_data(idn, id, do_action); @@ -881,10 +900,8 @@ static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata } } -void BKE_libblock_free_data(ID *id) +void BKE_libblock_free_data(Main *bmain, ID *id) { - Main *bmain = G.main; /* should eventually be an arg */ - if (id->properties) { IDP_FreeProperty(id->properties); MEM_freeN(id->properties); @@ -1003,17 +1020,26 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user) BKE_mask_free(bmain, (Mask *)id); break; case ID_LS: - BKE_free_linestyle((FreestyleLineStyle *)id); + BKE_linestyle_free((FreestyleLineStyle *)id); + break; + case ID_PAL: + BKE_palette_free((Palette *)id); + break; + case ID_PC: + BKE_paint_curve_free((PaintCurve *)id); break; } /* avoid notifying on removed data */ + BKE_main_lock(bmain); + if (free_notifier_reference_cb) free_notifier_reference_cb(id); BLI_remlink(lb, id); - BKE_libblock_free_data(id); + BKE_libblock_free_data(bmain, id); + BKE_main_unlock(bmain); MEM_freeN(id); } @@ -1043,7 +1069,10 @@ void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */ Main *BKE_main_new(void) { Main *bmain = MEM_callocN(sizeof(Main), "new main"); - bmain->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "EvaluationContext"); + bmain->eval_ctx = MEM_callocN(sizeof(EvaluationContext), + "EvaluationContext"); + bmain->lock = MEM_mallocN(sizeof(SpinLock), "main lock"); + BLI_spin_init((SpinLock *)bmain->lock); return bmain; } @@ -1106,19 +1135,34 @@ void BKE_main_free(Main *mainvar) } } + BLI_spin_end((SpinLock *)mainvar->lock); + MEM_freeN(mainvar->lock); MEM_freeN(mainvar->eval_ctx); MEM_freeN(mainvar); } -/* ***************** ID ************************ */ +void BKE_main_lock(struct Main *bmain) +{ + BLI_spin_lock((SpinLock *) bmain->lock); +} +void BKE_main_unlock(struct Main *bmain) +{ + BLI_spin_unlock((SpinLock *) bmain->lock); +} -ID *BKE_libblock_find_name(const short type, const char *name) /* type: "OB" or "MA" etc */ +/* ***************** ID ************************ */ +ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) { - ListBase *lb = which_libbase(G.main, type); + ListBase *lb = which_libbase(bmain, type); BLI_assert(lb != NULL); return BLI_findstring(lb, name, offsetof(ID, name) + 2); } +ID *BKE_libblock_find_name(const short type, const char *name) +{ + return BKE_libblock_find_name_ex(G.main, type, name); +} + void id_sort_by_name(ListBase *lb, ID *id) { diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index e9bdc3679c1..6d2e2f1ecd4 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -47,10 +47,12 @@ #include "DNA_mask_types.h" #include "DNA_node_types.h" #include "DNA_object_force.h" +#include "DNA_scene_types.h" #include "DNA_sequence_types.h" #include "DNA_screen_types.h" #include "DNA_speaker_types.h" #include "DNA_sound_types.h" +#include "DNA_text_types.h" #include "DNA_vfont_types.h" #include "DNA_world_types.h" @@ -168,6 +170,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_SCE: { Scene *scene = (Scene *) id; + SceneRenderLayer *srl; Base *base; CALLBACK_INVOKE(scene->camera, IDWALK_NOP); @@ -178,6 +181,31 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } CALLBACK_INVOKE(scene->obedit, IDWALK_NOP); + for (srl = scene->r.layers.first; srl; srl = srl->next) { + FreestyleModuleConfig *fmc; + FreestyleLineSet *fls; + + if (srl->mat_override) { + CALLBACK_INVOKE(srl->mat_override, IDWALK_NOP); + } + if (srl->light_override) { + CALLBACK_INVOKE(srl->light_override, IDWALK_NOP); + } + for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { + if (fmc->script) { + CALLBACK_INVOKE(fmc->script, IDWALK_NOP); + } + } + for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { + if (fls->group) { + CALLBACK_INVOKE(fls->group, IDWALK_NOP); + } + if (fls->linestyle) { + CALLBACK_INVOKE(fls->linestyle, IDWALK_NOP); + } + } + } + if (scene->ed) { Sequence *seq; SEQP_BEGIN(scene->ed, seq) @@ -455,12 +483,38 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u case ID_LS: { FreestyleLineStyle *linestyle = (FreestyleLineStyle *) id; + LineStyleModifier *m; for (i = 0; i < MAX_MTEX; i++) { if (linestyle->mtex[i]) { library_foreach_mtex(&data, linestyle->mtex[i]); } } CALLBACK_INVOKE(linestyle->nodetree, IDWALK_NOP); + + for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) { + if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)m; + if (p->target) { + CALLBACK_INVOKE(p->target, IDWALK_NOP); + } + } + } + for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next) { + if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)m; + if (p->target) { + CALLBACK_INVOKE(p->target, IDWALK_NOP); + } + } + } + for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next) { + if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) { + LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)m; + if (p->target) { + CALLBACK_INVOKE(p->target, IDWALK_NOP); + } + } + } break; } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 8028bdbc327..bcdaf9b7af0 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -43,6 +43,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BKE_context.h" +#include "BKE_freestyle.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_linestyle.h" @@ -51,6 +53,8 @@ #include "BKE_colortools.h" #include "BKE_animsys.h" +#include "RNA_access.h" + static const char *modifier_name[LS_MODIFIER_NUM] = { NULL, "Along Stroke", @@ -89,6 +93,7 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle) linestyle->min_length = 0.0f; linestyle->max_length = 10000.0f; linestyle->split_length = 100; + linestyle->chain_count = 10; linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA; linestyle->integration_type = LS_INTEGRATION_MEAN; linestyle->texstep = 1.0f; @@ -99,12 +104,12 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle) BLI_listbase_clear(&linestyle->thickness_modifiers); BLI_listbase_clear(&linestyle->geometry_modifiers); - BKE_add_linestyle_geometry_modifier(linestyle, LS_MODIFIER_SAMPLING); + BKE_linestyle_geometry_modifier_add(linestyle, NULL, LS_MODIFIER_SAMPLING); linestyle->caps = LS_CAPS_BUTT; } -FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main) +FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main) { FreestyleLineStyle *linestyle; @@ -118,7 +123,7 @@ FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main) return linestyle; } -void BKE_free_linestyle(FreestyleLineStyle *linestyle) +void BKE_linestyle_free(FreestyleLineStyle *linestyle) { LineStyleModifier *m; @@ -137,33 +142,33 @@ void BKE_free_linestyle(FreestyleLineStyle *linestyle) BKE_free_animdata(&linestyle->id); while ((m = (LineStyleModifier *)linestyle->color_modifiers.first)) - BKE_remove_linestyle_color_modifier(linestyle, m); + BKE_linestyle_color_modifier_remove(linestyle, m); while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first)) - BKE_remove_linestyle_alpha_modifier(linestyle, m); + BKE_linestyle_alpha_modifier_remove(linestyle, m); while ((m = (LineStyleModifier *)linestyle->thickness_modifiers.first)) - BKE_remove_linestyle_thickness_modifier(linestyle, m); + BKE_linestyle_thickness_modifier_remove(linestyle, m); while ((m = (LineStyleModifier *)linestyle->geometry_modifiers.first)) - BKE_remove_linestyle_geometry_modifier(linestyle, m); + BKE_linestyle_geometry_modifier_remove(linestyle, m); } -FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle) +FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle) { FreestyleLineStyle *new_linestyle; LineStyleModifier *m; int a; - new_linestyle = BKE_new_linestyle(linestyle->id.name + 2, NULL); - BKE_free_linestyle(new_linestyle); + new_linestyle = BKE_linestyle_new(linestyle->id.name + 2, NULL); + BKE_linestyle_free(new_linestyle); for (a = 0; a < MAX_MTEX; a++) { if (linestyle->mtex[a]) { - new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_copy_linestyle"); + new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_linestyle_copy"); memcpy(new_linestyle->mtex[a], linestyle->mtex[a], sizeof(MTex)); id_us_plus((ID *)new_linestyle->mtex[a]->tex); } } if (linestyle->nodetree) { - linestyle->nodetree = ntreeCopyTree(linestyle->nodetree); + new_linestyle->nodetree = ntreeCopyTree(linestyle->nodetree); } new_linestyle->r = linestyle->r; @@ -182,6 +187,7 @@ FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle) new_linestyle->max_angle = linestyle->max_angle; new_linestyle->min_length = linestyle->min_length; new_linestyle->max_length = linestyle->max_length; + new_linestyle->chain_count = linestyle->chain_count; new_linestyle->split_dash1 = linestyle->split_dash1; new_linestyle->split_gap1 = linestyle->split_gap1; new_linestyle->split_dash2 = linestyle->split_dash2; @@ -198,24 +204,39 @@ FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle) new_linestyle->texstep = linestyle->texstep; new_linestyle->pr_texture = linestyle->pr_texture; for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) - BKE_copy_linestyle_color_modifier(new_linestyle, m); + BKE_linestyle_color_modifier_copy(new_linestyle, m); for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next) - BKE_copy_linestyle_alpha_modifier(new_linestyle, m); + BKE_linestyle_alpha_modifier_copy(new_linestyle, m); for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next) - BKE_copy_linestyle_thickness_modifier(new_linestyle, m); + BKE_linestyle_thickness_modifier_copy(new_linestyle, m); for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next) - BKE_copy_linestyle_geometry_modifier(new_linestyle, m); + BKE_linestyle_geometry_modifier_copy(new_linestyle, m); return new_linestyle; } -static LineStyleModifier *new_modifier(int type, size_t size) +FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene) +{ + SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); + FreestyleConfig *config = &actsrl->freestyleConfig; + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); + + if (lineset) { + return lineset->linestyle; + } + return NULL; +} + +static LineStyleModifier *new_modifier(const char *name, int type, size_t size) { LineStyleModifier *m; + if (!name) { + name = modifier_name[type]; + } m = (LineStyleModifier *)MEM_callocN(size, "line style modifier"); m->type = type; - BLI_strncpy(m->name, modifier_name[type], sizeof(m->name)); + BLI_strncpy(m->name, name, sizeof(m->name)); m->influence = 1.0f; m->flags = LS_MODIFIER_ENABLED | LS_MODIFIER_EXPANDED; @@ -228,7 +249,7 @@ static void add_to_modifier_list(ListBase *lb, LineStyleModifier *m) BLI_uniquename(lb, m, modifier_name[m->type], '.', offsetof(LineStyleModifier, name), sizeof(m->name)); } -static LineStyleModifier *alloc_color_modifier(int type) +static LineStyleModifier *alloc_color_modifier(const char *name, int type) { size_t size; @@ -249,14 +270,14 @@ static LineStyleModifier *alloc_color_modifier(int type) return NULL; /* unknown modifier type */ } - return new_modifier(type, size); + return new_modifier(name, type, size); } -LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, int type) +LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type) { LineStyleModifier *m; - m = alloc_color_modifier(type); + m = alloc_color_modifier(name, type); m->blend = MA_RAMP_BLEND; switch (type) { @@ -276,7 +297,7 @@ LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyl break; case LS_MODIFIER_MATERIAL: ((LineStyleColorModifier_Material *)m)->color_ramp = add_colorband(1); - ((LineStyleColorModifier_Material *)m)->mat_attr = LS_MODIFIER_MATERIAL_DIFF; + ((LineStyleColorModifier_Material *)m)->mat_attr = LS_MODIFIER_MATERIAL_LINE; break; default: return NULL; /* unknown modifier type */ @@ -286,11 +307,11 @@ LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyl return m; } -LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) { LineStyleModifier *new_m; - new_m = alloc_color_modifier(m->type); + new_m = alloc_color_modifier(m->name, m->type); new_m->influence = m->influence; new_m->flags = m->flags; new_m->blend = m->blend; @@ -341,8 +362,10 @@ LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linesty return new_m; } -void BKE_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m) { + if (BLI_findindex(&linestyle->color_modifiers, m) == -1) + return -1; switch (m->type) { case LS_MODIFIER_ALONG_STROKE: MEM_freeN(((LineStyleColorModifier_AlongStroke *)m)->color_ramp); @@ -358,9 +381,10 @@ void BKE_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyl break; } BLI_freelinkN(&linestyle->color_modifiers, m); + return 0; } -static LineStyleModifier *alloc_alpha_modifier(int type) +static LineStyleModifier *alloc_alpha_modifier(const char *name, int type) { size_t size; @@ -380,14 +404,14 @@ static LineStyleModifier *alloc_alpha_modifier(int type) default: return NULL; /* unknown modifier type */ } - return new_modifier(type, size); + return new_modifier(name, type, size); } -LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, int type) +LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type) { LineStyleModifier *m; - m = alloc_alpha_modifier(type); + m = alloc_alpha_modifier(name, type); m->blend = LS_VALUE_BLEND; switch (type) { @@ -418,7 +442,7 @@ LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyl { LineStyleAlphaModifier_Material *p = (LineStyleAlphaModifier_Material *)m; p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - p->mat_attr = LS_MODIFIER_MATERIAL_DIFF; + p->mat_attr = LS_MODIFIER_MATERIAL_LINE_A; break; } default: @@ -429,11 +453,11 @@ LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyl return m; } -LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) { LineStyleModifier *new_m; - new_m = alloc_alpha_modifier(m->type); + new_m = alloc_alpha_modifier(m->name, m->type); new_m->influence = m->influence; new_m->flags = m->flags; new_m->blend = m->blend; @@ -487,8 +511,10 @@ LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linesty return new_m; } -void BKE_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m) { + if (BLI_findindex(&linestyle->alpha_modifiers, m) == -1) + return -1; switch (m->type) { case LS_MODIFIER_ALONG_STROKE: curvemapping_free(((LineStyleAlphaModifier_AlongStroke *)m)->curve); @@ -504,9 +530,10 @@ void BKE_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyl break; } BLI_freelinkN(&linestyle->alpha_modifiers, m); + return 0; } -static LineStyleModifier *alloc_thickness_modifier(int type) +static LineStyleModifier *alloc_thickness_modifier(const char *name, int type) { size_t size; @@ -530,14 +557,14 @@ static LineStyleModifier *alloc_thickness_modifier(int type) return NULL; /* unknown modifier type */ } - return new_modifier(type, size); + return new_modifier(name, type, size); } -LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, int type) +LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type) { LineStyleModifier *m; - m = alloc_thickness_modifier(type); + m = alloc_thickness_modifier(name, type); m->blend = LS_VALUE_BLEND; switch (type) { @@ -574,7 +601,7 @@ LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *line { LineStyleThicknessModifier_Material *p = (LineStyleThicknessModifier_Material *)m; p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - p->mat_attr = LS_MODIFIER_MATERIAL_DIFF; + p->mat_attr = LS_MODIFIER_MATERIAL_LINE; p->value_min = 0.0f; p->value_max = 1.0f; break; @@ -595,11 +622,11 @@ LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *line return m; } -LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) { LineStyleModifier *new_m; - new_m = alloc_thickness_modifier(m->type); + new_m = alloc_thickness_modifier(m->name, m->type); if (!new_m) return NULL; new_m->influence = m->influence; @@ -672,8 +699,10 @@ LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *lin return new_m; } -void BKE_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m) { + if (BLI_findindex(&linestyle->thickness_modifiers, m) == -1) + return -1; switch (m->type) { case LS_MODIFIER_ALONG_STROKE: curvemapping_free(((LineStyleThicknessModifier_AlongStroke *)m)->curve); @@ -691,9 +720,10 @@ void BKE_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, Line break; } BLI_freelinkN(&linestyle->thickness_modifiers, m); + return 0; } -static LineStyleModifier *alloc_geometry_modifier(int type) +static LineStyleModifier *alloc_geometry_modifier(const char *name, int type) { size_t size; @@ -741,14 +771,14 @@ static LineStyleModifier *alloc_geometry_modifier(int type) return NULL; /* unknown modifier type */ } - return new_modifier(type, size); + return new_modifier(name, type, size); } -LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, int type) +LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type) { LineStyleModifier *m; - m = alloc_geometry_modifier(type); + m = alloc_geometry_modifier(name, type); switch (type) { case LS_MODIFIER_SAMPLING: @@ -862,11 +892,11 @@ LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *lines return m; } -LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) { LineStyleModifier *new_m; - new_m = alloc_geometry_modifier(m->type); + new_m = alloc_geometry_modifier(m->name, m->type); new_m->flags = m->flags; switch (m->type) { @@ -996,9 +1026,12 @@ LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *line return new_m; } -void BKE_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +int BKE_linestyle_geometry_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m) { + if (BLI_findindex(&linestyle->geometry_modifiers, m) == -1) + return -1; BLI_freelinkN(&linestyle->geometry_modifiers, m); + return 0; } static void move_modifier(ListBase *lb, LineStyleModifier *modifier, int direction) @@ -1010,27 +1043,27 @@ static void move_modifier(ListBase *lb, LineStyleModifier *modifier, int directi BLI_insertlinkafter(lb, modifier->next, modifier); } -void BKE_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) +void BKE_linestyle_color_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) { move_modifier(&linestyle->color_modifiers, modifier, direction); } -void BKE_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) +void BKE_linestyle_alpha_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) { move_modifier(&linestyle->alpha_modifiers, modifier, direction); } -void BKE_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) +void BKE_linestyle_thickness_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) { move_modifier(&linestyle->thickness_modifiers, modifier, direction); } -void BKE_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) +void BKE_linestyle_geometry_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) { move_modifier(&linestyle->geometry_modifiers, modifier, direction); } -void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase) +void BKE_linestyle_modifier_list_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase) { LineStyleModifier *m; ColorBand *color_ramp; @@ -1061,7 +1094,7 @@ void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *list } } -char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp) +char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp) { LineStyleModifier *m; bool found = false; @@ -1092,11 +1125,11 @@ char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *c return BLI_sprintfN("color_modifiers[\"%s\"].color_ramp", name_esc); } } - printf("BKE_path_from_ID_to_color_ramp: No color ramps correspond to the given pointer.\n"); + printf("BKE_linestyle_path_to_color_ramp: No color ramps correspond to the given pointer.\n"); return NULL; } -void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob) +void BKE_linestyle_target_object_unlink(FreestyleLineStyle *linestyle, struct Object *ob) { LineStyleModifier *m; @@ -1122,3 +1155,64 @@ void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Ob } } } + +bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_shading_nodes) +{ + if (use_shading_nodes) { + if (linestyle && linestyle->use_nodes && linestyle->nodetree) { + bNode *node; + + for (node = linestyle->nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) { + return true; + } + } + } + } + else { + if (linestyle && (linestyle->flag & LS_TEXTURE)) { + return (linestyle->mtex[0] != NULL); + } + } + return false; +} + +void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linestyle) +{ + bNode *uv_along_stroke, *input_texure, *output_linestyle; + bNodeSocket *fromsock, *tosock; + bNodeTree *ntree; + + BLI_assert(linestyle->nodetree == NULL); + + ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree"); + + linestyle->nodetree = ntree; + + uv_along_stroke = nodeAddStaticNode(C, ntree, SH_NODE_UVALONGSTROKE); + uv_along_stroke->locx = 0.0f; + uv_along_stroke->locy = 300.0f; + uv_along_stroke->custom1 = 0; // use_tips + + input_texure = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE); + input_texure->locx = 200.0f; + input_texure->locy = 300.0f; + + output_linestyle = nodeAddStaticNode(C, ntree, SH_NODE_OUTPUT_LINESTYLE); + output_linestyle->locx = 400.0f; + output_linestyle->locy = 300.0f; + output_linestyle->custom1 = MA_RAMP_BLEND; + output_linestyle->custom2 = 0; // use_clamp + + nodeSetActive(ntree, input_texure); + + fromsock = BLI_findlink(&uv_along_stroke->outputs, 0); // UV + tosock = BLI_findlink(&input_texure->inputs, 0); // UV + nodeAddLink(ntree, uv_along_stroke, fromsock, input_texure, tosock); + + fromsock = BLI_findlink(&input_texure->outputs, 0); // Color + tosock = BLI_findlink(&output_linestyle->inputs, 0); // Color + nodeAddLink(ntree, input_texure, fromsock, output_linestyle, tosock); + + ntreeUpdateTree(CTX_data_main(C), ntree); +} diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 8c1cc4b0279..83ad2f1b2d2 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1133,7 +1133,7 @@ void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_c BKE_movieclip_get_size_fl(clip, user, frame_size); BKE_movieclip_get_aspect(clip, &aspx, &aspy); - frame_size[1] /= (aspy / aspx); + frame_size[1] *= (aspy / aspx); BKE_mask_coord_to_frame(r_co, co, frame_size); } @@ -1147,7 +1147,7 @@ void BKE_mask_coord_to_image(Image *image, ImageUser *iuser, float r_co[2], cons BKE_image_get_size_fl(image, iuser, frame_size); BKE_image_get_aspect(image, &aspx, &aspy); - frame_size[1] /= (aspy / aspx); + frame_size[1] *= (aspy / aspx); BKE_mask_coord_to_frame(r_co, co, frame_size); } @@ -1212,7 +1212,7 @@ void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float } invert_m3_m3(mask_to_clip_matrix, mask_from_clip_matrix); - mul_serie_m3(parent_matrix, mask_to_clip_matrix, H, mask_from_clip_matrix, NULL, NULL, NULL, NULL, NULL); + mul_m3_series(parent_matrix, mask_from_clip_matrix, H, mask_to_clip_matrix); } } } @@ -1821,10 +1821,10 @@ void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_sha BKE_mask_layer_shape_free(masklay_shape); } -static int mask_layer_shape_sort_cb(void *masklay_shape_a_ptr, void *masklay_shape_b_ptr) +static int mask_layer_shape_sort_cb(const void *masklay_shape_a_ptr, const void *masklay_shape_b_ptr) { - MaskLayerShape *masklay_shape_a = (MaskLayerShape *)masklay_shape_a_ptr; - MaskLayerShape *masklay_shape_b = (MaskLayerShape *)masklay_shape_b_ptr; + const MaskLayerShape *masklay_shape_a = masklay_shape_a_ptr; + const MaskLayerShape *masklay_shape_b = masklay_shape_b_ptr; if (masklay_shape_a->frame < masklay_shape_b->frame) return -1; else if (masklay_shape_a->frame > masklay_shape_b->frame) return 1; diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 35207595103..4dc8ed21463 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -326,7 +326,7 @@ static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather * are to any of the triangle edges. */ static bool layer_bucket_isect_test( - MaskRasterLayer *layer, unsigned int face_index, + const MaskRasterLayer *layer, unsigned int face_index, const unsigned int bucket_x, const unsigned int bucket_y, const float bucket_size_x, const float bucket_size_y, const float bucket_max_rad_squared) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index de3aea9267f..eeca60f7ef4 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -63,6 +63,7 @@ #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" +#include "BKE_scene.h" #include "BKE_node.h" #include "BKE_curve.h" @@ -111,6 +112,9 @@ void BKE_material_free_ex(Material *ma, bool do_id_user) MEM_freeN(ma->nodetree); } + if (ma->texpaintslot) + MEM_freeN(ma->texpaintslot); + if (ma->gpumaterial.first) GPU_material_free(ma); } @@ -269,7 +273,8 @@ Material *localize_material(Material *ma) if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col); if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec); - + + man->texpaintslot = NULL; man->preview = NULL; if (ma->nodetree) @@ -467,7 +472,7 @@ Material ***give_matarar(Object *ob) me = ob->data; return &(me->mat); } - else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { cu = ob->data; return &(cu->mat); } @@ -488,7 +493,7 @@ short *give_totcolp(Object *ob) me = ob->data; return &(me->totcol); } - else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { cu = ob->data; return &(cu->totcol); } @@ -780,11 +785,13 @@ void test_object_materials(Main *bmain, ID *id) return; } + BKE_main_lock(bmain); for (ob = bmain->object.first; ob; ob = ob->id.next) { if (ob->data == id) { BKE_material_resize_object(ob, *totcol, false); } } + BKE_main_unlock(bmain); } void assign_material_id(ID *id, Material *ma, short act) @@ -1289,7 +1296,7 @@ bool object_remove_material_slot(Object *ob) } /* check indices from mesh */ - if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { material_data_index_remove_id((ID *)ob->data, actcol - 1); if (ob->curve_cache) { BKE_displist_free(&ob->curve_cache->disp); @@ -1299,6 +1306,124 @@ bool object_remove_material_slot(Object *ob) return true; } +static bool get_mtex_slot_valid_texpaint(struct MTex *mtex) +{ + return (mtex && (mtex->texco == TEXCO_UV) && + mtex->tex && (mtex->tex->type == TEX_IMAGE) && + mtex->tex->ima); +} + +void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) +{ + MTex **mtex; + short count = 0; + short index = 0, i; + + bool use_nodes = BKE_scene_use_new_shading_nodes(scene); + bool is_bi = BKE_scene_uses_blender_internal(scene); + + if (!ma) + return; + + if (ma->texpaintslot) { + MEM_freeN(ma->texpaintslot); + ma->tot_slots = 0; + ma->texpaintslot = NULL; + } + + if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + + if (use_nodes || ma->use_nodes) { + bNode *node, *active_node; + + if (!(ma->nodetree)) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + + for (node = ma->nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) + count++; + } + + if (count == 0) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); + + active_node = nodeGetActiveTexture(ma->nodetree); + + for (node = ma->nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) { + if (active_node == node) + ma->paint_active_slot = index; + ma->texpaintslot[index++].ima = (Image *)node->id; + } + } + } + else if (is_bi) { + for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) { + if (get_mtex_slot_valid_texpaint(*mtex)) { + count++; + } + } + + if (count == 0) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + + ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); + + for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) { + if (get_mtex_slot_valid_texpaint(*mtex)) { + ma->texpaintslot[index].ima = (*mtex)->tex->ima; + ma->texpaintslot[index].uvname = (*mtex)->uvname; + ma->texpaintslot[index].index = i; + + index++; + } + } + } + else { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + + + ma->tot_slots = count; + + + if (ma->paint_active_slot >= count) { + ma->paint_active_slot = count - 1; + } + + if (ma->paint_clone_slot >= count) { + ma->paint_clone_slot = count - 1; + } + + return; +} + +void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob) +{ + int i; + + for (i = 1; i < ob->totcol + 1; i++) { + Material *ma = give_current_material(ob, i); + BKE_texpaint_slot_refresh_cache(scene, ma); + } +} + /* r_col = current value, col = new value, (fac == 0) is no change */ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) @@ -1571,7 +1696,7 @@ void copy_matcopybuf(Material *ma) matcopybuf.mtex[a] = MEM_dupallocN(mtex); } } - matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, false); + matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false); matcopybuf.preview = NULL; BLI_listbase_clear(&matcopybuf.gpumaterial); matcopied = 1; @@ -1624,7 +1749,7 @@ void paste_matcopybuf(Material *ma) } } - ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, false); + ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, G.main, false); } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index fc6f9149841..453c6df6e3b 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -491,10 +491,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object) BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.'); - /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ - if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL)) - return; - + BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { if (ob->type == OB_MBALL) { if (ob != active_object) { @@ -537,23 +534,17 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ - if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL)) - return NULL; - + BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { - if (ob->type == OB_MBALL) { + if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) { 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 */ + /* 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) { if (obnr < basisnr) { - if (!(ob->flag & OB_FROMDUPLI)) { - basis = ob; - basisnr = obnr; - } + basis = ob; + basisnr = obnr; } } } @@ -2227,10 +2218,7 @@ static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *sc 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(eval_ctx, &iter, &sce_iter, 0, NULL, NULL)) - return; - + BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { if (ob->type == OB_MBALL) { if (ob == bob) { @@ -2280,7 +2268,7 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, mball_count(eval_ctx, &process, scene, ob); if (process.totelem == 0) return; - if ((eval_ctx->for_render == false) && (mb->flag == MB_UPDATE_NEVER)) return; + if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return; if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return; process.thresh = mb->thresh; @@ -2318,7 +2306,7 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, } /* width is size per polygonize cube */ - if (eval_ctx->for_render) { + if (eval_ctx->mode == DAG_EVAL_RENDER) { width = mb->rendersize; } else { @@ -2361,8 +2349,8 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, process.indices = NULL; a = process.vertices.count; - dl->verts = co = MEM_mallocN(sizeof(float) * 3 * a, "mballverts"); - dl->nors = no = MEM_mallocN(sizeof(float) * 3 * a, "mballnors"); + dl->verts = co = MEM_mallocN(sizeof(float[3]) * a, "mballverts"); + dl->nors = no = MEM_mallocN(sizeof(float[3]) * a, "mballnors"); for (a = 0; a < process.vertices.count; ptr++, a++, no += 3, co += 3) { copy_v3_v3(co, ptr->co); @@ -2454,6 +2442,30 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3]) return 0; } +void BKE_mball_transform(MetaBall *mb, float mat[4][4]) +{ + MetaElem *me; + float quat[4]; + const float scale = mat4_to_scale(mat); + const float scale_sqrt = sqrtf(scale); + + mat4_to_quat(quat, mat); + + for (me = mb->elems.first; me; me = me->next) { + mul_m4_v3(mat, &me->x); + mul_qt_qtqt(me->quat, quat, me->quat); + me->rad *= scale; + /* hrmf, probably elems shouldn't be + * treating scale differently - campbell */ + if (!MB_TYPE_SIZE_SQUARED(me->type)) { + mul_v3_fl(&me->expx, scale); + } + else { + mul_v3_fl(&me->expx, scale_sqrt); + } + } +} + void BKE_mball_translate(MetaBall *mb, const float offset[3]) { MetaElem *ml; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index f0566a7f473..2e80379522c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -115,16 +115,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 int i, i1 = 0, i2 = 0, tot, j; for (i = 0; i < c1->totlayer; i++) { - if (ELEM7(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) { i1++; } } for (i = 0; i < c2->totlayer; i++) { - if (ELEM7(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) { i2++; } @@ -135,16 +135,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 l1 = c1->layers; l2 = c2->layers; tot = i1; - i1 = 0; i2 = 0; + i1 = 0; i2 = 0; for (i = 0; i < tot; i++) { - while (i1 < c1->totlayer && !ELEM7(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) { i1++, l1++; } - while (i2 < c2->totlayer && !ELEM7(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) { i2++, l2++; } @@ -1531,7 +1531,7 @@ void BKE_mesh_from_nurbs(Object *ob) } typedef struct EdgeLink { - Link *next, *prev; + struct EdgeLink *next, *prev; void *edge; } EdgeLink; @@ -1610,13 +1610,11 @@ void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int e BLI_freelinkN(&edges, edges.last); totedges--; while (ok) { /* while connected edges are found... */ + EdgeLink *edl = edges.last; ok = false; - i = totedges; - while (i) { - EdgeLink *edl; + while (edl) { + EdgeLink *edl_prev = edl->prev; - i -= 1; - edl = BLI_findlink(&edges, i); med = edl->edge; if (med->v1 == endVert) { @@ -1643,6 +1641,8 @@ void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int e BLI_freelinkN(&edges, edl); totedges--; ok = true; } + + edl = edl_prev; } } @@ -1869,6 +1869,27 @@ bool BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3]) return (me->totvert != 0); } +void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys) +{ + int i; + MVert *mvert = me->mvert; + + for (i = 0; i < me->totvert; i++, mvert++) + mul_m4_v3(mat, mvert->co); + + if (do_keys && me->key) { + KeyBlock *kb; + for (kb = me->key->block.first; kb; kb = kb->next) { + float *fp = kb->data; + for (i = kb->totelem; i--; fp += 3) { + mul_m4_v3(mat, fp); + } + } + } + + /* don't update normals, caller can do this explicitly */ +} + void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys) { int i = me->totvert; @@ -2041,7 +2062,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type) { int i; - BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL)); + BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL)); for (i = 0; i < me->totselect; i++) { if ((me->mselect[i].index == index) && @@ -2059,7 +2080,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type) */ int BKE_mesh_mselect_active_get(Mesh *me, int type) { - BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL)); + BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL)); if (me->totselect) { if (me->mselect[me->totselect - 1].type == type) { @@ -2148,7 +2169,7 @@ Mesh *BKE_mesh_new_from_object( * if it didn't the curve did not have any segments or otherwise * would have generated an empty mesh */ if (tmpobj->type != OB_MESH) { - BKE_libblock_free_us(G.main, tmpobj); + BKE_libblock_free_us(bmain, tmpobj); return NULL; } @@ -2179,7 +2200,7 @@ Mesh *BKE_mesh_new_from_object( * implemented, this is to be rethinked. */ EvaluationContext eval_ctx = {0}; - eval_ctx.for_render = render; + eval_ctx.mode = DAG_EVAL_RENDER; BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp); BKE_mesh_from_metaball(&disp, tmpmesh); BKE_displist_free(&disp); diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 74e380c7d50..4c9e44682c3 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -386,10 +386,12 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg } else if (e2l[1] == INDEX_UNSET) { /* Second loop using this edge, time to test its sharpness. - * An edge is sharp if it is tagged as such, or its face is not smooth, or angle between - * both its polys' normals is above split_angle value... + * An edge is sharp if it is tagged as such, or its face is not smooth, + * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the same vertex, + * or angle between both its polys' normals is above split_angle value. */ if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) || + ml_curr->v == mloops[e2l[0]].v || (check_angle && dot_v3v3(polynors[loop_to_poly[e2l[0]]], polynors[mp_index]) < split_angle)) { /* Note: we are sure that loop != 0 here ;) */ @@ -441,8 +443,15 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg copy_v3_v3(*lnors, polynors[mp_index]); /* No need to mark loop as done here, we won't run into it again anyway! */ } - /* This loop may have been already computed, in which case its 'to_poly' map is set to -1... */ - else if (loop_to_poly[ml_curr_index] != -1) { + /* We *do not need* to check/tag loops as already computed! + * Due to the fact a loop only links to one of its two edges, a same fan *will never be walked more than + * once!* + * Since we consider edges having neighbor polys with inverted (flipped) normals as sharp, we are sure that + * no fan will be skipped, even only considering the case (sharp curr_edge, smooth prev_edge), and not the + * alternative (smooth curr_edge, sharp prev_edge). + * All this due/thanks to link between normals and loop ordering. + */ + else { /* Gah... We have to fan around current vertex, until we find the other non-smooth edge, * and accumulate face normals into the vertex! * Note in case this vertex has only one sharp edges, this is a waste because the normal is the same as @@ -466,6 +475,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg mlfan_vert_index = ml_curr_index; mpfan_curr_index = mp_index; + BLI_assert(mlfan_curr_index >= 0); + BLI_assert(mlfan_vert_index >= 0); + BLI_assert(mpfan_curr_index >= 0); + /* Only need to compute previous edge's vector once, then we can just reuse old current one! */ { const MEdge *me_prev = &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */ @@ -501,9 +514,6 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg /* We store here a pointer to all loop-normals processed. */ BLI_SMALLSTACK_PUSH(normal, &(r_loopnors[mlfan_vert_index][0])); - /* And we are done with this loop, mark it as such! */ - loop_to_poly[mlfan_vert_index] = -1; - if (IS_EDGE_SHARP(e2lfan_curr)) { /* Current edge is sharp, we have finished with this fan of faces around this vert! */ break; @@ -521,6 +531,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg */ mlfan_curr_index = (e2lfan_curr[0] == mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0]; mpfan_curr_index = loop_to_poly[mlfan_curr_index]; + + BLI_assert(mlfan_curr_index >= 0); + BLI_assert(mpfan_curr_index >= 0); + mlfan_next = &mloops[mlfan_curr_index]; mpfan_next = &mpolys[mpfan_curr_index]; if ((mlfan_curr->v == mlfan_next->v && mlfan_curr->v == mv_pivot_index) || @@ -553,6 +567,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg copy_v3_v3(nor, lnor); } } + else { + /* We still have to clear the stack! */ + while (BLI_SMALLSTACK_POP(normal)); + } } ml_prev = ml_curr; @@ -560,8 +578,6 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg } } - BLI_SMALLSTACK_FREE(normal); - MEM_freeN(edge_to_loops); MEM_freeN(loop_to_poly); @@ -715,7 +731,7 @@ void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangent } BKE_mesh_loop_tangents_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents, - loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports); + loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports); } /** \} */ @@ -1007,7 +1023,7 @@ void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap, const MPoly *mp, ml = mloop; while (i-- != 0) { - BLI_BITMAP_SET(edge_bitmap, ml->e); + BLI_BITMAP_ENABLE(edge_bitmap, ml->e); ml++; } } @@ -1082,6 +1098,125 @@ bool BKE_mesh_center_centroid(Mesh *me, float cent[3]) /* -------------------------------------------------------------------- */ +/** \name Mesh Volume Calculation + * \{ */ + +static bool mesh_calc_center_centroid_ex(MVert *mverts, int UNUSED(numVerts), + MFace *mfaces, int numFaces, + float center[3]) +{ + float totweight; + int f; + + zero_v3(center); + + if (numFaces == 0) + return false; + + totweight = 0.0f; + for (f = 0; f < numFaces; ++f) { + MFace *face = &mfaces[f]; + MVert *v1 = &mverts[face->v1]; + MVert *v2 = &mverts[face->v2]; + MVert *v3 = &mverts[face->v3]; + MVert *v4 = &mverts[face->v4]; + float area; + + area = area_tri_v3(v1->co, v2->co, v3->co); + madd_v3_v3fl(center, v1->co, area); + madd_v3_v3fl(center, v2->co, area); + madd_v3_v3fl(center, v3->co, area); + totweight += area; + + if (face->v4) { + area = area_tri_v3(v3->co, v4->co, v1->co); + madd_v3_v3fl(center, v3->co, area); + madd_v3_v3fl(center, v4->co, area); + madd_v3_v3fl(center, v1->co, area); + totweight += area; + } + } + if (totweight == 0.0f) + return false; + + mul_v3_fl(center, 1.0f / (3.0f * totweight)); + + return true; +} + +void BKE_mesh_calc_volume(MVert *mverts, int numVerts, + MFace *mfaces, int numFaces, + float *r_vol, float *r_com) +{ + float center[3]; + float totvol; + int f; + + if (r_vol) *r_vol = 0.0f; + if (r_com) zero_v3(r_com); + + if (numFaces == 0) + return; + + if (!mesh_calc_center_centroid_ex(mverts, numVerts, mfaces, numFaces, center)) + return; + + totvol = 0.0f; + for (f = 0; f < numFaces; ++f) { + MFace *face = &mfaces[f]; + MVert *v1 = &mverts[face->v1]; + MVert *v2 = &mverts[face->v2]; + MVert *v3 = &mverts[face->v3]; + MVert *v4 = &mverts[face->v4]; + float vol; + + vol = volume_tetrahedron_signed_v3(center, v1->co, v2->co, v3->co); + if (r_vol) { + totvol += vol; + } + if (r_com) { + /* averaging factor 1/4 is applied in the end */ + madd_v3_v3fl(r_com, center, vol); // XXX could extract this + madd_v3_v3fl(r_com, v1->co, vol); + madd_v3_v3fl(r_com, v2->co, vol); + madd_v3_v3fl(r_com, v3->co, vol); + } + + if (face->v4) { + vol = volume_tetrahedron_signed_v3(center, v3->co, v4->co, v1->co); + + if (r_vol) { + totvol += vol; + } + if (r_com) { + /* averaging factor 1/4 is applied in the end */ + madd_v3_v3fl(r_com, center, vol); // XXX could extract this + madd_v3_v3fl(r_com, v3->co, vol); + madd_v3_v3fl(r_com, v4->co, vol); + madd_v3_v3fl(r_com, v1->co, vol); + } + } + } + + /* Note: Depending on arbitrary centroid position, + * totvol can become negative even for a valid mesh. + * The true value is always the positive value. + */ + if (r_vol) { + *r_vol = fabsf(totvol); + } + if (r_com) { + /* Note: Factor 1/4 is applied once for all vertices here. + * This also automatically negates the vector if totvol is negative. + */ + if (totvol != 0.0f) + mul_v3_fl(r_com, 0.25f / totvol); + } +} + + +/* -------------------------------------------------------------------- */ + /** \name NGon Tessellation (NGon/Tessface Conversion) * \{ */ @@ -1161,9 +1296,9 @@ void BKE_mesh_loops_to_mface_corners( /** * Convert all CD layers from loop/poly to tessface data. * - * @loopindices is an array of an int[4] per tessface, mapping tessface's verts to loops indices. + * \param loopindices is an array of an int[4] per tessface, mapping tessface's verts to loops indices. * - * Note when mface is not NULL, mface[face_index].v4 is used to test quads, else, loopindices[face_index][3] is used. + * \note when mface is not NULL, mface[face_index].v4 is used to test quads, else, loopindices[face_index][3] is used. */ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData *pdata, MFace *mface, int *polyindices, unsigned int (*loopindices)[4], const int num_faces) @@ -1246,7 +1381,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData /** * Recreate tessellation. * - * @do_face_nor_copy controls whether the normals from the poly are copied to the tessellated faces. + * \param do_face_nor_copy controls whether the normals from the poly are copied to the tessellated faces. * * \return number of tessellation faces. */ @@ -1397,7 +1532,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat mul_v2_m3v3(projverts[j], axis_mat, mvert[ml->v].co); } - BLI_polyfill_calc_arena((const float (*)[2])projverts, mp_totloop, tris, arena); + BLI_polyfill_calc_arena((const float (*)[2])projverts, mp_totloop, -1, tris, arena); /* apply fill */ for (j = 0; j < totfilltri; j++) { @@ -2096,11 +2231,10 @@ void BKE_mesh_calc_relative_deform( float tvec[3]; - barycentric_transform( - tvec, vert_cos_dst[v_curr], - vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next], - vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next] - ); + transform_point_by_tri_v3( + tvec, vert_cos_dst[v_curr], + vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next], + vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]); add_v3_v3(vert_cos_new[v_curr], tvec); vert_accum[v_curr] += 1; diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 65c576dd6a0..53d1aae104c 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -416,18 +416,22 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, while (ps_curr_idx != ps_end_idx) { const MPoly *mp; const MLoop *ml; + bool sharp_poly; int j; poly = poly_stack[ps_curr_idx++]; BLI_assert(poly_groups[poly] == poly_group_id); mp = &mpoly[poly]; + sharp_poly = !(mp->flag & ME_SMOOTH); for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) { /* loop over poly users */ const MeshElemMap *map_ele = &edge_poly_map[ml->e]; const int *p = map_ele->indices; int i = map_ele->count; - if (!(medge[ml->e].flag & ME_SHARP)) { + /* Edge is smooth only if its poly is not sharp, edge is not sharp, + * and edge is used by exactly two polygons. */ + if (!sharp_poly && !(medge[ml->e].flag & ME_SHARP) && i == 2) { for (; i--; p++) { /* if we meet other non initialized its a bug */ BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id)); @@ -442,7 +446,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */ for (; i--; p++) { int bit = poly_groups[*p]; - if (!ELEM3(bit, 0, poly_group_id, poly_group_id_overflowed) && + if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) && !(bit_poly_group_mask & bit)) { bit_poly_group_mask |= bit; @@ -482,6 +486,11 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, } } + if (use_bitflags) { + /* used bits are zero-based. */ + tot_group++; + } + if (UNLIKELY(group_id_overflow)) { int i = totpoly, *gid = poly_groups; for (; i--; gid++) { @@ -489,13 +498,15 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, *gid = 0; } } + /* Using 0 as group id adds one more group! */ + tot_group++; } MEM_freeN(edge_poly_map); MEM_freeN(edge_poly_mem); MEM_freeN(poly_stack); - *r_totgroup = tot_group + 1; + *r_totgroup = tot_group; return poly_groups; } diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 858fe83b43f..f3a9e894eb3 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -164,16 +164,20 @@ static int search_poly_cmp(const void *v1, const void *v2) { const SortPoly *sp1 = v1, *sp2 = v2; const int max_idx = sp1->numverts > sp2->numverts ? sp2->numverts : sp1->numverts; - int idx = 0; + int idx; /* Reject all invalid polys at end of list! */ if (sp1->invalid || sp2->invalid) - return sp1->invalid && sp2->invalid ? 0 : sp1->invalid ? 1 : -1; - /* Else, sort on first non-egal verts (remember verts of valid polys are sorted). */ - while (idx < max_idx && sp1->verts[idx] == sp2->verts[idx]) - idx++; - return sp1->verts[idx] > sp2->verts[idx] ? 1 : sp1->verts[idx] < sp2->verts[idx] ? -1 : - sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0; + return sp1->invalid ? (sp2->invalid ? 0 : 1) : -1; + /* Else, sort on first non-equal verts (remember verts of valid polys are sorted). */ + for (idx = 0; idx < max_idx; idx++) { + const int v1 = sp1->verts[idx]; + const int v2 = sp2->verts[idx]; + if (v1 != v2) { + return (v1 > v2) ? 1 : -1; + } + } + return sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0; } static int search_polyloop_cmp(const void *v1, const void *v2) @@ -255,7 +259,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, do_edge_recalc = do_fixes; } - for (i = 1; i < totvert; i++, mv++) { + for (i = 0; i < totvert; i++, mv++) { bool fix_normal = true; for (j = 0; j < 3; j++) { @@ -498,8 +502,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, PRINT_ERR("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v); sp->invalid = true; } - - mverts[ml->v].flag |= ME_VERT_TMP_TAG; + else { + mverts[ml->v].flag |= ME_VERT_TMP_TAG; + } *v = ml->v; } @@ -909,8 +914,6 @@ static bool mesh_validate_customdata(CustomData *data, CustomDataMask mask, return is_valid; } -#undef PRINT - /** * \returns is_valid. */ @@ -1052,8 +1055,36 @@ void BKE_mesh_cd_validate(Mesh *me) } } } -/** \} */ +/** + * Check all material indices of polygons are valid, invalid ones are set to 0. + * \returns is_valid. + */ +int BKE_mesh_validate_material_indices(Mesh *me) +{ + MPoly *mp; + const int max_idx = max_ii(0, me->totcol - 1); + const int totpoly = me->totpoly; + int i; + bool is_valid = true; + + for (mp = me->mpoly, i = 0; i < totpoly; i++, mp++) { + if (mp->mat_nr > max_idx) { + mp->mat_nr = 0; + is_valid = false; + } + } + + if (!is_valid) { + DAG_id_tag_update(&me->id, OB_RECALC_DATA); + return true; + } + else { + return false; + } +} + +/** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 563831616de..a9e853c873e 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -171,11 +171,14 @@ bool modifier_isPreview(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (!(mti->flags & eModifierTypeFlag_UsesPreview)) + /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */ + if (!((mti->flags & eModifierTypeFlag_UsesPreview) || (mti->type == eModifierTypeType_Constructive))) { return false; + } - if (md->mode & eModifierMode_Realtime) + if (md->mode & eModifierMode_Realtime) { return true; + } return false; } @@ -350,6 +353,7 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC /* Find the last modifier acting on the cage. */ for (i = 0; md; i++, md = md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + bool supports_mapping; md->scene = scene; @@ -357,16 +361,17 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue; if (md->mode & eModifierMode_DisableTemporary) continue; - if (!modifier_supportsMapping(md)) - break; - - if (r_lastPossibleCageIndex) { + supports_mapping = modifier_supportsMapping(md); + if (r_lastPossibleCageIndex && supports_mapping) { *r_lastPossibleCageIndex = i; } if (!(md->mode & eModifierMode_Realtime)) continue; if (!(md->mode & eModifierMode_Editmode)) continue; + if (!supports_mapping) + break; + if (md->mode & eModifierMode_OnCage) cageIndex = i; } @@ -409,13 +414,12 @@ bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode md->scene = scene; - if ((md->mode & required_mode) != required_mode) return 0; - if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return 0; - if (md->mode & eModifierMode_DisableTemporary) return 0; - if (required_mode & eModifierMode_Editmode) - if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0; + if ((md->mode & required_mode) != required_mode) return false; + if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return false; + if (md->mode & eModifierMode_DisableTemporary) return false; + if ((required_mode & eModifierMode_Editmode) && !(mti->flags & eModifierTypeFlag_SupportsEditmode)) return false; - return 1; + return true; } CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData *md, @@ -709,7 +713,7 @@ const char *modifier_path_relbase(Object *ob) else { /* last resort, better then using "" which resolves to the current * working directory */ - return BLI_temporary_dir(); + return BLI_temp_dir_session(); } } @@ -719,7 +723,7 @@ void modifier_path_init(char *path, int path_maxlen, const char *name) /* elubie: changed this to default to the same dir as the render output * to prevent saving to C:\ on Windows */ BLI_join_dirfile(path, path_maxlen, - G.relbase_valid ? "//" : BLI_temporary_dir(), + G.relbase_valid ? "//" : BLI_temp_dir_session(), name); } diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index c1726da32ae..645567eea67 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -70,7 +70,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal) int i, j, totvert, totedge /* , totface */ /* UNUSED */ ; bool is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0); bool is_cddm = (dm->type == DM_TYPE_CDDM); /* duplicate the arrays for non cddm */ - char has_orig_hflag = 0; + char has_orig_htype = 0; int cd_vert_bweight_offset; int cd_edge_bweight_offset; @@ -78,9 +78,9 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal) if (is_init == false) { /* check if we have an origflag */ - has_orig_hflag |= CustomData_has_layer(&bm->vdata, CD_ORIGINDEX) ? BM_VERT : 0; - has_orig_hflag |= CustomData_has_layer(&bm->edata, CD_ORIGINDEX) ? BM_EDGE : 0; - has_orig_hflag |= CustomData_has_layer(&bm->pdata, CD_ORIGINDEX) ? BM_FACE : 0; + has_orig_htype |= CustomData_has_layer(&bm->vdata, CD_ORIGINDEX) ? BM_VERT : 0; + has_orig_htype |= CustomData_has_layer(&bm->edata, CD_ORIGINDEX) ? BM_EDGE : 0; + has_orig_htype |= CustomData_has_layer(&bm->pdata, CD_ORIGINDEX) ? BM_FACE : 0; } /*merge custom data layout*/ @@ -118,7 +118,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal) /* add bevel weight */ if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mv->bweight / 255.0f); - if (UNLIKELY(has_orig_hflag & BM_VERT)) { + if (UNLIKELY(has_orig_htype & BM_VERT)) { int *orig_index = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_ORIGINDEX); *orig_index = ORIGINDEX_NONE; } @@ -141,7 +141,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal) if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)me->bweight / 255.0f); if (cd_edge_crease_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)me->crease / 255.0f); - if (UNLIKELY(has_orig_hflag & BM_EDGE)) { + if (UNLIKELY(has_orig_htype & BM_EDGE)) { int *orig_index = CustomData_bmesh_get(&bm->edata, e->head.data, CD_ORIGINDEX); *orig_index = ORIGINDEX_NONE; } @@ -188,7 +188,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal) } } - if (UNLIKELY(has_orig_hflag & BM_FACE)) { + if (UNLIKELY(has_orig_htype & BM_FACE)) { int *orig_index = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_ORIGINDEX); *orig_index = ORIGINDEX_NONE; } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 35bf453c328..e28adb7c0e0 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -406,27 +406,14 @@ static unsigned int moviecache_hashhash(const void *keyv) return rval; } -static int moviecache_hashcmp(const void *av, const void *bv) +static bool moviecache_hashcmp(const void *av, const void *bv) { const MovieClipImBufCacheKey *a = (MovieClipImBufCacheKey *)av; const MovieClipImBufCacheKey *b = (MovieClipImBufCacheKey *)bv; - if (a->framenr < b->framenr) - return -1; - else if (a->framenr > b->framenr) - return 1; - - if (a->proxy < b->proxy) - return -1; - else if (a->proxy > b->proxy) - return 1; - - if (a->render_flag < b->render_flag) - return -1; - else if (a->render_flag > b->render_flag) - return 1; - - return 0; + return ((a->framenr != b->framenr) || + (a->proxy != b->proxy) || + (a->render_flag != b->render_flag)); } static void *moviecache_getprioritydata(void *key_v) diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 3d8e35699a9..9f5e049fe24 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -112,7 +112,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, /* assumed to be at hi_level (or * null) */ - BLI_bitmap *prev_hidden) + const BLI_bitmap *prev_hidden) { BLI_bitmap *subd; int hi_gridsize = BKE_ccg_gridsize(hi_level); @@ -126,7 +126,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, if (lo_level == hi_level) return MEM_dupallocN(lo_hidden); - subd = BLI_BITMAP_NEW(hi_gridsize * hi_gridsize, "MDisps.hidden upsample"); + subd = BLI_BITMAP_NEW(SQUARE(hi_gridsize), "MDisps.hidden upsample"); factor = BKE_ccg_factor(lo_level, hi_level); offset = 1 << (hi_level - lo_level - 1); @@ -134,7 +134,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, /* low-res blocks */ for (yl = 0; yl < lo_gridsize; yl++) { for (xl = 0; xl < lo_gridsize; xl++) { - int lo_val = BLI_BITMAP_GET(lo_hidden, yl * lo_gridsize + xl); + int lo_val = BLI_BITMAP_TEST(lo_hidden, yl * lo_gridsize + xl); /* high-res blocks */ for (yo = -offset; yo <= offset; yo++) { @@ -153,13 +153,15 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, /* If prev_hidden is available, copy it to * subd, except when the equivalent element in * lo_hidden is different */ - if (lo_val != prev_hidden[hi_ndx]) - BLI_BITMAP_MODIFY(subd, hi_ndx, lo_val); - else - BLI_BITMAP_MODIFY(subd, hi_ndx, prev_hidden[hi_ndx]); + if (lo_val != prev_hidden[hi_ndx]) { + BLI_BITMAP_SET(subd, hi_ndx, lo_val); + } + else { + BLI_BITMAP_SET(subd, hi_ndx, prev_hidden[hi_ndx]); + } } else { - BLI_BITMAP_MODIFY(subd, hi_ndx, lo_val); + BLI_BITMAP_SET(subd, hi_ndx, lo_val); } } } @@ -180,17 +182,15 @@ static BLI_bitmap *multires_mdisps_downsample_hidden(BLI_bitmap *old_hidden, BLI_assert(new_level <= old_level); factor = BKE_ccg_factor(new_level, old_level); - new_hidden = BLI_BITMAP_NEW(new_gridsize * new_gridsize, - "downsample hidden"); - + new_hidden = BLI_BITMAP_NEW(SQUARE(new_gridsize), "downsample hidden"); for (y = 0; y < new_gridsize; y++) { for (x = 0; x < new_gridsize; x++) { - old_value = BLI_BITMAP_GET(old_hidden, + old_value = BLI_BITMAP_TEST(old_hidden, factor * y * old_gridsize + x * factor); - BLI_BITMAP_MODIFY(new_hidden, y * new_gridsize + x, old_value); + BLI_BITMAP_SET(new_hidden, y * new_gridsize + x, old_value); } } @@ -248,15 +248,15 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level) MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); int gridsize = BKE_ccg_gridsize(level); - int gridarea = gridsize * gridsize; - int i, j, k; + int gridarea = SQUARE(gridsize); + int i, j; for (i = 0; i < me->totpoly; i++) { - int hide = 0; + bool hide = false; for (j = 0; j < me->mpoly[i].totloop; j++) { if (me->mvert[me->mloop[me->mpoly[i].loopstart + j].v].flag & ME_HIDE) { - hide = 1; + hide = true; break; } } @@ -270,9 +270,7 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level) BLI_assert(!md->hidden); md->hidden = BLI_BITMAP_NEW(gridarea, "MDisps.hidden initialize"); - - for (k = 0; k < gridarea; k++) - BLI_BITMAP_SET(md->hidden, k); + BLI_BITMAP_SET_ALL(md->hidden, true, gridarea); } } @@ -286,7 +284,7 @@ DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob DerivedMesh *tdm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); DerivedMesh *dm; - dm = mti->applyModifier(md, ob, tdm, MOD_APPLY_USECACHE); + dm = mti->applyModifier(md, ob, tdm, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY); if (dm == tdm) { dm = CDDM_copy(tdm); } @@ -338,12 +336,15 @@ MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, bool use_f return mmd; } -static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render) +static int multires_get_level(Object *ob, MultiresModifierData *mmd, + bool render, bool ignore_simplify) { if (render) return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl) : mmd->renderlvl; else if (ob->mode == OB_MODE_SCULPT) return mmd->sculptlvl; + else if (ignore_simplify) + return mmd->lvl; else return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl) : mmd->lvl; } @@ -433,7 +434,7 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm int numVerts, result; float (*deformedVerts)[3]; - if (multires_get_level(ob, mmd, 0) == 0) + if (multires_get_level(ob, mmd, false, true) == 0) return 0; /* Create DerivedMesh for deformation modifier */ @@ -596,7 +597,7 @@ static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level) { if (level < gpm->level) { int gridsize = BKE_ccg_gridsize(level); - float *data = MEM_callocN(sizeof(float) * gridsize * gridsize, + float *data = MEM_callocN(sizeof(float) * SQUARE(gridsize), "multires_grid_paint_mask_downsample"); int x, y; @@ -682,7 +683,7 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction) { Mesh *me = BKE_mesh_from_object(ob); - int lvl = multires_get_level(ob, mmd, 0); + int lvl = multires_get_level(ob, mmd, false, true); int levels = mmd->totlvl - lvl; MDisps *mdisps; @@ -1431,7 +1432,9 @@ DerivedMesh *multires_make_derived_from_derived(DerivedMesh *dm, CCGDerivedMesh *ccgdm = NULL; CCGElem **gridData, **subGridData; CCGKey key; - int lvl = multires_get_level(ob, mmd, (flags & MULTIRES_USE_RENDER_PARAMS)); + const bool render = (flags & MULTIRES_USE_RENDER_PARAMS) != 0; + const bool ignore_simplify = (flags & MULTIRES_IGNORE_SIMPLIFY) != 0; + int lvl = multires_get_level(ob, mmd, render, ignore_simplify); int i, gridSize, numGrids; if (lvl == 0) diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c index 64d59b165e1..6c3f4d545d3 100644 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ b/source/blender/blenkernel/intern/navmesh_conversion.c @@ -305,7 +305,7 @@ struct SortContext { const int *trisToFacesMap; }; -static int compareByData(void *ctx, const void *a, const void *b) +static int compareByData(const void *a, const void *b, void *ctx) { return (((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int *)a]] - ((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int *)b]]); @@ -341,7 +341,7 @@ int buildNavMeshData(const int nverts, const float *verts, trisMapping[i] = i; context.recastData = recastData; context.trisToFacesMap = trisToFacesMap; - BLI_qsort_r(trisMapping, ntris, sizeof(int), &context, compareByData); + BLI_qsort_r(trisMapping, ntris, sizeof(int), compareByData, &context); /* search first valid triangle - triangle of convex polygon */ validTriStart = -1; diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 0c244e8a40b..19e45142960 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -157,8 +157,10 @@ void free_nladata(ListBase *tracks) /* Copying ------------------------------------------- */ -/* Copy NLA strip - * < use_same_action: if true, the existing action is used (instead of being duplicated) +/** + * Copy NLA strip + * + * \param use_same_action When true, the existing action is used (instead of being duplicated) */ NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action) { @@ -428,7 +430,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short return (strip->end + (strip->actstart * scale - cframe)) / scale; } else { /* if (mode == NLATIME_CONVERT_EVAL) */ - if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) { + if (IS_EQF((float)cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) { /* this case prevents the motion snapping back to the first frame at the end of the strip * by catching the case where repeats is a whole number, which means that the end of the strip * could also be interpreted as the end of the start of a repeat @@ -451,7 +453,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short return strip->actstart + (cframe - strip->start) / scale; } else { /* if (mode == NLATIME_CONVERT_EVAL) */ - if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) { + if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) { /* this case prevents the motion snapping back to the first frame at the end of the strip * by catching the case where repeats is a whole number, which means that the end of the strip * could also be interpreted as the end of the start of a repeat @@ -1635,7 +1637,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) } } - if (ELEM3(NULL, activeTrack, activeStrip, activeStrip->act)) { + if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) { if (G.debug & G_DEBUG) { printf("NLA tweakmode enter - neither active requirement found\n"); printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip); @@ -1742,7 +1744,7 @@ static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimDat * 1) Scene and AnimData must be provided * 2) there must be tracks to merge... */ - if (ELEM3(NULL, scene, adt, adt->nla_tracks.first)) + if (ELEM(NULL, scene, adt, adt->nla_tracks.first)) return; /* if animdata currently has an action, 'push down' this onto the stack first */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index ce1e34de0b0..3a7bfb03e07 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -174,7 +174,7 @@ static void node_set_typeinfo(const struct bContext *C, bNodeTree *ntree, bNode { /* for nodes saved in older versions storage can get lost, make undefined then */ if (node->flag & NODE_INIT) { - if (typeinfo->storagename[0] && !node->storage) + if (typeinfo && typeinfo->storagename[0] && !node->storage) typeinfo = NULL; } @@ -1205,13 +1205,13 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_ return newtree; } -bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const bool do_id_user) +bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user) { - return ntreeCopyTree_internal(ntree, G.main, do_id_user, true, true); + return ntreeCopyTree_internal(ntree, bmain, do_id_user, true, true); } bNodeTree *ntreeCopyTree(bNodeTree *ntree) { - return ntreeCopyTree_ex(ntree, true); + return ntreeCopyTree_ex(ntree, G.main, true); } /* use when duplicating scenes */ @@ -1777,7 +1777,7 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user) if (tntree == ntree) break; if (tntree == NULL) { - BKE_libblock_free_data(&ntree->id); + BKE_libblock_free_data(G.main, &ntree->id); } } /* same as ntreeFreeTree_ex but always manage users */ @@ -2682,16 +2682,12 @@ static unsigned int node_instance_hash_key(const void *key) return ((const bNodeInstanceKey *)key)->value; } -static int node_instance_hash_key_cmp(const void *a, const void *b) +static bool node_instance_hash_key_cmp(const void *a, const void *b) { unsigned int value_a = ((const bNodeInstanceKey *)a)->value; unsigned int value_b = ((const bNodeInstanceKey *)b)->value; - if (value_a == value_b) - return 0; - else if (value_a < value_b) - return -1; - else - return 1; + + return (value_a != value_b); } bNodeInstanceHash *BKE_node_instance_hash_new(const char *info) @@ -3406,6 +3402,7 @@ static void registerCompositNodes(void) register_node_type_cmp_inpaint(); register_node_type_cmp_despeckle(); register_node_type_cmp_defocus(); + register_node_type_cmp_sunbeams(); register_node_type_cmp_valtorgb(); register_node_type_cmp_rgbtobw(); @@ -3495,6 +3492,8 @@ static void registerShaderNodes(void) register_node_type_sh_combrgb(); register_node_type_sh_sephsv(); register_node_type_sh_combhsv(); + register_node_type_sh_sepxyz(); + register_node_type_sh_combxyz(); register_node_type_sh_hue_sat(); register_node_type_sh_attribute(); @@ -3526,10 +3525,12 @@ static void registerShaderNodes(void) register_node_type_sh_mix_shader(); register_node_type_sh_add_shader(); register_node_type_sh_uvmap(); + register_node_type_sh_uvalongstroke(); register_node_type_sh_output_lamp(); register_node_type_sh_output_material(); register_node_type_sh_output_world(); + register_node_type_sh_output_linestyle(); register_node_type_sh_tex_image(); register_node_type_sh_tex_environment(); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d99086a626a..53b0e0cf4a1 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -42,6 +42,7 @@ #include "DNA_constraint_types.h" #include "DNA_group_types.h" #include "DNA_key_types.h" +#include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_material_types.h" #include "DNA_meta_types.h" @@ -180,10 +181,11 @@ void BKE_object_free_curve_cache(Object *ob) { if (ob->curve_cache) { BKE_displist_free(&ob->curve_cache->disp); - BLI_freelistN(&ob->curve_cache->bev); + BKE_curve_bevelList_free(&ob->curve_cache->bev); if (ob->curve_cache->path) { free_path(ob->curve_cache->path); } + BKE_nurbList_free(&ob->curve_cache->deformed_nurbs); MEM_freeN(ob->curve_cache); ob->curve_cache = NULL; } @@ -246,7 +248,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) ModifierData *md; BKE_object_free_modifiers(ob_dst); - if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (!ELEM(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { /* only objects listed above can have modifiers and linking them to objects * which doesn't have modifiers stack is quite silly */ return; @@ -255,11 +257,11 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) for (md = ob_src->modifiers.first; md; md = md->next) { ModifierData *nmd = NULL; - if (ELEM4(md->type, - eModifierType_Hook, - eModifierType_Softbody, - eModifierType_ParticleInstance, - eModifierType_Collision)) + if (ELEM(md->type, + eModifierType_Hook, + eModifierType_Softbody, + eModifierType_ParticleInstance, + eModifierType_Collision)) { continue; } @@ -296,7 +298,7 @@ void BKE_object_free_derived_caches(Object *ob) me->bb->flag |= BOUNDBOX_DIRTY; } } - else if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { + else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { Curve *cu = ob->data; if (cu->bb) { @@ -320,18 +322,7 @@ void BKE_object_free_derived_caches(Object *ob) ob->derivedDeform = NULL; } - if (ob->curve_cache) { - BKE_displist_free(&ob->curve_cache->disp); - BLI_freelistN(&ob->curve_cache->bev); - if (ob->curve_cache->path) { - free_path(ob->curve_cache->path); - ob->curve_cache->path = NULL; - } - - /* Signal for viewport to run DAG workarounds. */ - MEM_freeN(ob->curve_cache); - ob->curve_cache = NULL; - } + BKE_object_free_curve_cache(ob); } /* do not free object itself */ @@ -408,7 +399,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user) /* Free runtime curves data. */ if (ob->curve_cache) { - BLI_freelistN(&ob->curve_cache->bev); + BKE_curve_bevelList_free(&ob->curve_cache->bev); if (ob->curve_cache->path) free_path(ob->curve_cache->path); MEM_freeN(ob->curve_cache); @@ -709,7 +700,7 @@ void BKE_object_unlink(Object *ob) lineset; lineset = lineset->next) { if (lineset->linestyle) { - BKE_unlink_linestyle_target_object(lineset->linestyle, ob); + BKE_linestyle_target_object_unlink(lineset->linestyle, ob); } } } @@ -873,9 +864,9 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob) { if (ob->type == OB_MESH) { Mesh *me = ob->data; - return ( (ob->mode & OB_MODE_WEIGHT_PAINT) && - (me->edit_btmesh == NULL) && - (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX) ); + return ((ob->mode & OB_MODE_WEIGHT_PAINT) && + (me->edit_btmesh == NULL) && + (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX)); } return false; @@ -977,7 +968,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) ob->empty_drawtype = OB_PLAINAXES; ob->empty_drawsize = 1.0; - if (ELEM3(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { + if (ELEM(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { ob->trackflag = OB_NEGZ; ob->upflag = OB_POSY; } @@ -1066,10 +1057,10 @@ void BKE_object_lod_add(Object *ob) BLI_addtail(&ob->lodlevels, lod); } -static int lod_cmp(void *a, void *b) +static int lod_cmp(const void *a, const void *b) { - LodLevel *loda = (LodLevel *)a; - LodLevel *lodb = (LodLevel *)b; + const LodLevel *loda = a; + const LodLevel *lodb = b; if (loda->distance < lodb->distance) return -1; return loda->distance > lodb->distance; @@ -1125,7 +1116,7 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3]) } else { /* check for lower LoD */ - while (current->next && dist_sq > (current->next->distance * current->next->distance)) { + while (current->next && dist_sq > SQUARE(current->next->distance)) { current = current->next; } } @@ -1479,7 +1470,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) defgroup_copy_list(&obn->defbase, &ob->defbase); BKE_constraints_copy(&obn->constraints, &ob->constraints, true); - obn->mode = 0; + obn->mode = OB_MODE_OBJECT; obn->sculpt = NULL; /* increase user numbers */ @@ -1526,6 +1517,18 @@ Object *BKE_object_copy(Object *ob) return BKE_object_copy_ex(G.main, ob, false); } +static void extern_local_object__modifiersForeachIDLink( + void *UNUSED(userData), Object *UNUSED(ob), + ID **idpoin) +{ + if (*idpoin) { + /* intentionally omit ID_OB */ + if (ELEM(GS((*idpoin)->name), ID_IM, ID_TE)) { + id_lib_extern(*idpoin); + } + } +} + static void extern_local_object(Object *ob) { ParticleSystem *psys; @@ -1539,6 +1542,8 @@ static void extern_local_object(Object *ob) for (psys = ob->particlesystem.first; psys; psys = psys->next) id_lib_extern((ID *)psys->part); + + modifiers_foreachIDLink(ob, extern_local_object__modifiersForeachIDLink, NULL); } void BKE_object_make_local(Object *ob) @@ -1778,6 +1783,55 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob) ob->dt = target->dt; } +/** + * Use with newly created objects to set their size + * (used to apply scene-scale). + */ +void BKE_object_obdata_size_init(struct Object *ob, const float size) +{ + /* apply radius as a scale to types that support it */ + switch (ob->type) { + case OB_EMPTY: + { + ob->empty_drawsize *= size; + break; + } + case OB_FONT: + { + Curve *cu = ob->data; + cu->fsize *= size; + break; + } + case OB_CAMERA: + { + Camera *cam = ob->data; + cam->drawsize *= size; + break; + } + case OB_LAMP: + { + Lamp *lamp = ob->data; + lamp->dist *= size; + lamp->area_size *= size; + lamp->area_sizey *= size; + lamp->area_sizez *= size; + break; + } + /* Only lattice (not mesh, curve, mball...), + * because its got data when newly added */ + case OB_LATTICE: + { + struct Lattice *lt = ob->data; + float mat[4][4]; + + unit_m4(mat); + scale_m4_fl(mat, size); + + BKE_lattice_transform(lt, (float (*)[4])mat, false); + break; + } + } +} /* *************** CALC ****************** */ @@ -1978,7 +2032,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4]) unit_m4(mat); cu = par->data; - if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */ + if (ELEM(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */ BKE_displist_make_curveTypes(scene, par, 0); if (par->curve_cache->path == NULL) return; @@ -1994,17 +2048,20 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4]) * we divide the curvetime calculated in the previous step by the length of the path, to get a time * factor, which then gets clamped to lie within 0.0 - 1.0 range */ - if (IS_EQF(cu->pathlen, 0.0f) == 0) + if (cu->pathlen) { ctime = cu->ctime / cu->pathlen; - else + } + else { ctime = cu->ctime; + } CLAMP(ctime, 0.0f, 1.0f); } else { ctime = BKE_scene_frame_get(scene); - if (IS_EQF(cu->pathlen, 0.0f) == 0) + if (cu->pathlen) { ctime /= cu->pathlen; + } CLAMP(ctime, 0.0f, 1.0f); } @@ -2152,8 +2209,18 @@ static void give_parvert(Object *par, int nr, float vec[3]) } } else if (ELEM(par->type, OB_CURVE, OB_SURF)) { - Curve *cu = par->data; - ListBase *nurb = BKE_curve_nurbs_get(cu); + ListBase *nurb; + + /* Unless there's some weird depsgraph failure the cache should exist. */ + BLI_assert(par->curve_cache != NULL); + + if (par->curve_cache->deformed_nurbs.first != NULL) { + nurb = &par->curve_cache->deformed_nurbs; + } + else { + Curve *cu = par->data; + nurb = BKE_curve_nurbs_get(cu); + } BKE_nurbList_index_get_co(nurb, nr, vec); } @@ -2289,7 +2356,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat int a; /* include framerate */ - fac1 = (1.0f / (1.0f + fabsf(ob->sf)) ); + fac1 = (1.0f / (1.0f + fabsf(ob->sf))); if (fac1 >= 1.0f) return 0; fac2 = 1.0f - fac1; @@ -2466,6 +2533,20 @@ void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float bb->vec[1][2] = bb->vec[2][2] = bb->vec[5][2] = bb->vec[6][2] = max[2]; } +void BKE_boundbox_calc_center_aabb(const BoundBox *bb, float r_cent[3]) +{ + r_cent[0] = 0.5f * (bb->vec[0][0] + bb->vec[4][0]); + r_cent[1] = 0.5f * (bb->vec[0][1] + bb->vec[2][1]); + r_cent[2] = 0.5f * (bb->vec[0][2] + bb->vec[1][2]); +} + +void BKE_boundbox_calc_size_aabb(const BoundBox *bb, float r_size[3]) +{ + r_size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]); + r_size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]); + r_size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]); +} + BoundBox *BKE_object_boundbox_get(Object *ob) { BoundBox *bb = NULL; @@ -2473,7 +2554,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob) if (ob->type == OB_MESH) { bb = BKE_mesh_boundbox_get(ob); } - else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { bb = BKE_curve_boundbox_get(ob); } else if (ob->type == OB_MBALL) { @@ -2483,7 +2564,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob) } /* used to temporally disable/enable boundbox */ -void BKE_object_boundbox_flag(Object *ob, int flag, int set) +void BKE_object_boundbox_flag(Object *ob, int flag, const bool set) { BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { @@ -2907,6 +2988,12 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, { BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL; uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH; +#ifdef WITH_FREESTYLE + /* make sure Freestyle edge/face marks appear in DM for render (see T40315) */ + if (eval_ctx->mode != DAG_EVAL_VIEWPORT) { + data_mask |= CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE; + } +#endif if (em) { makeDerivedMesh(scene, ob, em, data_mask, 0); /* was CD_MASK_BAREMESH */ } @@ -2969,7 +3056,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, lamp_drivers_update(scene, ob->data, ctime); /* particles */ - if (ob->particlesystem.first) { + if (ob != scene->obedit && ob->particlesystem.first) { ParticleSystem *tpsys, *psys; DerivedMesh *dm; ob->transflag &= ~OB_DUPLIPARTS; @@ -2983,7 +3070,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, if (psys_check_enabled(ob, psys)) { /* check use of dupli objects here */ - if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->for_render) && + if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) && ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) || (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group))) { @@ -3003,7 +3090,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, psys = psys->next; } - if (eval_ctx->for_render && ob->transflag & OB_DUPLIPARTS) { + if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) { /* this is to make sure we get render level duplis in groups: * the derivedmesh must be created before init_render_mesh, * since object_duplilist does dupliparticles before that */ @@ -3120,8 +3207,10 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, * Test a bounding box for ray intersection * assumes the ray is already local to the boundbox space */ -bool BKE_boundbox_ray_hit_check(struct BoundBox *bb, const float ray_start[3], const float ray_normal[3], - float *r_lambda) +bool BKE_boundbox_ray_hit_check( + const struct BoundBox *bb, + const float ray_start[3], const float ray_normal[3], + float *r_lambda) { const int triangle_indexes[12][3] = { {0, 1, 2}, {0, 2, 3}, @@ -3153,9 +3242,9 @@ bool BKE_boundbox_ray_hit_check(struct BoundBox *bb, const float ray_start[3], c return result; } -static int pc_cmp(void *a, void *b) +static int pc_cmp(const void *a, const void *b) { - LinkData *ad = a, *bd = b; + const LinkData *ad = a, *bd = b; if (GET_INT_FROM_POINTER(ad->data) > GET_INT_FROM_POINTER(bd->data)) return 1; else return 0; @@ -3384,6 +3473,9 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) VirtualModifierData virtualModifierData; int flag = 0; + if (BKE_key_from_object(ob)) + flag |= eModifierMode_Realtime | eModifierMode_Render; + /* cloth */ for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md && (flag != (eModifierMode_Render | eModifierMode_Realtime)); diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 84e626a3104..0d82c6e89a1 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -101,7 +101,7 @@ static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene r_ctx->eval_ctx = eval_ctx; r_ctx->scene = scene; /* don't allow BKE_object_handle_update for viewport during render, can crash */ - r_ctx->do_update = update && !(G.is_rendering && !eval_ctx->for_render); + r_ctx->do_update = update && !(G.is_rendering && eval_ctx->mode != DAG_EVAL_RENDER); r_ctx->animated = false; r_ctx->group = NULL; @@ -162,9 +162,6 @@ static DupliObject *make_dupli(const DupliContext *ctx, dob->type = ctx->gen->type; dob->animated = animated || ctx->animated; /* object itself or some parent is animated */ - dob->origlay = ob->lay; - ob->lay = ctx->lay; - /* set persistent id, which is an array with a persistent index for each level * (particle number, vertex number, ..). by comparing this we can find the same * dupli object between frames, which is needed for motion blur. last level @@ -250,13 +247,6 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild ob->flag |= OB_DONE; /* doesnt render */ make_child_duplis_cb(ctx, userdata, ob); - - /* Set proper layer in case of scene looping, - * in case of groups the object layer will be - * changed when it's duplicated due to the - * group duplication. - */ - ob->lay = ctx->object->lay; } } } @@ -268,7 +258,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild /* OB_DUPLIGROUP */ static void make_duplis_group(const DupliContext *ctx) { - bool for_render = ctx->eval_ctx->for_render; + bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER); Object *ob = ctx->object; Group *group; GroupObject *go; @@ -458,7 +448,6 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], Object *inst_ob = vdd->inst_ob; DupliObject *dob; float obmat[4][4], space_mat[4][4]; - unsigned int origlay; /* obmat is transform to vertex */ get_duplivert_transform(co, nor_f, nor_s, vdd->use_rotation, inst_ob->trackflag, inst_ob->upflag, obmat); @@ -472,10 +461,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], */ mul_m4_m4m4(space_mat, obmat, inst_ob->imat); - origlay = vdd->inst_ob->lay; dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false); - /* restore the original layer so that each dupli will have proper dob->origlay */ - vdd->inst_ob->lay = origlay; if (vdd->orco) copy_v3_v3(dob->orco, vdd->orco[index]); @@ -524,7 +510,7 @@ static void make_duplis_verts(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; - bool for_render = ctx->eval_ctx->for_render; + bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); VertexDupliData vdd; vdd.ctx = ctx; @@ -534,7 +520,7 @@ static void make_duplis_verts(const DupliContext *ctx) { Mesh *me = parent->data; BMEditMesh *em = BKE_editmesh_from_object(parent); - CustomDataMask dm_mask = (for_render ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH); + CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH); if (em) vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); @@ -542,7 +528,7 @@ static void make_duplis_verts(const DupliContext *ctx) vdd.dm = mesh_get_derived_final(scene, parent, dm_mask); vdd.edit_btmesh = me->edit_btmesh; - if (for_render) + if (use_texcoords) vdd.orco = vdd.dm->getVertDataArray(vdd.dm, CD_ORCO); else vdd.orco = NULL; @@ -724,6 +710,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj float (*orco)[3] = fdd->orco; MLoopUV *mloopuv = fdd->mloopuv; int a, totface = fdd->totface; + bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); float child_imat[4][4]; DupliObject *dob; @@ -762,19 +749,19 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj mul_m4_m4m4(space_mat, obmat, inst_ob->imat); dob = make_dupli(ctx, inst_ob, obmat, a, false, false); - if (ctx->eval_ctx->for_render) { + if (use_texcoords) { float w = 1.0f / (float)mp->totloop; if (orco) { int j; - for (j = 0; j < mpoly->totloop; j++) { + for (j = 0; j < mp->totloop; j++) { madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w); } } if (mloopuv) { int j; - for (j = 0; j < mpoly->totloop; j++) { + for (j = 0; j < mp->totloop; j++) { madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w); } } @@ -789,7 +776,7 @@ static void make_duplis_faces(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; - bool for_render = ctx->eval_ctx->for_render; + bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); FaceDupliData fdd; fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); @@ -797,14 +784,14 @@ static void make_duplis_faces(const DupliContext *ctx) /* gather mesh info */ { BMEditMesh *em = BKE_editmesh_from_object(parent); - CustomDataMask dm_mask = (for_render ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); + CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); if (em) fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); else fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); - if (for_render) { + if (use_texcoords) { fdd.orco = fdd.dm->getVertDataArray(fdd.dm, CD_ORCO); fdd.mloopuv = fdd.dm->getLoopDataArray(fdd.dm, CD_MLOOPUV); } @@ -834,7 +821,8 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem { Scene *scene = ctx->scene; Object *par = ctx->object; - bool for_render = ctx->eval_ctx->for_render; + bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER; + bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; @@ -1051,7 +1039,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem dob = make_dupli(ctx, go->ob, mat, a, false, false); dob->particle_system = psys; - if (for_render) + if (use_texcoords) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } @@ -1100,7 +1088,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem dob = make_dupli(ctx, ob, mat, a, false, false); dob->particle_system = psys; - if (for_render) + if (use_texcoords) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); /* XXX blender internal needs this to be set to dupligroup to render * groups correctly, but we don't want this hack for cycles */ @@ -1161,7 +1149,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) return NULL; /* Should the dupli's be generated for this object? - Respect restrict flags */ - if (ctx->eval_ctx->for_render ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW)) + if (ctx->eval_ctx->mode == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW)) return NULL; if (transflag & OB_DUPLIPARTS) { @@ -1215,15 +1203,6 @@ ListBase *object_duplilist(EvaluationContext *eval_ctx, Scene *sce, Object *ob) void free_object_duplilist(ListBase *lb) { - DupliObject *dob; - - /* loop in reverse order, if object is instanced multiple times - * the original layer may not really be original otherwise, proper - * solution is more complicated */ - for (dob = lb->last; dob; dob = dob->prev) { - dob->ob->lay = dob->origlay; - } - BLI_freelistN(lb); MEM_freeN(lb); } @@ -1258,10 +1237,11 @@ int count_duplilist(Object *ob) return 1; } -DupliApplyData *duplilist_apply_matrix(ListBase *duplilist) +DupliApplyData *duplilist_apply(Object *ob, ListBase *duplilist) { DupliApplyData *apply_data = NULL; int num_objects = BLI_countlist(duplilist); + if (num_objects > 0) { DupliObject *dob; int i; @@ -1271,14 +1251,19 @@ DupliApplyData *duplilist_apply_matrix(ListBase *duplilist) "DupliObject apply extra data"); for (dob = duplilist->first, i = 0; dob; dob = dob->next, ++i) { + /* copy obmat from duplis */ copy_m4_m4(apply_data->extra[i].obmat, dob->ob->obmat); copy_m4_m4(dob->ob->obmat, dob->mat); + + /* copy layers from the main duplicator object */ + apply_data->extra[i].lay = dob->ob->lay; + dob->ob->lay = ob->lay; } } return apply_data; } -void duplilist_restore_matrix(ListBase *duplilist, DupliApplyData *apply_data) +void duplilist_restore(ListBase *duplilist, DupliApplyData *apply_data) { DupliObject *dob; int i; @@ -1288,6 +1273,8 @@ void duplilist_restore_matrix(ListBase *duplilist, DupliApplyData *apply_data) */ for (dob = duplilist->last, i = apply_data->num_objects - 1; dob; dob = dob->prev, --i) { copy_m4_m4(dob->ob->obmat, apply_data->extra[i].obmat); + + dob->ob->lay = apply_data->extra[i].lay; } } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index dafe5ca55ff..d186b4299a5 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -368,7 +368,7 @@ int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, i int checkPackedFile(const char *filename, PackedFile *pf) { - struct stat st; + BLI_stat_t st; int ret_val, i, len, file; char buf[4096]; char name[FILE_MAX]; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 1b8c4e084cf..d16575d80c8 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -45,8 +45,10 @@ #include "BLI_bitmap.h" #include "BLI_utildefines.h" #include "BLI_math_vector.h" +#include "BLI_listbase.h" #include "BKE_brush.h" +#include "BKE_main.h" #include "BKE_context.h" #include "BKE_crazyspace.h" #include "BKE_depsgraph.h" @@ -269,6 +271,98 @@ void BKE_paint_brush_set(Paint *p, Brush *br) } } +void BKE_paint_curve_free(PaintCurve *pc) +{ + if (pc->points) { + MEM_freeN(pc->points); + pc->points = NULL; + pc->tot_points = 0; + } +} + +PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name) +{ + PaintCurve *pc; + + pc = BKE_libblock_alloc(bmain, ID_PC, name); + + return pc; +} + +Palette *BKE_paint_palette(Paint *p) +{ + return p ? p->palette : NULL; +} + +void BKE_paint_palette_set(Paint *p, Palette *palette) +{ + if (p) { + id_us_min((ID *)p->palette); + id_us_plus((ID *)palette); + p->palette = palette; + } +} + +void BKE_paint_curve_set(Brush *br, PaintCurve *pc) +{ + if (br) { + id_us_min((ID *)br->paint_curve); + id_us_plus((ID *)pc); + br->paint_curve = pc; + } +} + +/* remove colour from palette. Must be certain color is inside the palette! */ +void BKE_palette_color_remove(Palette *palette, PaletteColor *color) +{ + if (color) { + int numcolors = BLI_countlist(&palette->colors); + if ((numcolors == palette->active_color + 1) && (numcolors != 1)) + palette->active_color--; + + BLI_remlink(&palette->colors, color); + BLI_addhead(&palette->deleted, color); + } +} + +void BKE_palette_cleanup(Palette *palette) +{ + BLI_freelistN(&palette->deleted); +} + + +Palette *BKE_palette_add(Main *bmain, const char *name) +{ + Palette *palette; + + palette = BKE_libblock_alloc(bmain, ID_PAL, name); + + /* enable fake user by default */ + palette->id.flag |= LIB_FAKEUSER; + + return palette; +} + +void BKE_palette_free(Palette *palette) +{ + BLI_freelistN(&palette->colors); +} + +PaletteColor *BKE_palette_color_add(Palette *palette) +{ + PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color"); + BLI_addtail(&palette->colors, color); + palette->active_color = BLI_countlist(&palette->colors) - 1; + return color; +} + + +bool BKE_palette_is_empty(const struct Palette *palette) +{ + return BLI_listbase_is_empty(&palette->colors); +} + + /* are we in vertex paint or weight pain face select mode? */ bool BKE_paint_select_face_test(Object *ob) { @@ -318,6 +412,7 @@ void BKE_paint_init(Paint *p, const char col[3]) void BKE_paint_free(Paint *paint) { id_us_min((ID *)paint->brush); + id_us_min((ID *)paint->palette); } /* called when copying scene settings, so even if 'src' and 'tar' are the same @@ -328,6 +423,7 @@ void BKE_paint_copy(Paint *src, Paint *tar) { tar->brush = src->brush; id_us_plus((ID *)tar->brush); + id_us_plus((ID *)tar->palette); } /* returns non-zero if any of the face's vertices @@ -347,10 +443,10 @@ bool paint_is_grid_face_hidden(const unsigned int *grid_hidden, int gridsize, int x, int y) { /* skip face if any of its corners are hidden */ - return (BLI_BITMAP_GET(grid_hidden, y * gridsize + x) || - BLI_BITMAP_GET(grid_hidden, y * gridsize + x + 1) || - BLI_BITMAP_GET(grid_hidden, (y + 1) * gridsize + x + 1) || - BLI_BITMAP_GET(grid_hidden, (y + 1) * gridsize + x)); + return (BLI_BITMAP_TEST(grid_hidden, y * gridsize + x) || + BLI_BITMAP_TEST(grid_hidden, y * gridsize + x + 1) || + BLI_BITMAP_TEST(grid_hidden, (y + 1) * gridsize + x + 1) || + BLI_BITMAP_TEST(grid_hidden, (y + 1) * gridsize + x)); } /* Return true if all vertices in the face are visible, false otherwise */ @@ -378,7 +474,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, return gpm->data[(y * factor) * gridsize + (x * factor)]; } -/* threshhold to move before updating the brush rotation */ +/* threshold to move before updating the brush rotation */ #define RAKE_THRESHHOLD 20 void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2]) @@ -390,7 +486,7 @@ void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_ sub_v2_v2v2(dpos, ups->last_rake, mouse_pos); if (len_squared_v2(dpos) >= r * r) { - ups->brush_rotation = atan2(dpos[0], dpos[1]); + ups->brush_rotation = atan2f(dpos[0], dpos[1]); interp_v2_v2v2(ups->last_rake, ups->last_rake, mouse_pos, u); @@ -658,14 +754,28 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, BKE_free_sculptsession_deformMats(ss); } - /* if pbvh is deformed, key block is already applied to it */ - if (ss->kb && !BKE_pbvh_isDeformed(ss->pbvh)) { - float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb); + if (ss->kb != NULL && ss->deform_cos == NULL) { + ss->deform_cos = BKE_key_convert_to_vertcos(ob, ss->kb); + } - if (vertCos) { - /* apply shape keys coordinates to PBVH */ - BKE_pbvh_apply_vertCos(ss->pbvh, vertCos); - MEM_freeN(vertCos); + /* if pbvh is deformed, key block is already applied to it */ + if (ss->kb) { + bool pbvh_deformd = BKE_pbvh_isDeformed(ss->pbvh); + if (!pbvh_deformd || ss->deform_cos == NULL) { + float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb); + + if (vertCos) { + if (!pbvh_deformd) { + /* apply shape keys coordinates to PBVH */ + BKE_pbvh_apply_vertCos(ss->pbvh, vertCos); + } + if (ss->deform_cos == NULL) { + ss->deform_cos = vertCos; + } + if (vertCos != ss->deform_cos) { + MEM_freeN(vertCos); + } + } } } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index eb657bac312..530573d6e38 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -656,7 +656,7 @@ static float psys_render_projected_area(ParticleSystem *psys, const float center } /* screen space radius */ - radius = sqrt(area / (float)M_PI); + radius = sqrtf(area / (float)M_PI); /* make smaller using fallof once over screen edge */ *viewport = 1.0f; @@ -917,8 +917,8 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t); elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t); - elem->scalemin = sqrt(elem->scalemin); - elem->scalemax = sqrt(elem->scalemax); + elem->scalemin = sqrtf(elem->scalemin); + elem->scalemax = sqrtf(elem->scalemax); /* clamp scaling */ scaleclamp = (float)min_ii(elem->totchild, 10); @@ -939,8 +939,8 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) } elem->lambda = lambda; - elem->scalemin = sqrt(elem->scalemin); - elem->scalemax = sqrt(elem->scalemax); + elem->scalemin = sqrtf(elem->scalemin); + elem->scalemax = sqrtf(elem->scalemax); elem->curchild = 0; } @@ -1657,11 +1657,14 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f index_mp_to_orig = NULL; } + totface = dm->getNumTessFaces(dm); + if (!totface) { + return DMCACHE_NOTFOUND; + } + mpoly = dm->getPolyArray(dm); osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE); - totface = dm->getNumTessFaces(dm); - if (osface == NULL || index_mf_to_mpoly == NULL) { /* Assume we don't need osface data */ if (index < totface) { @@ -1907,7 +1910,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3], float ornor[3]) { - if (psmd) { + if (psmd && psmd->dm) { if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) { if (vec) copy_v3_v3(vec, fuv); @@ -1947,10 +1950,10 @@ static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float t = time * freq * (float)M_PI; if (smooth_start) { - dt = fabs(t); + dt = fabsf(t); /* smooth the beginning of kink */ CLAMP(dt, 0.f, (float)M_PI); - dt = sin(dt / 2.f); + dt = sinf(dt / 2.f); } if (type != PART_KINK_RADIAL) { @@ -2011,12 +2014,12 @@ static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float madd_v3_v3fl(result, proj, flat); } - madd_v3_v3fl(result, par_vec, -amplitude * (float)sin(t)); + madd_v3_v3fl(result, par_vec, -amplitude * sinf(t)); break; } case PART_KINK_WAVE: { - madd_v3_v3fl(result, kink, amplitude * (float)sin(t)); + madd_v3_v3fl(result, kink, amplitude * sinf(t)); if (flat > 0.f) { float proj[3]; @@ -2051,22 +2054,22 @@ static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float if (inp_y > 0.5f) { copy_v3_v3(state_co, y_vec); - mul_v3_fl(y_vec, amplitude * (float)cos(t)); - mul_v3_fl(z_vec, amplitude / 2.f * (float)sin(2.f * t)); + mul_v3_fl(y_vec, amplitude * cosf(t)); + mul_v3_fl(z_vec, amplitude / 2.f * sinf(2.f * t)); } else if (inp_z > 0.0f) { - mul_v3_v3fl(state_co, z_vec, (float)sin((float)M_PI / 3.f)); + mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.f)); madd_v3_v3fl(state_co, y_vec, -0.5f); - mul_v3_fl(y_vec, -amplitude * (float)cos(t + (float)M_PI / 3.f)); - mul_v3_fl(z_vec, amplitude / 2.f * (float)cos(2.f * t + (float)M_PI / 6.f)); + mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.f)); + mul_v3_fl(z_vec, amplitude / 2.f * cosf(2.f * t + (float)M_PI / 6.f)); } else { - mul_v3_v3fl(state_co, z_vec, -(float)sin((float)M_PI / 3.f)); + mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.f)); madd_v3_v3fl(state_co, y_vec, -0.5f); - mul_v3_fl(y_vec, amplitude * (float)-sin(t + (float)M_PI / 6.f)); - mul_v3_fl(z_vec, amplitude / 2.f * (float)-sin(2.f * t + (float)M_PI / 3.f)); + mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.f)); + mul_v3_fl(z_vec, amplitude / 2.f * -sinf(2.f * t + (float)M_PI / 3.f)); } mul_v3_fl(state_co, amplitude); @@ -2268,8 +2271,11 @@ static void do_rough(float *loc, float mat[4][4], float t, float fac, float size float rough[3]; float rco[3]; - if (thres != 0.0f) - if ((float)fabs((float)(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) return; + if (thres != 0.0f) { + if (fabsf((float)(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) { + return; + } + } copy_v3_v3(rco, loc); mul_v3_fl(rco, t); @@ -2666,6 +2672,9 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle /* get the original coordinates (orco) for texture usage */ cpa_from = part->from; cpa_num = pa->num; + /* XXX hack to avoid messed up particle num and subsequent crash (#40733) */ + if (cpa_num > ctx->sim.psmd->dm->getNumTessFaces(ctx->sim.psmd->dm)) + cpa_num = 0; cpa_fuv = pa->fuv; psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, ornor, 0, 0, orco, 0); @@ -3887,6 +3896,8 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti } void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra) { + Object *ob = sim->ob; + Mesh *me = (Mesh *)ob->data; ParticleSettings *part = sim->psys->part; MTex **mtexp = part->mtex; MTex *mtex; @@ -3926,6 +3937,14 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex /* no break, failed to get uv's, so let's try orco's */ case TEXCO_ORCO: psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, 0, 0, 0, texvec, 0); + + if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { + BKE_mesh_texspace_calc(me); + } + sub_v3_v3(texvec, me->loc); + if (me->size[0] != 0.0f) texvec[0] /= me->size[0]; + if (me->size[1] != 0.0f) texvec[1] /= me->size[1]; + if (me->size[2] != 0.0f) texvec[2] /= me->size[2]; break; case TEXCO_PARTICLE: /* texture coordinates in range [-1, 1] */ @@ -4551,8 +4570,8 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa normalize_v3(nor); /* make sure that we get a proper side vector */ - if (fabs(dot_v3v3(nor, vec)) > 0.999999) { - if (fabs(dot_v3v3(nor, xvec)) > 0.999999) { + if (fabsf(dot_v3v3(nor, vec)) > 0.999999) { + if (fabsf(dot_v3v3(nor, xvec)) > 0.999999) { nor[0] = 0.0f; nor[1] = 1.0f; nor[2] = 0.0f; @@ -4660,12 +4679,12 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] copy_v3_v3(tvec, xvec); copy_v3_v3(tvec2, yvec); - mul_v3_fl(xvec, cos(bb->tilt * (float)M_PI)); - mul_v3_fl(tvec2, sin(bb->tilt * (float)M_PI)); + mul_v3_fl(xvec, cosf(bb->tilt * (float)M_PI)); + mul_v3_fl(tvec2, sinf(bb->tilt * (float)M_PI)); add_v3_v3(xvec, tvec2); - mul_v3_fl(yvec, cos(bb->tilt * (float)M_PI)); - mul_v3_fl(tvec, -sin(bb->tilt * (float)M_PI)); + mul_v3_fl(yvec, cosf(bb->tilt * (float)M_PI)); + mul_v3_fl(tvec, -sinf(bb->tilt * (float)M_PI)); add_v3_v3(yvec, tvec); mul_v3_fl(xvec, bb->size[0]); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index d213a88f8b1..155299b69c3 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -117,7 +117,7 @@ static int particles_are_dynamic(ParticleSystem *psys) if (psys->part->type == PART_HAIR) return psys->flag & PSYS_HAIR_DYNAMICS; else - return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID); + return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID); } float psys_get_current_display_percentage(ParticleSystem *psys) @@ -399,7 +399,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) } } - if (origindex_final != ORIGINDEX_NONE) { + if (origindex_final != ORIGINDEX_NONE && origindex_final < totelem) { if (nodearray[origindex_final]) { /* prepend */ node->next = nodearray[origindex_final]; @@ -507,7 +507,7 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) sub_v3_v3v3(delta, max, min); /* determine major axis */ - axis = (delta[0]>=delta[1]) ? 0 : ((delta[1]>=delta[2]) ? 1 : 2); + axis = axis_dominant_v3_single(delta); d = delta[axis]/(float)res; @@ -701,7 +701,7 @@ static void init_mv_jit(float *jit, int num, int seed2, float amount) rad1= (float)(1.0f/sqrtf((float)num)); rad2= (float)(1.0f/((float)num)); - rad3= (float)sqrt((float)num)/((float)num); + rad3= (float)sqrtf((float)num)/((float)num); rng = BLI_rng_new(31415926 + num + seed2); x= 0; @@ -1011,7 +1011,7 @@ static void *distribute_threads_exec_cb(void *data) return 0; } -static int distribute_compare_orig_index(void *user_data, const void *p1, const void *p2) +static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data) { int *orig_index = (int *) user_data; int index1 = orig_index[*(const int *)p1]; @@ -1079,7 +1079,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL; float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3]; - if (ELEM3(NULL, ob, psys, psys->part)) + if (ELEM(NULL, ob, psys, psys->part)) return 0; part=psys->part; @@ -1344,7 +1344,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D } if (orig_index) { - BLI_qsort_r(particle_element, totpart, sizeof(int), orig_index, distribute_compare_orig_index); + BLI_qsort_r(particle_element, totpart, sizeof(int), distribute_compare_orig_index, orig_index); } } @@ -1546,20 +1546,32 @@ static void initialize_particle_texture(ParticleSimulationData *sim, ParticleDat ParticleSettings *part = psys->part; ParticleTexture ptex; - if (part->type != PART_FLUID) { - psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f); - + psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f); + + switch (part->type) { + case PART_EMITTER: if (ptex.exist < psys_frand(psys, p+125)) pa->flag |= PARS_UNEXIST; - - pa->time = (part->type == PART_HAIR) ? 0.f : part->sta + (part->end - part->sta)*ptex.time; + pa->time = part->sta + (part->end - part->sta)*ptex.time; + break; + case PART_HAIR: + if (ptex.exist < psys_frand(psys, p+125)) + pa->flag |= PARS_UNEXIST; + pa->time = 0.f; + break; + case PART_FLUID: + break; } } /* set particle parameters that don't change during particle's life */ -void initialize_particle(ParticleData *pa) +void initialize_particle(ParticleSimulationData *sim, ParticleData *pa) { + ParticleSettings *part = sim->psys->part; + float birth_time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart; + pa->flag &= ~PARS_UNEXIST; + pa->time = part->sta + (part->end - part->sta) * birth_time; pa->hair_index = 0; /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */ @@ -1575,7 +1587,7 @@ static void initialize_all_particles(ParticleSimulationData *sim) LOOP_PARTICLES { if ((pa->flag & PARS_UNEXIST)==0) - initialize_particle(pa); + initialize_particle(sim, pa); if (pa->flag & PARS_UNEXIST) psys->totunexist++; @@ -2626,7 +2638,7 @@ static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr) mul_v3_v3fl(sphdata->flow, flow, 1.0f / pfr->tot_neighbors); } else { - sphdata->element_size = MAXFLOAT; + sphdata->element_size = FLT_MAX; copy_v3_v3(sphdata->flow, flow); } } @@ -3141,7 +3153,7 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f extrotfac = 0.0f; } - if ((part->flag & PART_ROT_DYN) && ELEM3(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) { + if ((part->flag & PART_ROT_DYN) && ELEM(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) { float angle; float len1 = len_v3(pa->prev_state.vel); float len2 = len_v3(pa->state.vel); @@ -4000,6 +4012,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) if (!psys->clmd) { psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth); psys->clmd->sim_parms->goalspring = 0.0f; + psys->clmd->sim_parms->vel_damping = 1.0f; psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; } @@ -4436,7 +4449,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) * and Monaghan). Note that, unlike double-density relaxation, * this algorithm is separated into distinct loops. */ -#pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5) +#pragma omp parallel for private (pa) schedule(dynamic,5) LOOP_DYNAMIC_PARTICLES { basic_integrate(sim, p, pa->state.time, cfra); } @@ -4834,13 +4847,13 @@ void psys_changed_type(Object *ob, ParticleSystem *psys) psys->flag &= ~PSYS_KEYED; if (part->type == PART_HAIR) { - if (ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) + if (ELEM(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) part->ren_as = PART_DRAW_PATH; if (part->distr == PART_DISTR_GRID) part->distr = PART_DISTR_JIT; - if (ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0) + if (ELEM(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0) part->draw_as = PART_DRAW_REND; CLAMP(part->path_start, 0.0f, 100.0f); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 45de1449027..ff6fae08460 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -50,6 +50,15 @@ #define STACK_FIXED_DEPTH 100 +/* Setting zero so we can catch bugs in OpenMP/PBVH. */ +#ifdef _OPENMP +# ifdef DEBUG +# define PBVH_OMP_LIMIT 0 +# else +# define PBVH_OMP_LIMIT 8 +# endif +#endif + typedef struct PBVHStack { PBVHNode *node; int revisiting; @@ -251,12 +260,12 @@ static int map_insert_vert(PBVH *bvh, GHash *map, if (value_p == NULL) { void *value; - if (BLI_BITMAP_GET(bvh->vert_bitmap, vertex)) { + if (BLI_BITMAP_TEST(bvh->vert_bitmap, vertex)) { value = SET_INT_IN_POINTER(~(*face_verts)); ++(*face_verts); } else { - BLI_BITMAP_SET(bvh->vert_bitmap, vertex); + BLI_BITMAP_ENABLE(bvh->vert_bitmap, vertex); value = SET_INT_IN_POINTER(*uniq_verts); ++(*uniq_verts); } @@ -410,7 +419,7 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc, } /* Return zero if all primitives in the node can be drawn with the - * same material (including flat/smooth shading), non-zerootherwise */ + * same material (including flat/smooth shading), non-zero otherwise */ static int leaf_needs_material_split(PBVH *bvh, int offset, int count) { int i, prim; @@ -965,7 +974,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, * can only update vertices marked with ME_VERT_PBVH_UPDATE. */ -#pragma omp parallel for private(n) schedule(static) +#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHNode *node = nodes[n]; @@ -1009,7 +1018,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, } } -#pragma omp parallel for private(n) schedule(static) +#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHNode *node = nodes[n]; @@ -1046,7 +1055,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) int n; /* update BB, redraw flag */ -#pragma omp parallel for private(n) schedule(static) +#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHNode *node = nodes[n]; @@ -1329,6 +1338,12 @@ void BKE_pbvh_node_mark_redraw(PBVHNode *node) node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw; } +void BKE_pbvh_node_mark_normals_update(PBVHNode *node) +{ + node->flag |= PBVH_UpdateNormals; +} + + void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden) { BLI_assert(node->flag & PBVH_Leaf); @@ -1418,7 +1433,7 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro typedef struct { IsectRayAABBData ray; - int original; + bool original; } RaycastData; static bool ray_aabb_intersect(PBVHNode *node, void *data_v) @@ -1434,9 +1449,10 @@ static bool ray_aabb_intersect(PBVHNode *node, void *data_v) return isect_ray_aabb(&rcd->ray, bb_min, bb_max, &node->tmin); } -void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data, - const float ray_start[3], const float ray_normal[3], - int original) +void BKE_pbvh_raycast( + PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data, + const float ray_start[3], const float ray_normal[3], + bool original) { RaycastData rcd; @@ -1629,7 +1645,7 @@ void BKE_pbvh_raycast_project_ray_root (PBVH *bvh, bool original, float ray_star } -//#include <GL/glew.h> +//#include "GPU_glew.h" typedef struct { DMSetMaterial setMaterial; diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 83e0d1a4740..01bca44d3b6 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -41,6 +41,13 @@ #include <assert.h> +// #define USE_VERIFY + +#ifdef USE_VERIFY +static void pbvh_bmesh_verify(PBVH *bvh); +#endif + + /****************************** Building ******************************/ /* Update node data after splitting */ @@ -71,7 +78,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index, const int cd_ver v = l_iter->v; if (!BLI_gset_haskey(n->bm_unique_verts, v)) { if (BM_ELEM_CD_GET_INT(v, cd_vert_node_offset) != DYNTOPO_NODE_NONE) { - BLI_gset_reinsert(n->bm_other_verts, v, NULL); + BLI_gset_add(n->bm_other_verts, v); } else { BLI_gset_insert(n->bm_unique_verts, v); @@ -274,22 +281,49 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) /**********************************************************************/ -static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, void *key, const int cd_node_offset) +static int pbvh_bmesh_node_offset_from_elem(PBVH *bvh, BMElem *ele) { - int node_index = BM_ELEM_CD_GET_INT((BMElem *)key, cd_node_offset); + switch (ele->head.htype) { + case BM_VERT: + return bvh->cd_vert_node_offset; + default: + BLI_assert(ele->head.htype == BM_FACE); + return bvh->cd_face_node_offset; + } - BLI_assert(node_index != DYNTOPO_NODE_NONE); +} + +static int pbvh_bmesh_node_lookup_index(PBVH *bvh, void *key) +{ + const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(bvh, key); + const int node_index = BM_ELEM_CD_GET_INT((BMElem *)key, cd_node_offset); + BLI_assert(node_index != DYNTOPO_NODE_NONE); BLI_assert(node_index < bvh->totnode); + (void)bvh; + + return node_index; +} - return &bvh->nodes[node_index]; +static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, void *key) +{ + return &bvh->nodes[pbvh_bmesh_node_lookup_index(bvh, key)]; } -static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index, - const float co[3], - const BMVert *example, - const int cd_vert_mask_offset, - const int cd_vert_node_offset) +/* typecheck */ +#define pbvh_bmesh_node_lookup_index(bvh, key) ( \ + CHECK_TYPE_ANY(key, BMFace *, BMVert *), \ + pbvh_bmesh_node_lookup_index(bvh, key)) +#define pbvh_bmesh_node_lookup(bvh, key) ( \ + CHECK_TYPE_ANY(key, BMFace *, BMVert *), \ + pbvh_bmesh_node_lookup(bvh, key)) + + +static BMVert *pbvh_bmesh_vert_create( + PBVH *bvh, int node_index, + const float co[3], + const BMVert *example, + const int cd_vert_mask_offset) { BMVert *v = BM_vert_create(bvh->bm, co, example, BM_CREATE_NOP); PBVHNode *node = &bvh->nodes[node_index]; @@ -297,7 +331,7 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index, BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode); BLI_gset_insert(node->bm_unique_verts, v); - BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, node_index); + BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, node_index); node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB; @@ -307,9 +341,10 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index, return v; } -static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, - BMVert *v_tri[3], BMEdge *e_tri[3], - const BMFace *f_example, const int cd_face_node_offset) +static BMFace *pbvh_bmesh_face_create( + PBVH *bvh, int node_index, + BMVert *v_tri[3], BMEdge *e_tri[3], + const BMFace *f_example) { BMFace *f; PBVHNode *node = &bvh->nodes[node_index]; @@ -321,7 +356,7 @@ static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, f->head.hflag = f_example->head.hflag; BLI_gset_insert(node->bm_faces, f); - BM_ELEM_CD_SET_INT(f, cd_face_node_offset, node_index); + BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, node_index); /* mark node for update */ node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals; @@ -334,7 +369,7 @@ static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, } /* Return the number of faces in 'node' that use vertex 'v' */ -static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v, const int cd_face_node_offset) +static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v) { BMIter bm_iter; BMFace *f; @@ -343,7 +378,7 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v, BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { PBVHNode *f_node; - f_node = pbvh_bmesh_node_lookup(bvh, f, cd_face_node_offset); + f_node = pbvh_bmesh_node_lookup(bvh, f); if (f_node == node) count++; @@ -353,20 +388,18 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v, } /* Return a node that uses vertex 'v' other than its current owner */ -static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v, - const int cd_vert_node_offset, - const int cd_face_node_offset) +static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v) { BMIter bm_iter; BMFace *f; PBVHNode *current_node; - current_node = pbvh_bmesh_node_lookup(bvh, v, cd_vert_node_offset); + current_node = pbvh_bmesh_node_lookup(bvh, v); BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { PBVHNode *f_node; - f_node = pbvh_bmesh_node_lookup(bvh, f, cd_face_node_offset); + f_node = pbvh_bmesh_node_lookup(bvh, f); if (f_node != current_node) return f_node; @@ -375,12 +408,13 @@ static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v, return NULL; } -static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, - BMVert *v, const int cd_vert_node_offset) +static void pbvh_bmesh_vert_ownership_transfer( + PBVH *bvh, PBVHNode *new_owner, + BMVert *v) { PBVHNode *current_owner; - current_owner = pbvh_bmesh_node_lookup(bvh, v, cd_vert_node_offset); + current_owner = pbvh_bmesh_node_lookup(bvh, v); /* mark node for update */ current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB; @@ -391,7 +425,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, BLI_gset_remove(current_owner->bm_unique_verts, v, NULL); /* Set new ownership */ - BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, new_owner - bvh->nodes); + BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, new_owner - bvh->nodes); BLI_gset_insert(new_owner->bm_unique_verts, v); BLI_gset_remove(new_owner->bm_other_verts, v, NULL); BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v)); @@ -400,20 +434,31 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB; } -static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v, const int cd_vert_node_offset, const int cd_face_node_offset) +static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v) { PBVHNode *v_node; BMIter bm_iter; BMFace *f; - v_node = pbvh_bmesh_node_lookup(bvh, v, cd_vert_node_offset); + /* never match for first time */ + int f_node_index_prev = DYNTOPO_NODE_NONE; + + v_node = pbvh_bmesh_node_lookup(bvh, v); BLI_gset_remove(v_node->bm_unique_verts, v, NULL); - BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE); + BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, DYNTOPO_NODE_NONE); /* Have to check each neighboring face's node */ BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { - PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f, cd_face_node_offset); + const int f_node_index = pbvh_bmesh_node_lookup_index(bvh, f); + PBVHNode *f_node; + /* faces often share the same node, + * quick check to avoid redundant #BLI_gset_remove calls */ + if (f_node_index_prev == f_node_index) + continue; + f_node_index_prev = f_node_index; + + f_node = &bvh->nodes[f_node_index]; f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB; /* Remove current ownership */ @@ -424,7 +469,7 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v, const int cd_vert_node_ } } -static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f, const int cd_vert_node_offset, const int cd_face_node_offset) +static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) { PBVHNode *f_node; BMVert *v; @@ -432,23 +477,23 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f, const int cd_vert_node_ BMLoop *l_iter; BMLoop *l_first; - f_node = pbvh_bmesh_node_lookup(bvh, f, cd_face_node_offset); + f_node = pbvh_bmesh_node_lookup(bvh, f); /* Check if any of this face's vertices need to be removed * from the node */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { v = l_iter->v; - if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v, cd_face_node_offset) == 1) { + if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) { if (BLI_gset_haskey(f_node->bm_unique_verts, v)) { /* Find a different node that uses 'v' */ PBVHNode *new_node; - new_node = pbvh_bmesh_vert_other_node_find(bvh, v, cd_vert_node_offset, cd_face_node_offset); + new_node = pbvh_bmesh_vert_other_node_find(bvh, v); BLI_assert(new_node || BM_vert_face_count(v) == 1); if (new_node) { - pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v, cd_vert_node_offset); + pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v); } } else { @@ -460,7 +505,7 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f, const int cd_vert_node_ /* Remove face from node and top level */ BLI_gset_remove(f_node->bm_faces, f, NULL); - BM_ELEM_CD_SET_INT(f, cd_face_node_offset, DYNTOPO_NODE_NONE); + BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, DYNTOPO_NODE_NONE); /* Log removed face */ BM_log_face_removed(bvh->bm_log, f); @@ -546,7 +591,8 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, * should already make the brush move the vertices only 50%, which means * that topology updates will also happen less frequent, that should be * enough. */ - if ((check_mask(eq_ctx, e->v1) || check_mask(eq_ctx, e->v2)) && + if (((eq_ctx->cd_vert_mask_offset == -1) || + (check_mask(eq_ctx, e->v1) || check_mask(eq_ctx, e->v2))) && !(BM_elem_flag_test_bool(e->v1, BM_ELEM_HIDDEN) || BM_elem_flag_test_bool(e->v2, BM_ELEM_HIDDEN))) { @@ -706,7 +752,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, mid_v3_v3v3(mid, e->v1->co, e->v2->co); node_index = BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset); - v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1, eq_ctx->cd_vert_mask_offset, eq_ctx->cd_vert_node_offset); + v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1, eq_ctx->cd_vert_mask_offset); /* update paint mask */ if (eq_ctx->cd_vert_mask_offset != -1) { @@ -740,14 +786,14 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, v2 = l_adj->next->v; if (ni != node_index && i == 0) - pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new, eq_ctx->cd_vert_node_offset); + pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new); /* Create two new faces */ v_tri[0] = v1; v_tri[1] = v_new; v_tri[2] = v_opp; bm_edges_from_tri(bvh->bm, v_tri, e_tri); - f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj, eq_ctx->cd_face_node_offset); + f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj); long_edge_queue_face_add(eq_ctx, f_new); v_tri[0] = v_new; @@ -756,11 +802,11 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, e_tri[0] = BM_edge_create(bvh->bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE); e_tri[2] = e_tri[1]; /* switched */ e_tri[1] = BM_edge_create(bvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE); - f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj, eq_ctx->cd_face_node_offset); + f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj); long_edge_queue_face_add(eq_ctx, f_new); /* Delete original */ - pbvh_bmesh_face_remove(bvh, f_adj, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset); + pbvh_bmesh_face_remove(bvh, f_adj); BM_face_kill(bvh->bm, f_adj); /* Ensure new vertex is in the node */ @@ -822,15 +868,16 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, return any_subdivided; } -static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, - BMVert *v1, BMVert *v2, - GSet *deleted_verts, - BLI_Buffer *edge_loops, - BLI_Buffer *deleted_faces, - EdgeQueueContext *eq_ctx) +static void pbvh_bmesh_collapse_edge( + PBVH *bvh, BMEdge *e, + BMVert *v1, BMVert *v2, + GSet *deleted_verts, + BLI_Buffer *deleted_faces, + EdgeQueueContext *eq_ctx) { BMIter bm_iter; BMFace *f; + BMLoop *l_adj; BMVert *v_del, *v_conn; int i; float mask_v1 = BM_ELEM_CD_GET_FLOAT(v1, eq_ctx->cd_vert_mask_offset); @@ -845,18 +892,14 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, v_conn = v1; } - /* Get all faces adjacent to the edge */ - pbvh_bmesh_edge_loops(edge_loops, e); - /* Remove the merge vertex from the PBVH */ - pbvh_bmesh_vert_remove(bvh, v_del, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset); + pbvh_bmesh_vert_remove(bvh, v_del); /* Remove all faces adjacent to the edge */ - for (i = 0; i < edge_loops->count; i++) { - BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i); + while ((l_adj = e->l)) { BMFace *f_adj = l_adj->f; - pbvh_bmesh_face_remove(bvh, f_adj, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset); + pbvh_bmesh_face_remove(bvh, f_adj); BM_face_kill(bvh->bm, f_adj); } @@ -869,7 +912,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, /* Note: this could be done with BM_vert_splice(), but that * requires handling other issues like duplicate edges, so doesn't * really buy anything. */ - deleted_faces->count = 0; + BLI_buffer_empty(deleted_faces); + BM_ITER_ELEM (f, &bm_iter, v_del, BM_FACES_OF_VERT) { BMVert *v_tri[3]; BMFace *existing_face; @@ -895,10 +939,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, } else { BMEdge *e_tri[3]; - n = pbvh_bmesh_node_lookup(bvh, f, eq_ctx->cd_face_node_offset); + n = pbvh_bmesh_node_lookup(bvh, f); ni = n - bvh->nodes; bm_edges_from_tri(bvh->bm, v_tri, e_tri); - pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f, eq_ctx->cd_face_node_offset); + pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f); /* Ensure that v_conn is in the new face's node */ if (!BLI_gset_haskey(n->bm_unique_verts, v_conn) && @@ -931,7 +975,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, for (j = 0; j < 3; j++) { if (v_tri[j] != v_del && BM_vert_face_count(v_tri[j]) == 1) { BLI_gset_insert(deleted_verts, v_tri[j]); - pbvh_bmesh_vert_remove(bvh, v_tri[j], eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset); + pbvh_bmesh_vert_remove(bvh, v_tri[j]); } else { v_tri[j] = NULL; @@ -939,7 +983,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, } /* Remove the face */ - pbvh_bmesh_face_remove(bvh, f_del, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset); + pbvh_bmesh_face_remove(bvh, f_del); BM_face_kill(bvh->bm, f_del); /* Check if any of the face's edges are now unused by any @@ -972,10 +1016,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BM_vert_kill(bvh->bm, v_del); } -static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, - PBVH *bvh, - BLI_Buffer *edge_loops, - BLI_Buffer *deleted_faces) +static bool pbvh_bmesh_collapse_short_edges( + EdgeQueueContext *eq_ctx, + PBVH *bvh, + BLI_Buffer *deleted_faces) { float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; GSet *deleted_verts; @@ -1019,7 +1063,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, any_collapsed = true; pbvh_bmesh_collapse_edge(bvh, e, v1, v2, - deleted_verts, edge_loops, + deleted_verts, deleted_faces, eq_ctx); } @@ -1213,7 +1257,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, const float center[3], float radius) { /* 2 is enough for edge faces - manifold edge */ - BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 2); + BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2); BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32); const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK); const int cd_vert_node_offset = bvh->cd_vert_node_offset; @@ -1229,7 +1273,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, short_edge_queue_create(&eq_ctx, bvh, center, radius); modified |= !BLI_heap_is_empty(q.heap); - pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &edge_loops, + pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &deleted_faces); BLI_heap_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); @@ -1260,6 +1304,10 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, BLI_buffer_free(&edge_loops); BLI_buffer_free(&deleted_faces); +#ifdef USE_VERIFY + pbvh_bmesh_verify(bvh); +#endif + return modified; } @@ -1381,104 +1429,28 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node) #if 0 -void bli_gset_duplicate_key_check(GSet *gs) -{ - GSetIterator gs_iter1, gs_iter2; - - GSET_ITER (gs_iter1, gs) { - void *key1 = BLI_gsetIterator_getKey(&gs_iter1); - int dup = -1; - - GSET_ITER (gs_iter2, gs) { - void *key2 = BLI_gsetIterator_getKey(&gs_iter2); - - if (key1 == key2) { - dup++; - if (dup > 0) { - BLI_assert(!"duplicate in hash"); - } - } - } - } -} - -void bmesh_print(BMesh *bm) -{ - BMIter iter, siter; - BMVert *v; - BMEdge *e; - BMFace *f; - BMLoop *l; - - fprintf(stderr, "\nbm=%p, totvert=%d, totedge=%d, " - "totloop=%d, totface=%d\n", - bm, bm->totvert, bm->totedge, - bm->totloop, bm->totface); - - fprintf(stderr, "vertices:\n"); - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - fprintf(stderr, " %d co=(%.3f %.3f %.3f) oflag=%x\n", - BM_elem_index_get(v), v->co[0], v->co[1], v->co[2], - v->oflags[bm->stackdepth - 1].f); - } - - fprintf(stderr, "edges:\n"); - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - fprintf(stderr, " %d v1=%d, v2=%d, oflag=%x\n", - BM_elem_index_get(e), - BM_elem_index_get(e->v1), - BM_elem_index_get(e->v2), - e->oflags[bm->stackdepth - 1].f); - } - - fprintf(stderr, "faces:\n"); - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - fprintf(stderr, " %d len=%d, oflag=%x\n", - BM_elem_index_get(f), f->len, - f->oflags[bm->stackdepth - 1].f); - - fprintf(stderr, " v: "); - BM_ITER_ELEM(v, &siter, f, BM_VERTS_OF_FACE) { - fprintf(stderr, "%d ", BM_elem_index_get(v)); - } - fprintf(stderr, "\n"); - - fprintf(stderr, " e: "); - BM_ITER_ELEM(e, &siter, f, BM_EDGES_OF_FACE) { - fprintf(stderr, "%d ", BM_elem_index_get(e)); - } - fprintf(stderr, "\n"); - - fprintf(stderr, " l: "); - BM_ITER_ELEM(l, &siter, f, BM_LOOPS_OF_FACE) { - fprintf(stderr, "%d(v=%d, e=%d) ", - BM_elem_index_get(l), - BM_elem_index_get(l->v), - BM_elem_index_get(l->e)); - } - fprintf(stderr, "\n"); - } -} - -void pbvh_bmesh_print(PBVH *bvh) +static void pbvh_bmesh_print(PBVH *bvh) { - GHashIterator gh_iter; GSetIterator gs_iter; int n; + BMIter iter; + BMFace *f; + BMVert *v; fprintf(stderr, "\npbvh=%p\n", bvh); fprintf(stderr, "bm_face_to_node:\n"); - GHASH_ITER (gh_iter, bvh->bm_face_to_node) { + + BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) { fprintf(stderr, " %d -> %d\n", - BM_elem_index_get((BMFace *)BLI_ghashIterator_getKey(&gh_iter)), - GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter))); + BM_elem_index_get(v), + pbvh_bmesh_node_lookup_index(bvh, f)); } fprintf(stderr, "bm_vert_to_node:\n"); - GHASH_ITER (gh_iter, bvh->bm_vert_to_node) { + BM_ITER_MESH(v, &iter, bvh->bm, BM_FACES_OF_MESH) { fprintf(stderr, " %d -> %d\n", - BM_elem_index_get((BMVert *)BLI_ghashIterator_getKey(&gh_iter)), - GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter))); + BM_elem_index_get(v), + pbvh_bmesh_node_lookup_index(bvh, v)); } for (n = 0; n < bvh->totnode; n++) { @@ -1487,9 +1459,9 @@ void pbvh_bmesh_print(PBVH *bvh) continue; fprintf(stderr, "node %d\n faces:\n", n); - GHASH_ITER (gh_iter, node->bm_faces) + GSET_ITER (gs_iter, node->bm_faces) fprintf(stderr, " %d\n", - BM_elem_index_get((BMFace *)BLI_ghashIterator_getKey(&gh_iter))); + BM_elem_index_get((BMFace *)BLI_gsetIterator_getKey(&gs_iter))); fprintf(stderr, " unique verts:\n"); GSET_ITER (gs_iter, node->bm_unique_verts) fprintf(stderr, " %d\n", @@ -1501,7 +1473,7 @@ void pbvh_bmesh_print(PBVH *bvh) } } -void print_flag_factors(int flag) +static void print_flag_factors(int flag) { int i; printf("flag=0x%x:\n", flag); @@ -1511,24 +1483,53 @@ void print_flag_factors(int flag) } } } +#endif + -void pbvh_bmesh_verify(PBVH *bvh) +#ifdef USE_VERIFY + +static void pbvh_bmesh_verify(PBVH *bvh) { - GHashIterator gh_iter; GSetIterator gs_iter; - int i, vert_count = 0; + int i; BMIter iter; - BMVert *vi; + BMFace *f; + BMVert *v; + + GSet *faces_all; + GSet *verts_all; + - /* Check faces */ - BLI_assert(bvh->bm->totface == BLI_ghash_size(bvh->bm_face_to_node)); - GHASH_ITER (gh_iter, bvh->bm_face_to_node) { + /* build list of faces & verts to lookup */ + faces_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totface); + verts_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totvert); + + BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) { + BLI_gset_insert(faces_all, f); + } + BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) { + if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) { + BLI_gset_insert(verts_all, v); + } + } + + /* Check vert/face counts */ + { + int totface = 0, totvert = 0; + for (i = 0; i < bvh->totnode; i++) { + PBVHNode *n = &bvh->nodes[i]; + totface += n->bm_faces ? BLI_gset_size(n->bm_faces) : 0; + totvert += n->bm_unique_verts ? BLI_gset_size(n->bm_unique_verts) : 0; + } + + BLI_assert(totface == BLI_gset_size(faces_all)); + BLI_assert(totvert == BLI_gset_size(verts_all)); + } + + BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) { BMIter bm_iter; BMVert *v; - BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - void *nip = BLI_ghashIterator_getValue(&gh_iter); - int ni = GET_INT_FROM_POINTER(nip); - PBVHNode *n = &bvh->nodes[ni]; + PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f); /* Check that the face's node is a leaf */ BLI_assert(n->flag & PBVH_Leaf); @@ -1545,7 +1546,7 @@ void pbvh_bmesh_verify(PBVH *bvh) BLI_gset_haskey(n->bm_other_verts, v)); /* Check that the vertex has a node owner */ - nv = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v); + nv = pbvh_bmesh_node_lookup(bvh, v); /* Check that the vertex's node knows it owns the vert */ BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v)); @@ -1556,16 +1557,18 @@ void pbvh_bmesh_verify(PBVH *bvh) } /* Check verts */ - BLI_assert(bvh->bm->totvert == BLI_ghash_size(bvh->bm_vert_to_node)); - GHASH_ITER (gh_iter, bvh->bm_vert_to_node) { + BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) { BMIter bm_iter; - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); - BMFace *f; - void *nip = BLI_ghashIterator_getValue(&gh_iter); - int ni = GET_INT_FROM_POINTER(nip); - PBVHNode *n = &bvh->nodes[ni]; + PBVHNode *n; bool found; + /* vertex isn't tracked */ + if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) { + continue; + } + + n = pbvh_bmesh_node_lookup(bvh, v); + /* Check that the vert's node is a leaf */ BLI_assert(n->flag & PBVH_Leaf); @@ -1578,7 +1581,7 @@ void pbvh_bmesh_verify(PBVH *bvh) /* Check that the vert's node also contains one of the vert's * adjacent faces */ BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { - if (BLI_ghash_lookup(bvh->bm_face_to_node, f) == nip) { + if (pbvh_bmesh_node_lookup(bvh, f) == n) { found = true; break; } @@ -1589,9 +1592,10 @@ void pbvh_bmesh_verify(PBVH *bvh) /* total freak stuff, check if node exists somewhere else */ /* Slow */ for (i = 0; i < bvh->totnode; i++) { - PBVHNode *n = &bvh->nodes[i]; - if (i != ni && n->bm_unique_verts) - BLI_assert(!BLI_gset_haskey(n->bm_unique_verts, v)); + PBVHNode *n_other = &bvh->nodes[i]; + if ((n != n_other) && (n_other->bm_unique_verts)) { + BLI_assert(!BLI_gset_haskey(n_other->bm_unique_verts, v)); + } } #endif @@ -1619,36 +1623,32 @@ void pbvh_bmesh_verify(PBVH *bvh) for (i = 0; i < bvh->totnode; i++) { PBVHNode *n = &bvh->nodes[i]; if (n->flag & PBVH_Leaf) { - /* Check for duplicate entries */ - /* Slow */ -#if 0 - bli_gset_duplicate_key_check(n->bm_faces); - bli_gset_duplicate_key_check(n->bm_unique_verts); - bli_gset_duplicate_key_check(n->bm_other_verts); -#endif - GHASH_ITER (gh_iter, n->bm_faces) { - BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - void *nip = BLI_ghash_lookup(bvh->bm_face_to_node, f); - BLI_assert(BLI_ghash_haskey(bvh->bm_face_to_node, f)); - BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes)); + GSET_ITER (gs_iter, n->bm_faces) { + BMFace *f = BLI_gsetIterator_getKey(&gs_iter); + PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, f); + BLI_assert(n == n_other); + BLI_assert(BLI_gset_haskey(faces_all, f)); } GSET_ITER (gs_iter, n->bm_unique_verts) { BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - void *nip = BLI_ghash_lookup(bvh->bm_vert_to_node, v); - BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v)); + PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, v); BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v)); - BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes)); + BLI_assert(n == n_other); + BLI_assert(BLI_gset_haskey(verts_all, v)); } GSET_ITER (gs_iter, n->bm_other_verts) { BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v)); BLI_assert(BM_vert_face_count(v) > 0); + BLI_assert(BLI_gset_haskey(verts_all, v)); } } } + + BLI_gset_free(faces_all, NULL); + BLI_gset_free(verts_all, NULL); } #endif diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 17c75341891..b77407cdcb2 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -51,7 +51,6 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_system.h" -#include BLI_SYSTEM_PID_H #include "BLF_translation.h" @@ -86,17 +85,17 @@ #ifdef WITH_LZO #include "minilzo.h" -#else -/* used for non-lzo cases */ -#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3) +#define LZO_HEAP_ALLOC(var,size) \ + lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] #endif +#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3) + #ifdef WITH_LZMA #include "LzmaLib.h" #endif /* needed for directory lookup */ -/* untitled blend's need getpid for a unique name */ #ifndef WIN32 # include <dirent.h> #else @@ -1491,7 +1490,7 @@ static int ptcache_path(PTCacheID *pid, char *filename) /* use the temp path. this is weak but better then not using point cache at all */ /* temporary directory is assumed to exist and ALWAYS has a trailing slash */ - BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", BLI_temporary_dir(), abs(getpid())); + BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BLI_temp_dir_session()); return BLI_add_slash(filename); /* new strlen() */ } diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 90b5d8cf1a1..b2178fe69b3 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -284,7 +284,7 @@ Report *BKE_reports_last_displayable(ReportList *reports) Report *report; for (report = reports->list.last; report; report = report->prev) { - if (ELEM3(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO)) + if (ELEM(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO)) return report; } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 8e5b67404ac..3d61b0bdefb 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -57,6 +57,7 @@ #include "BKE_effect.h" #include "BKE_global.h" #include "BKE_library.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_pointcache.h" #include "BKE_rigidbody.h" @@ -287,10 +288,10 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) DM_ensure_tessface(dm); - mvert = (dm) ? dm->getVertArray(dm) : NULL; - totvert = (dm) ? dm->getNumVerts(dm) : 0; - mface = (dm) ? dm->getTessFaceArray(dm) : NULL; - totface = (dm) ? dm->getNumTessFaces(dm) : 0; + mvert = dm->getVertArray(dm); + totvert = dm->getNumVerts(dm); + mface = dm->getTessFaceArray(dm); + totface = dm->getNumTessFaces(dm); /* sanity checking - potential case when no data will be present */ if ((totvert == 0) || (totface == 0)) { @@ -344,7 +345,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) } /* cleanup temp data */ - if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { + if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { dm->release(dm); } } @@ -394,7 +395,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) } mul_v3_fl(size, 0.5f); - if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { + if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { /* take radius as largest x/y dimension, and height as z-dimension */ radius = MAX2(size[0], size[1]); height = size[2]; @@ -455,8 +456,186 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) /* --------------------- */ -/* Create physics sim representation of object given RigidBody settings - * < rebuild: even if an instance already exists, replace it +/* helper function to calculate volume of rigidbody object */ +// TODO: allow a parameter to specify method used to calculate this? +void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + + float size[3] = {1.0f, 1.0f, 1.0f}; + float radius = 1.0f; + float height = 1.0f; + + float volume = 0.0f; + + /* if automatically determining dimensions, use the Object's boundbox + * - assume that all quadrics are standing upright on local z-axis + * - assume even distribution of mass around the Object's pivot + * (i.e. Object pivot is centralized in boundbox) + * - boundbox gives full width + */ + // XXX: all dimensions are auto-determined now... later can add stored settings for this + BKE_object_dimensions_get(ob, size); + + if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { + /* take radius as largest x/y dimension, and height as z-dimension */ + radius = MAX2(size[0], size[1]) * 0.5f; + height = size[2]; + } + else if (rbo->shape == RB_SHAPE_SPHERE) { + /* take radius to the the largest dimension to try and encompass everything */ + radius = max_fff(size[0], size[1], size[2]) * 0.5f; + } + + /* calculate volume as appropriate */ + switch (rbo->shape) { + case RB_SHAPE_BOX: + volume = size[0] * size[1] * size[2]; + break; + + case RB_SHAPE_SPHERE: + volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius; + break; + + /* for now, assume that capsule is close enough to a cylinder... */ + case RB_SHAPE_CAPSULE: + case RB_SHAPE_CYLINDER: + volume = (float)M_PI * radius * radius * height; + break; + + case RB_SHAPE_CONE: + volume = (float)M_PI / 3.0f * radius * radius * height; + break; + + case RB_SHAPE_CONVEXH: + case RB_SHAPE_TRIMESH: + { + if (ob->type == OB_MESH) { + DerivedMesh *dm = rigidbody_get_mesh(ob); + MVert *mvert; + MFace *mface; + int totvert, totface; + + /* ensure mesh validity, then grab data */ + if (dm == NULL) + return; + + DM_ensure_tessface(dm); + + mvert = dm->getVertArray(dm); + totvert = dm->getNumVerts(dm); + mface = dm->getTessFaceArray(dm); + totface = dm->getNumTessFaces(dm); + + if (totvert > 0 && totface > 0) { + BKE_mesh_calc_volume(mvert, totvert, mface, totface, &volume, NULL); + } + + /* cleanup temp data */ + if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { + dm->release(dm); + } + } + else { + /* rough estimate from boundbox as fallback */ + /* XXX could implement other types of geometry here (curves, etc.) */ + volume = size[0] * size[1] * size[2]; + } + break; + } + +#if 0 // XXX: not defined yet + case RB_SHAPE_COMPOUND: + volume = 0.0f; + break; +#endif + } + + /* return the volume calculated */ + if (r_vol) *r_vol = volume; +} + +void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3]) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + + float size[3] = {1.0f, 1.0f, 1.0f}; + float height = 1.0f; + + zero_v3(r_com); + + /* if automatically determining dimensions, use the Object's boundbox + * - assume that all quadrics are standing upright on local z-axis + * - assume even distribution of mass around the Object's pivot + * (i.e. Object pivot is centralized in boundbox) + * - boundbox gives full width + */ + // XXX: all dimensions are auto-determined now... later can add stored settings for this + BKE_object_dimensions_get(ob, size); + + /* calculate volume as appropriate */ + switch (rbo->shape) { + case RB_SHAPE_BOX: + case RB_SHAPE_SPHERE: + case RB_SHAPE_CAPSULE: + case RB_SHAPE_CYLINDER: + break; + + case RB_SHAPE_CONE: + /* take radius as largest x/y dimension, and height as z-dimension */ + height = size[2]; + /* cone is geometrically centered on the median, + * center of mass is 1/4 up from the base + */ + r_com[2] = -0.25f * height; + break; + + case RB_SHAPE_CONVEXH: + case RB_SHAPE_TRIMESH: + { + if (ob->type == OB_MESH) { + DerivedMesh *dm = rigidbody_get_mesh(ob); + MVert *mvert; + MFace *mface; + int totvert, totface; + + /* ensure mesh validity, then grab data */ + if (dm == NULL) + return; + + DM_ensure_tessface(dm); + + mvert = dm->getVertArray(dm); + totvert = dm->getNumVerts(dm); + mface = dm->getTessFaceArray(dm); + totface = dm->getNumTessFaces(dm); + + if (totvert > 0 && totface > 0) { + BKE_mesh_calc_volume(mvert, totvert, mface, totface, NULL, r_com); + } + + /* cleanup temp data */ + if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { + dm->release(dm); + } + } + break; + } + +#if 0 // XXX: not defined yet + case RB_SHAPE_COMPOUND: + volume = 0.0f; + break; +#endif + } +} + +/* --------------------- */ + +/** + * Create physics sim representation of object given RigidBody settings + * + * \param rebuild Even if an instance already exists, replace it */ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool rebuild) { @@ -518,8 +697,10 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool /* --------------------- */ -/* Create physics sim representation of constraint given rigid body constraint settings - * < rebuild: even if an instance already exists, replace it +/** + * Create physics sim representation of constraint given rigid body constraint settings + * + * \param rebuild Even if an instance already exists, replace it */ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, bool rebuild) { @@ -539,7 +720,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b return; } - if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) { + if (ELEM(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) { if (rbc->physics_constraint) { RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); RB_constraint_delete(rbc->physics_constraint); @@ -895,7 +1076,8 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty /* Utilities API */ /* Get RigidBody world for the given scene, creating one if needed - * < scene: Scene to find active Rigid Body world for + * + * \param scene Scene to find active Rigid Body world for */ RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { @@ -1093,8 +1275,10 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o */ } -/* Updates and validates world, bodies and shapes. - * < rebuild: rebuild entire simulation +/** + * Updates and validates world, bodies and shapes. + * + * \param rebuild Rebuild entire simulation */ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool rebuild) { @@ -1105,6 +1289,26 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool BKE_rigidbody_validate_sim_world(scene, rbw, true); rigidbody_update_sim_world(scene, rbw); + /* XXX TODO For rebuild: remove all constraints first. + * Otherwise we can end up deleting objects that are still + * referenced by constraints, corrupting bullet's internal list. + * + * Memory management needs redesign here, this is just a dirty workaround. + */ + if (rebuild && rbw->constraints) { + for (go = rbw->constraints->gobject.first; go; go = go->next) { + Object *ob = go->ob; + if (ob) { + RigidBodyCon *rbc = ob->rigidbody_constraint; + if (rbc && rbc->physics_constraint) { + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; + } + } + } + } + /* update objects */ for (go = rbw->group->gobject.first; go; go = go->next) { Object *ob = go->ob; @@ -1150,6 +1354,7 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool rigidbody_update_sim_ob(scene, rbw, ob, rbo); } } + /* update constraints */ if (rbw->constraints == NULL) /* no constraints, move on */ return; @@ -1386,6 +1591,8 @@ struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; } struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; } void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc) {} void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {} +void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) { if (r_vol) *r_vol = 0.0f; } +void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3]) { zero_v3(r_com); } struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; } struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; } void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {} diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index b0b64cac802..4be75344133 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -391,6 +391,8 @@ void init_actuator(bActuator *act) bSoundActuator *sa; bSteeringActuator *sta; bArmatureActuator *arma; + bMouseActuator *ma; + bEditObjectActuator *eoa; if (act->data) MEM_freeN(act->data); act->data= NULL; @@ -429,6 +431,9 @@ void init_actuator(bActuator *act) break; case ACT_EDIT_OBJECT: act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact"); + eoa = act->data; + eoa->upflag= ACT_TRACK_UP_Z; + eoa->trackflag= ACT_TRACK_TRAXIS_Y; break; case ACT_CONSTRAINT: act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act"); @@ -477,6 +482,15 @@ void init_actuator(bActuator *act) sta->flag = ACT_STEERING_AUTOMATICFACING; sta->facingaxis = 1; break; + case ACT_MOUSE: + ma = act->data = MEM_callocN(sizeof( bMouseActuator ), "mouse act"); + ma->flag = ACT_MOUSE_VISIBLE|ACT_MOUSE_USE_AXIS_X|ACT_MOUSE_USE_AXIS_Y|ACT_MOUSE_RESET_X|ACT_MOUSE_RESET_Y|ACT_MOUSE_LOCAL_Y; + ma->sensitivity[0] = ma->sensitivity[1] = 2.f; + ma->object_axis[0] = ACT_MOUSE_OBJECT_AXIS_Z; + ma->object_axis[1] = ACT_MOUSE_OBJECT_AXIS_X; + ma->limit_y[0] = DEG2RADF(-90.0f); + ma->limit_y[1] = DEG2RADF(90.0f); + break; default: ; /* this is very severe... I cannot make any memory for this */ /* logic brick... */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 0e95cf1d418..5bfd6e8a120 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -39,6 +39,7 @@ #include "DNA_anim_types.h" #include "DNA_group_types.h" #include "DNA_linestyle_types.h" +#include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" @@ -46,6 +47,8 @@ #include "DNA_screen_types.h" #include "DNA_sequence_types.h" #include "DNA_space_types.h" +#include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" #include "BLI_math.h" #include "BLI_blenlib.h" @@ -62,6 +65,7 @@ #include "BKE_action.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" +#include "BKE_editmesh.h" #include "BKE_fcurve.h" #include "BKE_freestyle.h" #include "BKE_global.h" @@ -78,6 +82,7 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_sound.h" +#include "BKE_unit.h" #include "BKE_world.h" #include "RE_engine.h" @@ -86,8 +91,7 @@ #include "IMB_colormanagement.h" -//XXX #include "BIF_previewrender.h" -//XXX #include "BIF_editseq.h" +#include "bmesh.h" #ifdef WIN32 #else @@ -253,6 +257,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint); ts->imapaint.paintcursor = NULL; + id_us_plus((ID *)ts->imapaint.stencil); ts->particle.paintcursor = NULL; } @@ -510,7 +515,12 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->r.border.ymin = 0.0f; sce->r.border.xmax = 1.0f; sce->r.border.ymax = 1.0f; + + sce->r.preview_start_resolution = 64; + sce->r.line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE; + sce->r.unit_line_thickness = 1.0f; + sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct"); sce->toolsettings->doublimit = 0.001; sce->toolsettings->uvcalc_margin = 0.001f; @@ -553,6 +563,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->toolsettings->proportional_size = 1.0f; sce->toolsettings->imapaint.paint.flags |= PAINT_SHOW_BRUSH; + sce->toolsettings->imapaint.normal_angle = 80; + sce->toolsettings->imapaint.seam_bleed = 2; sce->physics_settings.gravity[0] = 0.0f; sce->physics_settings.gravity[1] = 0.0f; @@ -719,14 +731,14 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) /* called from creator.c */ Scene *BKE_scene_set_name(Main *bmain, const char *name) { - Scene *sce = (Scene *)BKE_libblock_find_name(ID_SCE, name); + Scene *sce = (Scene *)BKE_libblock_find_name_ex(bmain, ID_SCE, name); if (sce) { BKE_scene_set_background(bmain, sce); - printf("Scene switch: '%s' in file: '%s'\n", name, G.main->name); + printf("Scene switch: '%s' in file: '%s'\n", name, bmain->name); return sce; } - printf("Can't find scene: '%s' in file: '%s'\n", name, G.main->name); + printf("Can't find scene: '%s' in file: '%s'\n", name, bmain->name); return NULL; } @@ -804,9 +816,7 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) BKE_libblock_free(bmain, sce); } -/* used by metaballs - * doesn't return the original duplicated object, only dupli's - */ +/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob) { @@ -817,11 +827,12 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, iter->phase = F_START; iter->dupob = NULL; iter->duplilist = NULL; + iter->dupli_refob = NULL; } else { /* run_again is set when a duplilist has been ended */ while (run_again) { - run_again = 0; + run_again = false; /* the first base */ if (iter->phase == F_START) { @@ -879,34 +890,46 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, iter->dupob = iter->duplilist->first; - if (!iter->dupob) + if (!iter->dupob) { free_object_duplilist(iter->duplilist); + iter->duplilist = NULL; + } + iter->dupli_refob = NULL; } } } /* handle dupli's */ if (iter->dupob) { - - copy_m4_m4(iter->omat, iter->dupob->ob->obmat); - copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->mat); - (*base)->flag |= OB_FROMDUPLI; *ob = iter->dupob->ob; iter->phase = F_DUPLI; - + + if (iter->dupli_refob != *ob) { + if (iter->dupli_refob) { + /* Restore previous object's real matrix. */ + copy_m4_m4(iter->dupli_refob->obmat, iter->omat); + } + /* Backup new object's real matrix. */ + iter->dupli_refob = *ob; + copy_m4_m4(iter->omat, iter->dupli_refob->obmat); + } + copy_m4_m4((*ob)->obmat, iter->dupob->mat); + iter->dupob = iter->dupob->next; } else if (iter->phase == F_DUPLI) { iter->phase = F_SCENE; (*base)->flag &= ~OB_FROMDUPLI; - for (iter->dupob = iter->duplilist->first; iter->dupob; iter->dupob = iter->dupob->next) { - copy_m4_m4(iter->dupob->ob->obmat, iter->omat); + if (iter->dupli_refob) { + /* Restore last object's real matrix. */ + copy_m4_m4(iter->dupli_refob->obmat, iter->omat); + iter->dupli_refob = NULL; } free_object_duplilist(iter->duplilist); iter->duplilist = NULL; - run_again = 1; + run_again = true; } } } @@ -1118,11 +1141,6 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra) double intpart; scene->r.subframe = modf(cfra, &intpart); scene->r.cfra = (int)intpart; - - if (cfra < 0.0) { - scene->r.cfra -= 1; - scene->r.subframe = 1.0f + scene->r.subframe; - } } /* drivers support/hacks @@ -1462,7 +1480,7 @@ static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene bool need_singlethread_pass; /* Early check for whether we need to invoke all the task-based - * tihngs (spawn new ppol, traverse dependency graph and so on). + * things (spawn new ppol, traverse dependency graph and so on). * * Basically if there's no ID datablocks tagged for update which * corresponds to object->recalc flags (which are checked in @@ -1541,6 +1559,53 @@ static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bma } +static bool check_rendered_viewport_visible(Main *bmain) +{ + wmWindowManager *wm = bmain->wm.first; + wmWindow *window; + for (window = wm->windows.first; window != NULL; window = window->next) { + bScreen *screen = window->screen; + ScrArea *area; + for (area = screen->areabase.first; area != NULL; area = area->next) { + View3D *v3d = area->spacedata.first; + if (area->spacetype != SPACE_VIEW3D) { + continue; + } + if (v3d->drawtype == OB_RENDER) { + return true; + } + } + } + return false; +} + +static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) +{ + /* This is needed to prepare mesh to be used by the render + * engine from the viewport rendering. We do loading here + * so all the objects which shares the same mesh datablock + * are nicely tagged for update and updated. + * + * This makes it so viewport render engine doesn't need to + * call loading of the edit data for the mesh objects. + */ + + Object *obedit = scene->obedit; + if (obedit) { + Mesh *mesh = obedit->data; + /* TODO(sergey): Check object recalc flags as well? */ + if ((obedit->type == OB_MESH) && + (mesh->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA))) + { + if (check_rendered_viewport_visible(bmain)) { + BMesh *bm = mesh->edit_btmesh->bm; + BM_mesh_bm_to_me(bm, mesh, false); + DAG_id_tag_update(&mesh->id, 0); + } + } + } +} + void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene) { Scene *sce_iter; @@ -1552,6 +1617,9 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) DAG_scene_relations_update(bmain, sce_iter); + /* flush editing data if needed */ + prepare_mesh_for_viewport_render(bmain, scene); + /* flush recalc flags to dependencies */ DAG_ids_flush_tagged(bmain); @@ -1599,7 +1667,20 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc BKE_animsys_evaluate_animdata(scene, &material->id, adt, ctime, 0); } } - + + /* Also do the same for node trees. */ + if (DAG_id_type_tagged(bmain, ID_NT)) { + float ctime = BKE_scene_frame_get(scene); + + FOREACH_NODETREE(bmain, ntree, id) + { + AnimData *adt = BKE_animdata_from_id(&ntree->id); + if (adt && (adt->recalc & ADT_RECALC_ANIM)) + BKE_animsys_evaluate_animdata(scene, &ntree->id, adt, ctime, 0); + } + FOREACH_NODETREE_END + } + /* notify editors and python about recalc */ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST); DAG_ids_check_recalc(bmain, scene, false); @@ -1819,6 +1900,12 @@ bool BKE_scene_use_new_shading_nodes(Scene *scene) return (type && type->flag & RE_USE_SHADING_NODES); } +bool BKE_scene_uses_blender_internal(struct Scene *scene) +{ + return strcmp("BLENDER_RENDER", scene->r.engine) == 0; +} + + void BKE_scene_base_flag_to_objects(struct Scene *scene) { Base *base = scene->base.first; @@ -1890,3 +1977,28 @@ int BKE_scene_num_threads(const Scene *scene) { return BKE_render_num_threads(&scene->r); } + +/* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently) + * and unit->scale_length. + */ +double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, double value) +{ + if (unit->system == USER_UNIT_NONE) { + /* Never apply scale_length when not using a unit setting! */ + return value; + } + + switch (unit_type) { + case B_UNIT_LENGTH: + return value * (double)unit->scale_length; + case B_UNIT_AREA: + return value * pow(unit->scale_length, 2); + case B_UNIT_VOLUME: + return value * pow(unit->scale_length, 3); + case B_UNIT_MASS: + return value * pow(unit->scale_length, 3); + case B_UNIT_CAMERA: /* *Do not* use scene's unit scale for camera focal lens! See T42026. */ + default: + return value; + } +} diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 9d40ee6e667..b2296151cf7 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -425,6 +425,32 @@ ScrArea *BKE_screen_find_big_area(bScreen *sc, const int spacetype, const short return big; } +/** + * Utility function to get the active layer to use when adding new objects. + */ +unsigned int BKE_screen_view3d_layer_active_ex(const View3D *v3d, const Scene *scene, bool use_localvd) +{ + unsigned int lay; + if ((v3d == NULL) || (v3d->scenelock && !v3d->localvd)) { + lay = scene->layact; + } + else { + lay = v3d->layact; + } + + if (use_localvd) { + if (v3d && v3d->localvd) { + lay |= v3d->lay; + } + } + + return lay; +} +unsigned int BKE_screen_view3d_layer_active(const struct View3D *v3d, const struct Scene *scene) +{ + return BKE_screen_view3d_layer_active_ex(v3d, scene, true); +} + void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene) { int bit; diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index 97062f728c5..4268b33cb14 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -69,58 +69,15 @@ static struct SeqPreprocessCache *preprocess_cache = NULL; static void preprocessed_cache_destruct(void); -static int seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b) +static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b) { - if (a->preview_render_size < b->preview_render_size) { - return -1; - } - if (a->preview_render_size > b->preview_render_size) { - return 1; - } - - if (a->rectx < b->rectx) { - return -1; - } - if (a->rectx > b->rectx) { - return 1; - } - - if (a->recty < b->recty) { - return -1; - } - if (a->recty > b->recty) { - return 1; - } - - if (a->bmain < b->bmain) { - return -1; - } - if (a->bmain > b->bmain) { - return 1; - } - - if (a->scene < b->scene) { - return -1; - } - if (a->scene > b->scene) { - return 1; - } - - if (a->motion_blur_shutter < b->motion_blur_shutter) { - return -1; - } - if (a->motion_blur_shutter > b->motion_blur_shutter) { - return 1; - } - - if (a->motion_blur_samples < b->motion_blur_samples) { - return -1; - } - if (a->motion_blur_samples > b->motion_blur_samples) { - return 1; - } - - return 0; + return ((a->preview_render_size != b->preview_render_size) || + (a->rectx != b->rectx) || + (a->recty != b->recty) || + (a->bmain != b->bmain) || + (a->scene != b->scene) || + (a->motion_blur_shutter != b->motion_blur_shutter) || + (a->motion_blur_samples != b->motion_blur_samples)); } static unsigned int seq_hash_render_data(const SeqRenderData *a) @@ -148,33 +105,15 @@ static unsigned int seqcache_hashhash(const void *key_) return rval; } -static int seqcache_hashcmp(const void *a_, const void *b_) +static bool seqcache_hashcmp(const void *a_, const void *b_) { const SeqCacheKey *a = (SeqCacheKey *) a_; const SeqCacheKey *b = (SeqCacheKey *) b_; - if (a->seq < b->seq) { - return -1; - } - if (a->seq > b->seq) { - return 1; - } - - if (a->cfra < b->cfra) { - return -1; - } - if (a->cfra > b->cfra) { - return 1; - } - - if (a->type < b->type) { - return -1; - } - if (a->type > b->type) { - return 1; - } - - return seq_cmp_render_data(&a->context, &b->context); + return ((a->seq != b->seq) || + (a->cfra != b->cfra) || + (a->type != b->type) || + seq_cmp_render_data(&a->context, &b->context)); } void BKE_sequencer_cache_destruct(void) diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 7ed9af8b87f..11a6cb7acc3 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -52,6 +52,11 @@ #include "RNA_access.h" +/* TODO(sergey): Could be considered a bad level call, but + * need this for gaussian table. + */ +#include "RE_pipeline.h" + static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1, unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out) @@ -305,41 +310,45 @@ static void do_alphaover_effect(const SeqRenderData *context, Sequence *UNUSED(s static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out) { - int fac2, mfac, fac, fac4; + float fac2, fac, fac4; int xo; - unsigned char *rt1, *rt2, *rt; + unsigned char *cp1, *cp2, *rt; + float tempc[4], rt1[4], rt2[4]; xo = x; - rt1 = rect1; - rt2 = rect2; + cp1 = rect1; + cp2 = rect2; rt = out; - fac2 = (int)(256.0f * facf0); - fac4 = (int)(256.0f * facf1); + fac2 = facf0; + fac4 = facf1; while (y--) { x = xo; while (x--) { /* rt = rt1 under rt2 (alpha from rt2) */ + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); /* this complex optimization is because the * 'skybuf' can be crossed in */ - if (rt2[3] == 0 && fac2 == 256) *((unsigned int *) rt) = *((unsigned int *) rt1); - else if (rt2[3] == 255) *((unsigned int *) rt) = *((unsigned int *) rt2); + if (rt2[3] <= 0.0f && fac2 >= 1.0f) *((unsigned int *) rt) = *((unsigned int *) cp1); + else if (rt2[3] >= 1.0f) *((unsigned int *) rt) = *((unsigned int *) cp2); else { - mfac = rt2[3]; - fac = (fac2 * (256 - mfac)) >> 8; + fac = (fac2 * (1.0f - rt2[3])); - if (fac == 0) *((unsigned int *) rt) = *((unsigned int *) rt2); + if (fac <= 0) *((unsigned int *) rt) = *((unsigned int *) cp2); else { - rt[0] = (fac * rt1[0] + mfac * rt2[0]) >> 8; - rt[1] = (fac * rt1[1] + mfac * rt2[1]) >> 8; - rt[2] = (fac * rt1[2] + mfac * rt2[2]) >> 8; - rt[3] = (fac * rt1[3] + mfac * rt2[3]) >> 8; + tempc[0] = (fac * rt1[0] + rt2[0]); + tempc[1] = (fac * rt1[1] + rt2[1]); + tempc[2] = (fac * rt1[2] + rt2[2]); + tempc[3] = (fac * rt1[3] + rt2[3]); + + premul_float_to_straight_uchar(rt, tempc); } } - rt1 += 4; rt2 += 4; rt += 4; + cp1 += 4; cp2 += 4; rt += 4; } if (y == 0) @@ -348,28 +357,32 @@ static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, un x = xo; while (x--) { - if (rt2[3] == 0 && fac4 == 256) *((unsigned int *) rt) = *((unsigned int *) rt1); - else if (rt2[3] == 255) *((unsigned int *) rt) = *((unsigned int *) rt2); - else { - mfac = rt2[3]; - fac = (fac4 * (256 - mfac)) >> 8; + straight_uchar_to_premul_float(rt1, cp1); + straight_uchar_to_premul_float(rt2, cp2); + + if (rt2[3] <= 0.0f && fac4 >= 1.0f) *((unsigned int *) rt) = *((unsigned int *) cp1); + else if (rt2[3] >= 1.0f) *((unsigned int *) rt) = *((unsigned int *) cp2); + else { + fac = (fac4 * (1.0f - rt2[3])); - if (fac == 0) *((unsigned int *)rt) = *((unsigned int *)rt2); + if (fac <= 0) *((unsigned int *)rt) = *((unsigned int *)cp2); else { - rt[0] = (fac * rt1[0] + mfac * rt2[0]) >> 8; - rt[1] = (fac * rt1[1] + mfac * rt2[1]) >> 8; - rt[2] = (fac * rt1[2] + mfac * rt2[2]) >> 8; - rt[3] = (fac * rt1[3] + mfac * rt2[3]) >> 8; + tempc[0] = (fac * rt1[0] + rt2[0]); + tempc[1] = (fac * rt1[1] + rt2[1]); + tempc[2] = (fac * rt1[2] + rt2[2]); + tempc[3] = (fac * rt1[3] + rt2[3]); + + premul_float_to_straight_uchar(rt, tempc); } } - rt1 += 4; rt2 += 4; rt += 4; + cp1 += 4; cp2 += 4; rt += 4; } } } static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out) { - float fac2, mfac, fac, fac4; + float fac2, fac, fac4; int xo; float *rt1, *rt2, *rt; @@ -396,17 +409,16 @@ static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, memcpy(rt, rt2, 4 * sizeof(float)); } else { - mfac = rt2[3]; - fac = fac2 * (1.0f - mfac); + fac = fac2 * (1.0f - rt2[3]); if (fac == 0) { memcpy(rt, rt2, 4 * sizeof(float)); } else { - rt[0] = fac * rt1[0] + mfac * rt2[0]; - rt[1] = fac * rt1[1] + mfac * rt2[1]; - rt[2] = fac * rt1[2] + mfac * rt2[2]; - rt[3] = fac * rt1[3] + mfac * rt2[3]; + rt[0] = fac * rt1[0] + rt2[0]; + rt[1] = fac * rt1[1] + rt2[1]; + rt[2] = fac * rt1[2] + rt2[2]; + rt[3] = fac * rt1[3] + rt2[3]; } } rt1 += 4; rt2 += 4; rt += 4; @@ -425,17 +437,16 @@ static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, memcpy(rt, rt2, 4 * sizeof(float)); } else { - mfac = rt2[3]; - fac = fac4 * (1.0f - mfac); + fac = fac4 * (1.0f - rt2[3]); if (fac == 0) { memcpy(rt, rt2, 4 * sizeof(float)); } else { - rt[0] = fac * rt1[0] + mfac * rt2[0]; - rt[1] = fac * rt1[1] + mfac * rt2[1]; - rt[2] = fac * rt1[2] + mfac * rt2[2]; - rt[3] = fac * rt1[3] + mfac * rt2[3]; + rt[0] = fac * rt1[0] + rt2[0]; + rt[1] = fac * rt1[1] + rt2[1]; + rt[2] = fac * rt1[2] + rt2[2]; + rt[3] = fac * rt1[3] + rt2[3]; } } rt1 += 4; rt2 += 4; rt += 4; @@ -1311,7 +1322,7 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f if (angle == 0.0f) { b1 = posy; b2 = y; - hyp = fabs(y - posy); + hyp = fabsf(y - posy); } else { b1 = posy - (-angle) * posx; @@ -1398,7 +1409,7 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f x = x - halfx; y = y - halfy; - temp2 = asin(abs(y) / sqrt(x * x + y * y)); + temp2 = asin(abs(y) / hypot(x, y)); if (x <= 0 && y >= 0) temp2 = (float)M_PI - temp2; else if (x <= 0 && y <= 0) temp2 += (float)M_PI; else if (x >= 0 && y <= 0) temp2 = 2.0f * (float)M_PI - temp2; @@ -1441,7 +1452,7 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f temp1 = xo * (1 - facf0 / 2) - xo * facf0 / 2; temp2 = yo * (1 - facf0 / 2) - yo * facf0 / 2; - pointdist = sqrtf(temp1 * temp1 + temp2 * temp2); + pointdist = hypot(temp1, temp2); if (b2 < b1 && b2 < b3) { if (hwidth < pointdist) @@ -1498,9 +1509,9 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f hwidth = width * 0.5f; temp1 = (halfx - (halfx) * facf0); - pointdist = sqrtf(temp1 * temp1 + temp1 * temp1); + pointdist = hypotf(temp1, temp1); - temp2 = sqrtf((halfx - x) * (halfx - x) + (halfy - y) * (halfy - y)); + temp2 = hypotf(halfx - x, halfy - y); if (temp2 > pointdist) output = in_band(hwidth, fabsf(temp2 - pointdist), 0, 1); else output = in_band(hwidth, fabsf(temp2 - pointdist), 1, 1); @@ -1734,8 +1745,8 @@ static void transform_image(int x, int y, ImBuf *ibuf1, ImBuf *out, float scale yo = y; /* Rotate */ - s = sin(rotate); - c = cos(rotate); + s = sinf(rotate); + c = cosf(rotate); for (yi = 0; yi < yo; yi++) { for (xi = 0; xi < xo; xi++) { @@ -2579,6 +2590,295 @@ static void do_overdrop_effect(const SeqRenderData *context, Sequence *UNUSED(se } } +/*********************** Gaussian Blur *************************/ + +/* NOTE: This gaussian blur implementation accumulates values in the square + * kernel rather that doing X direction and then Y direction because of the + * lack of using multiple-staged filters. + * + * Once we can we'll implement a way to apply filter as multiple stages we + * can optimize hell of a lot in here. + */ + +static void init_gaussian_blur_effect(Sequence *seq) +{ + if (seq->effectdata) + MEM_freeN(seq->effectdata); + + seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars"); +} + +static int num_inputs_gaussian_blur(void) +{ + return 1; +} + +static void free_gaussian_blur_effect(Sequence *seq) +{ + if (seq->effectdata) + MEM_freeN(seq->effectdata); + + seq->effectdata = NULL; +} + +static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1)) +{ + GaussianBlurVars *data = seq->effectdata; + if (data->size_x == 0.0f && data->size_y == 0) { + return EARLY_USE_INPUT_1; + } + return EARLY_DO_EFFECT; +} + +/* TODO(sergey): De-duplicate with compositor. */ +static float *make_gaussian_blur_kernel(float rad, int size) +{ + float *gausstab, sum, val; + float fac; + int i, n; + + n = 2 * size + 1; + + gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__); + + sum = 0.0f; + fac = (rad > 0.0f ? 1.0f / rad : 0.0f); + for (i = -size; i <= size; i++) { + val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac); + sum += val; + gausstab[i + size] = val; + } + + sum = 1.0f / sum; + for (i = 0; i < n; i++) + gausstab[i] *= sum; + + return gausstab; +} + +static void do_gaussian_blur_effect_byte(Sequence *seq, + int start_line, + int x, int y, + int frame_width, int frame_height, + unsigned char *rect, + unsigned char *out) +{ +#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4) + GaussianBlurVars *data = seq->effectdata; + const int size_x = (int) (data->size_x + 0.5f), + size_y = (int) (data->size_y + 0.5f); + int i, j; + + /* Make gaussian weight tabke. */ + float *gausstab_x, *gausstab_y; + gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x); + if (data->size_x == data->size_y) { + gausstab_y = gausstab_x; + } + else { + gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y); + } + + for (i = 0; i < y; ++i) { + for (j = 0; j < x; ++j) { + int out_index = INDEX(j, i); + int current_x, current_y; + float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float accum_weight = 0.0f; + for (current_y = i - size_y; + current_y <= i + size_y; + ++current_y) + { + if (current_y < -start_line || + current_y + start_line >= frame_height) + { + /* Out of bounds. */ + continue; + } + + for (current_x = j - size_x; + current_x <= j + size_x; + ++current_x) + { + float weight; + int index = INDEX(current_x, current_y + start_line); + if (current_x < 0 || current_x >= frame_width) { + /* Out of bounds. */ + continue; + } + BLI_assert(index >= 0); + BLI_assert(index < frame_width * frame_height * 4); + + if (size_x != 0 && size_y != 0) { + weight = gausstab_x[current_x - j + size_x] * + gausstab_y[current_y - i + size_y]; + } + else if (size_x == 0) { + weight = gausstab_y[current_y - i + size_y]; + } + else { + weight = gausstab_x[current_x - j + size_x]; + } + accum[0] += rect[index] * weight; + accum[1] += rect[index + 1] * weight; + accum[2] += rect[index + 2] * weight; + accum[3] += rect[index + 3] * weight; + accum_weight += weight; + } + } + out[out_index + 0] = accum[0] / accum_weight; + out[out_index + 1] = accum[1] / accum_weight; + out[out_index + 2] = accum[2] / accum_weight; + out[out_index + 3] = accum[3] / accum_weight; + } + } + + MEM_freeN(gausstab_x); + if (gausstab_x != gausstab_y) { + MEM_freeN(gausstab_y); + } +#undef INDEX +} + +static void do_gaussian_blur_effect_float(Sequence *seq, + int start_line, + int x, int y, + int frame_width, int frame_height, + float *rect, + float *out) +{ +#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4) + GaussianBlurVars *data = seq->effectdata; + const int size_x = (int) (data->size_x + 0.5f), + size_y = (int) (data->size_y + 0.5f); + int i, j; + + /* Make gaussian weight tabke. */ + float *gausstab_x, *gausstab_y; + gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x); + if (data->size_x == data->size_y) { + gausstab_y = gausstab_x; + } + else { + gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y); + } + + for (i = 0; i < y; ++i) { + for (j = 0; j < x; ++j) { + int out_index = INDEX(j, i); + int current_x, current_y; + float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float accum_weight = 0.0f; + for (current_y = i - size_y; + current_y <= i + size_y; + ++current_y) + { + float weight; + if (current_y < -start_line || + current_y + start_line >= frame_height) + { + /* Out of bounds. */ + continue; + } + + for (current_x = j - size_x; + current_x <= j + size_x; + ++current_x) + { + int index = INDEX(current_x, current_y + start_line); + if (current_x < 0 || current_x >= frame_width) { + /* Out of bounds. */ + continue; + } + + if (size_x != 0 && size_y != 0) { + weight = gausstab_x[current_x - j + size_x] * + gausstab_y[current_y - i + size_y]; + } + else if (size_x == 0) { + weight = gausstab_y[current_y - i + size_y]; + } + else { + weight = gausstab_x[current_x - j + size_x]; + } + madd_v4_v4fl(accum, &rect[index], weight); + accum_weight += weight; + } + } + mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight); + } + } + + MEM_freeN(gausstab_x); + if (gausstab_x != gausstab_y) { + MEM_freeN(gausstab_y); + } +#undef INDEX +} + +static void do_gaussian_blur_effect(const SeqRenderData *context, + Sequence *seq, + float UNUSED(cfra), + float UNUSED(facf0), + float UNUSED(facf1), + ImBuf *ibuf1, + ImBuf *ibuf2, + ImBuf *UNUSED(ibuf3), + int start_line, + int total_lines, + ImBuf *out) +{ + if (out->rect_float) { + float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; + + slice_get_float_buffers(context, + ibuf1, ibuf2, + NULL, + out, + start_line, + &rect1, + &rect2, + NULL, + &rect_out); + + do_gaussian_blur_effect_float(seq, + start_line, + context->rectx, + total_lines, + context->rectx, + context->recty, + ibuf1->rect_float, + rect_out); + } + else { + unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; + + slice_get_byte_buffers(context, + ibuf1, ibuf2, + NULL, + out, + start_line, + &rect1, + &rect2, + NULL, + &rect_out); + + do_gaussian_blur_effect_byte(seq, + start_line, + context->rectx, + total_lines, + context->rectx, + context->recty, + (unsigned char *) ibuf1->rect, + rect_out); + } +} + /*********************** sequence effect factory *************************/ static void init_noop(Sequence *UNUSED(seq)) @@ -2767,6 +3067,15 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.early_out = early_out_adjustment; rval.execute = do_adjustment; break; + case SEQ_TYPE_GAUSSIAN_BLUR: + rval.multithreaded = true; + rval.init = init_gaussian_blur_effect; + rval.num_inputs = num_inputs_gaussian_blur; + rval.free = free_gaussian_blur_effect; + rval.copy = copy_gaussian_blur_effect; + rval.early_out = early_out_gaussian_blur; + rval.execute_slice = do_gaussian_blur_effect; + break; } return rval; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index cf15b235b45..0a22faf3c26 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -257,26 +257,15 @@ Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc) return scene->ed; } -static void seq_free_clipboard_recursive(Sequence *seq_parent) -{ - Sequence *seq, *nseq; - - for (seq = seq_parent->seqbase.first; seq; seq = nseq) { - nseq = seq->next; - seq_free_clipboard_recursive(seq); - } - - BKE_sequence_clipboard_pointers_free(seq_parent); - BKE_sequence_free_ex(NULL, seq_parent, false); -} - void BKE_sequencer_free_clipboard(void) { Sequence *seq, *nseq; + BKE_sequencer_base_clipboard_pointers_free(&seqbase_clipboard); + for (seq = seqbase_clipboard.first; seq; seq = nseq) { nseq = seq->next; - seq_free_clipboard_recursive(seq); + seq_free_sequence_recurse(NULL, seq); } BLI_listbase_clear(&seqbase_clipboard); } @@ -373,6 +362,33 @@ void BKE_sequence_clipboard_pointers_restore(Sequence *seq, Main *bmain) seqclipboard_ptr_restore(bmain, (ID **)&seq->mask); seqclipboard_ptr_restore(bmain, (ID **)&seq->sound); } + +/* recursive versions of funcions above */ +void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_free(seq); + BKE_sequencer_base_clipboard_pointers_free(&seq->seqbase); + } +} +void BKE_sequencer_base_clipboard_pointers_store(ListBase *seqbase) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_store(seq); + BKE_sequencer_base_clipboard_pointers_store(&seq->seqbase); + } +} +void BKE_sequencer_base_clipboard_pointers_restore(ListBase *seqbase, Main *bmain) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_restore(seq, bmain); + BKE_sequencer_base_clipboard_pointers_restore(&seq->seqbase, bmain); + } +} + /* end clipboard pointer mess */ @@ -758,7 +774,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r int prev_startdisp = 0, prev_enddisp = 0; /* note: don't rename the strip, will break animation curves */ - if (ELEM7(seq->type, + if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) == 0) { @@ -994,28 +1010,29 @@ void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) static const char *give_seqname_by_type(int type) { switch (type) { - case SEQ_TYPE_META: return "Meta"; - case SEQ_TYPE_IMAGE: return "Image"; - case SEQ_TYPE_SCENE: return "Scene"; - case SEQ_TYPE_MOVIE: return "Movie"; - case SEQ_TYPE_MOVIECLIP: return "Clip"; - case SEQ_TYPE_MASK: return "Mask"; - case SEQ_TYPE_SOUND_RAM: return "Audio"; - case SEQ_TYPE_CROSS: return "Cross"; - case SEQ_TYPE_GAMCROSS: return "Gamma Cross"; - case SEQ_TYPE_ADD: return "Add"; - case SEQ_TYPE_SUB: return "Sub"; - case SEQ_TYPE_MUL: return "Mul"; - case SEQ_TYPE_ALPHAOVER: return "Alpha Over"; - case SEQ_TYPE_ALPHAUNDER: return "Alpha Under"; - case SEQ_TYPE_OVERDROP: return "Over Drop"; - case SEQ_TYPE_WIPE: return "Wipe"; - case SEQ_TYPE_GLOW: return "Glow"; - case SEQ_TYPE_TRANSFORM: return "Transform"; - case SEQ_TYPE_COLOR: return "Color"; - case SEQ_TYPE_MULTICAM: return "Multicam"; - case SEQ_TYPE_ADJUSTMENT: return "Adjustment"; - case SEQ_TYPE_SPEED: return "Speed"; + case SEQ_TYPE_META: return "Meta"; + case SEQ_TYPE_IMAGE: return "Image"; + case SEQ_TYPE_SCENE: return "Scene"; + case SEQ_TYPE_MOVIE: return "Movie"; + case SEQ_TYPE_MOVIECLIP: return "Clip"; + case SEQ_TYPE_MASK: return "Mask"; + case SEQ_TYPE_SOUND_RAM: return "Audio"; + case SEQ_TYPE_CROSS: return "Cross"; + case SEQ_TYPE_GAMCROSS: return "Gamma Cross"; + case SEQ_TYPE_ADD: return "Add"; + case SEQ_TYPE_SUB: return "Sub"; + case SEQ_TYPE_MUL: return "Mul"; + case SEQ_TYPE_ALPHAOVER: return "Alpha Over"; + case SEQ_TYPE_ALPHAUNDER: return "Alpha Under"; + case SEQ_TYPE_OVERDROP: return "Over Drop"; + case SEQ_TYPE_WIPE: return "Wipe"; + case SEQ_TYPE_GLOW: return "Glow"; + case SEQ_TYPE_TRANSFORM: return "Transform"; + case SEQ_TYPE_COLOR: return "Color"; + case SEQ_TYPE_MULTICAM: return "Multicam"; + case SEQ_TYPE_ADJUSTMENT: return "Adjustment"; + case SEQ_TYPE_SPEED: return "Speed"; + case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur"; default: return NULL; } @@ -2224,7 +2241,7 @@ static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, con init_data.out = out; IMB_processor_apply_threaded(out->y, sizeof(RenderEffectThread), &init_data, - render_effect_execute_init_handle, render_effect_execute_do_thread); + render_effect_execute_init_handle, render_effect_execute_do_thread); return out; } @@ -2539,7 +2556,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq } /* prevent eternal loop */ - do_seq = context->scene->r.scemode & R_DOSEQ; + do_seq = scene->r.scemode & R_DOSEQ; scene->r.scemode &= ~R_DOSEQ; #ifdef DURIAN_CAMERA_SWITCH @@ -2808,13 +2825,12 @@ static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, floa float nr = give_stripelem_index(seq, cfra); /* all effects are handled similarly with the exception of speed effect */ int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type; - bool is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE); + bool is_preprocessed = !ELEM(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE); ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); if (ibuf == NULL) { - if (ibuf == NULL) - ibuf = copy_from_ibuf_still(context, seq, nr); + ibuf = copy_from_ibuf_still(context, seq, nr); if (ibuf == NULL) { ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); @@ -2876,7 +2892,7 @@ static bool seq_must_swap_input_in_blend_mode(Sequence *seq) /* bad hack, to fix crazy input ordering of * those two effects */ - if (ELEM3(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) { + if (ELEM(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) { swap_input = true; } @@ -2961,7 +2977,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq /* Some of the blend modes are unclear how to apply with only single input, * or some of them will just produce an empty result.. */ - if (ELEM3(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) { + if (ELEM(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) { int early_out; if (seq->blend_mode == SEQ_BLEND_REPLACE) { early_out = EARLY_NO_INPUT; @@ -3028,7 +3044,13 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq break; case EARLY_DO_EFFECT: if (i == 0) { - out = seq_render_strip(context, seq, cfra); + ImBuf *ibuf1 = IMB_allocImBuf(context->rectx, context->recty, 32, IB_rect); + ImBuf *ibuf2 = seq_render_strip(context, seq, cfra); + + out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2); + + IMB_freeImBuf(ibuf1); + IMB_freeImBuf(ibuf2); } break; @@ -3069,13 +3091,12 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int chanshown) { Editing *ed = BKE_sequencer_editing_get(context->scene, false); - int count; ListBase *seqbasep; if (ed == NULL) return NULL; - count = BLI_countlist(&ed->metastack); - if ((chanshown < 0) && (count > 0)) { + if ((chanshown < 0) && !BLI_listbase_is_empty(&ed->metastack)) { + int count = BLI_countlist(&ed->metastack); count = max_ii(count + chanshown, 0); seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep; } @@ -3508,16 +3529,28 @@ bool BKE_sequence_single_check(Sequence *seq) } /* check if the selected seq's reference unselected seq's */ -bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase) +bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase, bool one_only) { Sequence *seq; - /* is there more than 1 select */ + /* is there a valid selection select */ bool ok = false; + /* is there one selected already? */ + bool first = false; for (seq = seqbase->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - ok = true; - break; + if (one_only) { + ok = true; + break; + } + else { + if (first) { + ok = true; + break; + } + else + first = true; + } } } @@ -3684,7 +3717,7 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame) if (seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame) continue; /* only use elements you can see - not */ - if (ELEM5(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) { + if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) { if (seq->machine > best_machine) { best_seq = seq; best_machine = seq->machine; @@ -4037,19 +4070,31 @@ int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) return 1; } +/* prefix + [" + escaped_name + "] + \0 */ +#define SEQ_RNAPATH_MAXSTR ((30 + 2 + (SEQ_NAME_MAXSTR * 2) + 2) + 1) + +static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char *name) +{ + char name_esc[SEQ_NAME_MAXSTR * 2]; + + BLI_strescape(name_esc, name, sizeof(name_esc)); + return BLI_snprintf(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); +} + /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ void BKE_sequencer_offset_animdata(Scene *scene, Sequence *seq, int ofs) { - char str[SEQ_NAME_MAXSTR + 3]; + char str[SEQ_RNAPATH_MAXSTR]; + size_t str_len; FCurve *fcu; if (scene->adt == NULL || ofs == 0 || scene->adt->action == NULL) return; - BLI_snprintf(str, sizeof(str), "[\"%s\"]", seq->name + 2); + str_len = sequencer_rna_path_prefix(str, seq->name + 2); for (fcu = scene->adt->action->curves.first; fcu; fcu = fcu->next) { - if (strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { + if (STREQLEN(fcu->rna_path, str, str_len)) { unsigned int i; if (fcu->bezt) { for (i = 0; i < fcu->totvert; i++) { @@ -4071,7 +4116,8 @@ void BKE_sequencer_offset_animdata(Scene *scene, Sequence *seq, int ofs) void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) { - char str_from[SEQ_NAME_MAXSTR + 3]; + char str_from[SEQ_RNAPATH_MAXSTR]; + size_t str_from_len; FCurve *fcu; FCurve *fcu_last; FCurve *fcu_cpy; @@ -4080,12 +4126,12 @@ void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char if (scene->adt == NULL || scene->adt->action == NULL) return; - BLI_snprintf(str_from, sizeof(str_from), "[\"%s\"]", name_src); + str_from_len = sequencer_rna_path_prefix(str_from, name_src); fcu_last = scene->adt->action->curves.last; for (fcu = scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu = fcu->next) { - if (strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str_from)) { + if (STREQLEN(fcu->rna_path, str_from, str_from_len)) { fcu_cpy = copy_fcurve(fcu); BLI_addtail(&lb, fcu_cpy); } @@ -4101,18 +4147,19 @@ void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char /* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */ static void seq_free_animdata(Scene *scene, Sequence *seq) { - char str[SEQ_NAME_MAXSTR + 3]; + char str[SEQ_RNAPATH_MAXSTR]; + size_t str_len; FCurve *fcu; if (scene->adt == NULL || scene->adt->action == NULL) return; - BLI_snprintf(str, sizeof(str), "[\"%s\"]", seq->name + 2); + str_len = sequencer_rna_path_prefix(str, seq->name + 2); fcu = scene->adt->action->curves.first; while (fcu) { - if (strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { + if (STREQLEN(fcu->rna_path, str, str_len)) { FCurve *next_fcu = fcu->next; BLI_remlink(&scene->adt->action->curves, fcu); @@ -4126,6 +4173,8 @@ static void seq_free_animdata(Scene *scene, Sequence *seq) } } +#undef SEQ_RNAPATH_MAXSTR + Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, bool recursive) { Sequence *iseq = NULL; @@ -4463,7 +4512,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad int start_frame_back = seq_load->start_frame; seq_load->channel++; - BKE_sequencer_add_sound_strip(C, seqbasep, seq_load); + seq_load->seq_sound = BKE_sequencer_add_sound_strip(C, seqbasep, seq_load); seq_load->start_frame = start_frame_back; seq_load->channel--; @@ -4583,11 +4632,15 @@ Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence * return seqn; } -void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag) +void BKE_sequence_base_dupli_recursive( + Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, + int dupe_flag) { Sequence *seq; Sequence *seqn = NULL; Sequence *last_seq = BKE_sequencer_active_get(scene); + /* always include meta's strips */ + int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL; for (seq = seqbase->first; seq; seq = seq->next) { seq->tmp = NULL; @@ -4600,8 +4653,11 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase * } BLI_addtail(nseqbase, seqn); - if (seq->type == SEQ_TYPE_META) - BKE_sequence_base_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag); + if (seq->type == SEQ_TYPE_META) { + BKE_sequence_base_dupli_recursive( + scene, scene_to, &seqn->seqbase, &seq->seqbase, + dupe_flag_recursive); + } if (dupe_flag & SEQ_DUPE_CONTEXT) { if (seq == last_seq) { diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index e2cc7b84f95..d2a4d15a2c6 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -50,6 +50,7 @@ #include "BKE_lattice.h" #include "BKE_deform.h" +#include "BKE_mesh.h" /* for OMP limits. */ #include "BKE_subsurf.h" #include "BKE_editmesh.h" @@ -65,57 +66,6 @@ /* Util macros */ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) -/* get derived mesh */ -/* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */ -DerivedMesh *object_get_derived_final(Object *ob, bool for_render) -{ - Mesh *me = ob->data; - BMEditMesh *em = me->edit_btmesh; - - if (for_render) { - /* TODO(sergey): use proper derived render here in the future. */ - return ob->derivedFinal; - } - - if (em) { - DerivedMesh *dm = em->derivedFinal; - return dm; - } - - return ob->derivedFinal; -} - -/* Space transform */ -void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float target[4][4]) -{ - float itarget[4][4]; - invert_m4_m4(itarget, target); - mul_m4_m4m4(data->local2target, itarget, local); - invert_m4_m4(data->target2local, data->local2target); -} - -void space_transform_apply(const SpaceTransform *data, float co[3]) -{ - mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co); -} - -void space_transform_invert(const SpaceTransform *data, float co[3]) -{ - mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co); -} - -static void space_transform_apply_normal(const SpaceTransform *data, float no[3]) -{ - mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no); - normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */ -} - -static void space_transform_invert_normal(const SpaceTransform *data, float no[3]) -{ - mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no); - normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */ -} - /* * Shrinkwrap to the nearest vertex * @@ -135,12 +85,12 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) OUT_OF_MEMORY(); return; } - + /* Setup nearest */ nearest.index = -1; nearest.dist_sq = FLT_MAX; #ifndef __APPLE__ -#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) +#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT) #endif for (i = 0; i < calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -158,7 +108,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) else { copy_v3_v3(tmp_co, co); } - space_transform_apply(&calc->local2target, tmp_co); + BLI_space_transform_apply(&calc->local2target, tmp_co); /* Use local proximity heuristics (to reduce the nearest search) * @@ -184,7 +134,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) /* Convert the coordinates back to mesh coordinates */ copy_v3_v3(tmp_co, nearest.co); - space_transform_invert(&calc->local2target, tmp_co); + BLI_space_transform_invert(&calc->local2target, tmp_co); interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ } @@ -223,11 +173,11 @@ bool BKE_shrinkwrap_project_normal( /* Apply space transform (TODO readjust dist) */ if (transf) { copy_v3_v3(tmp_co, vert); - space_transform_apply(transf, tmp_co); + BLI_space_transform_apply(transf, tmp_co); co = tmp_co; copy_v3_v3(tmp_no, dir); - space_transform_apply_normal(transf, tmp_no); + BLI_space_transform_apply_normal(transf, tmp_no); no = tmp_no; #ifdef USE_DIST_CORRECT @@ -246,7 +196,7 @@ bool BKE_shrinkwrap_project_normal( if (hit_tmp.index != -1) { /* invert the normal first so face culling works on rotated objects */ if (transf) { - space_transform_invert_normal(transf, hit_tmp.no); + BLI_space_transform_invert_normal(transf, hit_tmp.no); } if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) { @@ -261,7 +211,7 @@ bool BKE_shrinkwrap_project_normal( if (transf) { /* Inverting space transform (TODO make coeherent with the initial dist readjust) */ - space_transform_invert(transf, hit_tmp.co); + BLI_space_transform_invert(transf, hit_tmp.co); #ifdef USE_DIST_CORRECT hit_tmp.dist = len_v3v3(vert, hit_tmp.co); #endif @@ -326,7 +276,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for auxMesh = object_get_derived_final(calc->smd->auxTarget, for_render); if (!auxMesh) return; - SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); + BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); } /* After sucessufuly build the trees, start projection vertexs */ @@ -335,7 +285,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for { #ifndef __APPLE__ -#pragma omp parallel for private(i, hit) schedule(static) +#pragma omp parallel for private(i, hit) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT) #endif for (i = 0; i < calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -445,7 +395,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) /* Find the nearest vertex */ #ifndef __APPLE__ -#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) +#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT) #endif for (i = 0; i < calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -460,7 +410,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) else { copy_v3_v3(tmp_co, co); } - space_transform_apply(&calc->local2target, tmp_co); + BLI_space_transform_apply(&calc->local2target, tmp_co); /* Use local proximity heuristics (to reduce the nearest search) * @@ -494,7 +444,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) } /* Convert the coordinates back to mesh coordinates */ - space_transform_invert(&calc->local2target, tmp_co); + BLI_space_transform_invert(&calc->local2target, tmp_co); interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ } } @@ -537,7 +487,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM /* TODO there might be several "bugs" on non-uniform scales matrixs * because it will no longer be nearest surface, not sphere projection * because space has been deformed */ - SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target); + BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target); /* TODO: smd->keepDist is in global units.. must change to local */ calc.keepDist = smd->keepDist; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index c0cc2cd119c..50e0054b125 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -33,8 +33,6 @@ /* Part of the code copied from elbeem fluid library, copyright by Nils Thuerey */ -#include <GL/glew.h> - #include "MEM_guardedalloc.h" #include <float.h> @@ -84,6 +82,8 @@ #include "RE_shader_ext.h" +#include "GPU_glew.h" + /* UNUSED so far, may be enabled later */ /* #define USE_SMOKE_COLLISION_DM */ @@ -211,7 +211,7 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[ /* smoke_turbulence_init uses non-threadsafe functions from fftw3 lib (like fftw_plan & co). */ BLI_lock_thread(LOCK_FFTW); - sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BLI_temporary_dir(), use_fire, use_colors); + sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BLI_temp_dir_session(), use_fire, use_colors); if (sds->flags & MOD_SMOKE_USE_MANTA){ smoke_mantaflow_write_scene_file(sds->smd); } @@ -1579,8 +1579,7 @@ static void sample_derivedmesh( static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, float dt) { clock_t start = clock(); - if (!sfs->dm) return; - { + if (sfs->dm) { DerivedMesh *dm; int defgrp_index = sfs->vgroup_density - 1; MDeformVert *dvert = NULL; @@ -1711,10 +1710,16 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo free_bvhtree_from_mesh(&treeData); /* restore original mverts */ CustomData_set_layer(&dm->vertData, CD_MVERT, mvert_orig); - if (mvert) + + if (mvert) { MEM_freeN(mvert); + } + if (vert_vel) { + MEM_freeN(vert_vel); + } - if (vert_vel) MEM_freeN(vert_vel); + dm->needsFree = 1; + dm->release(dm); } clock_t end = clock(); float seconds = (float)(end - start) / CLOCKS_PER_SEC; diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 9c411142566..13575560669 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -2160,7 +2160,7 @@ static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, floa // dfdx_spring(ia, ia, op, dir, bs->len, distance, -mpos); /* depending on my vel */ // dfdv_goal(ia, ia, mvel); // well that ignores geometie - if (bp2->goal < SOFTGOALSNAP) { /* ommit this bp when it snaps */ + if (bp2->goal < SOFTGOALSNAP) { /* omit this bp when it snaps */ /* depending on other pos */ // dfdx_spring(ia, ic, op, dir, bs->len, distance, mpos); /* depending on other vel */ @@ -2257,7 +2257,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo } /* naive ball self collision done */ - if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* ommit this bp when it snaps */ + if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */ float auxvect[3]; float velgoal[3]; @@ -2652,7 +2652,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa } /* naive ball self collision done */ - if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* ommit this bp when it snaps */ + if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */ float auxvect[3]; float velgoal[3]; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 6ba843c8a8f..da6ead06d98 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -727,7 +727,7 @@ void sound_update_scene(Main *bmain, struct Scene *scene) if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) { if (speaker->sound) { - AUD_moveSequence(strip->speaker_handle, (double)strip->start / FPS, -1, 0); + AUD_moveSequence(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0); } else { AUD_removeSequence(scene->sound_scene, strip->speaker_handle); @@ -738,7 +738,7 @@ void sound_update_scene(Main *bmain, struct Scene *scene) if (speaker->sound) { strip->speaker_handle = AUD_addSequence(scene->sound_scene, speaker->sound->playback_handle, - (double)strip->start / FPS, -1, 0); + (double)strip->start / FPS, FLT_MAX, 0); AUD_setRelativeSequence(strip->speaker_handle, 0); } } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index a9eba54128a..f03e2eaff4a 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -41,6 +41,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -71,10 +72,9 @@ # include "BLI_array.h" #endif -#include "GL/glew.h" - #include "GPU_draw.h" #include "GPU_extensions.h" +#include "GPU_glew.h" #include "GPU_material.h" #include "CCGSubSurf.h" @@ -360,7 +360,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MVert *mv0 = mvert + (ml[j_next].v); MVert *mv1 = mvert + (ml[j].v); - if (BLI_edgeset_reinsert(eset, v0, v1)) { + if (BLI_edgeset_add(eset, v0, v1)) { CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next); CCGEdgeHDL ehdl = SET_INT_IN_POINTER(mp->loopstart + j_next); float crease; @@ -1077,7 +1077,7 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly, vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize); offset = (y * factor) * hidden_gridsize + (x * factor); - if (BLI_BITMAP_GET(md->hidden, offset)) + if (BLI_BITMAP_TEST(md->hidden, offset)) mvert[vndx].flag |= ME_HIDE; } } @@ -1457,6 +1457,7 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e; } + ccgEdgeIterator_free(ei); totface = ccgSubSurf_getNumFaces(ss); faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap"); @@ -2290,18 +2291,23 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, DMSetDrawOptionsTex drawParams, DMSetDrawOptions drawParamsMapped, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag flag) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; CCGKey key; MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + MTFace *tf_stencil_base = NULL; + MTFace *tf_stencil = NULL; + MTFace *tf_base; short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); DMFlagMat *faceFlags = ccgdm->faceFlags; DMDrawOption draw_option; int i, totface, gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; + int gridOffset = 0; + int mat_nr_cache = -1; (void) compareDrawOptions; @@ -2315,6 +2321,12 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL); totface = ccgSubSurf_getNumFaces(ss); + + if (flag & DM_DRAW_USE_TEXPAINT_UV) { + int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE); + tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil); + } + for (i = 0; i < totface; i++) { CCGFace *f = ccgdm->faceMap[i].face; int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); @@ -2333,6 +2345,19 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, mat_nr = 0; } + /* texture painting, handle the correct uv layer here */ + if (flag & DM_DRAW_USE_TEXPAINT_UV) { + if (mat_nr != mat_nr_cache) { + tf_base = DM_paint_uvlayer_active_get(dm, mat_nr); + + mat_nr_cache = mat_nr; + } + + tf = tf_base ? tf_base + gridOffset : NULL; + tf_stencil = tf_stencil_base ? tf_stencil_base + gridOffset : NULL; + gridOffset += gridFaces * gridFaces * numVerts; + } + if (drawParams) draw_option = drawParams(tf, (mcol != NULL), mat_nr); else if (index != ORIGINDEX_NONE) @@ -2373,26 +2398,31 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1); if (tf) glTexCoord2fv(tf->uv[1]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]); if (cp) glColor3ub(cp[7], cp[6], cp[5]); glNormal3sv(ln[0][1]); glVertex3fv(d_co); if (tf) glTexCoord2fv(tf->uv[2]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]); if (cp) glColor3ub(cp[11], cp[10], cp[9]); glNormal3sv(ln[0][2]); glVertex3fv(c_co); if (tf) glTexCoord2fv(tf->uv[3]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]); if (cp) glColor3ub(cp[15], cp[14], cp[13]); glNormal3sv(ln[0][3]); glVertex3fv(b_co); if (tf) glTexCoord2fv(tf->uv[0]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]); if (cp) glColor3ub(cp[3], cp[2], cp[1]); glNormal3sv(ln[0][0]); glVertex3fv(a_co); if (tf) tf++; + if (tf_stencil) tf_stencil++; if (cp) cp += 16; ln++; } @@ -2408,17 +2438,20 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, b = CCG_grid_elem(&key, faceGridData, x, y + 1); if (tf) glTexCoord2fv(tf->uv[0]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]); if (cp) glColor3ub(cp[3], cp[2], cp[1]); glNormal3fv(CCG_elem_no(&key, a)); glVertex3fv(CCG_elem_co(&key, a)); if (tf) glTexCoord2fv(tf->uv[1]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]); if (cp) glColor3ub(cp[7], cp[6], cp[5]); glNormal3fv(CCG_elem_no(&key, b)); glVertex3fv(CCG_elem_co(&key, b)); if (x != gridFaces - 1) { if (tf) tf++; + if (tf_stencil) tf_stencil++; if (cp) cp += 16; } } @@ -2427,16 +2460,19 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, b = CCG_grid_elem(&key, faceGridData, x, y + 1); if (tf) glTexCoord2fv(tf->uv[3]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]); if (cp) glColor3ub(cp[15], cp[14], cp[13]); glNormal3fv(CCG_elem_no(&key, a)); glVertex3fv(CCG_elem_co(&key, a)); if (tf) glTexCoord2fv(tf->uv[2]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]); if (cp) glColor3ub(cp[11], cp[10], cp[9]); glNormal3fv(CCG_elem_no(&key, b)); glVertex3fv(CCG_elem_co(&key, b)); if (tf) tf++; + if (tf_stencil) tf_stencil++; if (cp) cp += 16; glEnd(); @@ -2455,22 +2491,27 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, ccgDM_glNormalFast(a_co, b_co, c_co, d_co); if (tf) glTexCoord2fv(tf->uv[1]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]); if (cp) glColor3ub(cp[7], cp[6], cp[5]); glVertex3fv(d_co); if (tf) glTexCoord2fv(tf->uv[2]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]); if (cp) glColor3ub(cp[11], cp[10], cp[9]); glVertex3fv(c_co); if (tf) glTexCoord2fv(tf->uv[3]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]); if (cp) glColor3ub(cp[15], cp[14], cp[13]); glVertex3fv(b_co); if (tf) glTexCoord2fv(tf->uv[0]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]); if (cp) glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(a_co); if (tf) tf++; + if (tf_stencil) tf_stencil++; if (cp) cp += 16; } } @@ -2483,17 +2524,17 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, static void ccgDM_drawFacesTex(DerivedMesh *dm, DMSetDrawOptionsTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag flag) { - ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); + ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag); } static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag flag) { - ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); + ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag); } static void ccgDM_drawUVEdges(DerivedMesh *dm) @@ -3542,6 +3583,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e; } + ccgEdgeIterator_free(ei); totface = ccgSubSurf_getNumFaces(ss); ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap"); @@ -3780,8 +3822,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, } if (has_edge_cd) { + BLI_assert(edgeIdx >= 0 && edgeIdx < dm->getNumEdges(dm)); for (i = 0; i < numFinalEdges; ++i) { - CustomData_copy_data(&dm->edgeData, &ccgdm->dm.edgeData, mapIndex, edgeNum + i, 1); + CustomData_copy_data(&dm->edgeData, &ccgdm->dm.edgeData, edgeIdx, edgeNum + i, 1); } } diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index b6d7e8922c4..8a272cd9d81 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -267,16 +267,79 @@ static void cleanup_textline(TextLine *tl) tl->len += txt_extended_ascii_as_utf8(&tl->line); } +/** + * used for load and reload (unlike txt_insert_buf) + * assumes all fields are empty + */ +static void text_from_buf(Text *text, const unsigned char *buffer, const int len) +{ + int i, llen; + + BLI_assert(BLI_listbase_is_empty(&text->lines)); + + text->nlines = 0; + llen = 0; + for (i = 0; i < len; i++) { + if (buffer[i] == '\n') { + TextLine *tmp; + + tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); + tmp->format = NULL; + + if (llen) memcpy(tmp->line, &buffer[i - llen], llen); + tmp->line[llen] = 0; + tmp->len = llen; + + cleanup_textline(tmp); + + BLI_addtail(&text->lines, tmp); + text->nlines++; + + llen = 0; + continue; + } + llen++; + } + + /* create new line in cases: + * - rest of line (if last line in file hasn't got \n terminator). + * in this case content of such line would be used to fill text line buffer + * - file is empty. in this case new line is needed to start editing from. + * - last characted in buffer is \n. in this case new line is needed to + * deal with newline at end of file. (see [#28087]) (sergey) */ + if (llen != 0 || text->nlines == 0 || buffer[len - 1] == '\n') { + TextLine *tmp; + + tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); + tmp->format = NULL; + + if (llen) memcpy(tmp->line, &buffer[i - llen], llen); + + tmp->line[llen] = 0; + tmp->len = llen; + + cleanup_textline(tmp); + + BLI_addtail(&text->lines, tmp); + text->nlines++; + } + + text->curl = text->sell = text->lines.first; + text->curc = text->selc = 0; +} + int BKE_text_reload(Text *text) { FILE *fp; - int i, llen, len; + int len; unsigned char *buffer; TextLine *tmp; char str[FILE_MAX]; - struct stat st; + BLI_stat_t st; - if (!text || !text->name) return 0; + if (!text->name) return 0; BLI_strncpy(str, text->name, FILE_MAX); BLI_path_abs(str, G.main->name); @@ -299,13 +362,12 @@ int BKE_text_reload(Text *text) /* clear undo buffer */ MEM_freeN(text->undo_buf); init_undo_text(text); - + fseek(fp, 0L, SEEK_END); len = ftell(fp); fseek(fp, 0L, SEEK_SET); - text->undo_pos = -1; - + buffer = MEM_mallocN(len, "text_buffer"); // under windows fread can return less then len bytes because // of CR stripping @@ -313,51 +375,11 @@ int BKE_text_reload(Text *text) fclose(fp); - stat(str, &st); + BLI_stat(str, &st); text->mtime = st.st_mtime; - - text->nlines = 0; - llen = 0; - for (i = 0; i < len; i++) { - if (buffer[i] == '\n') { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); - tmp->format = NULL; - - if (llen) memcpy(tmp->line, &buffer[i - llen], llen); - tmp->line[llen] = 0; - tmp->len = llen; - - cleanup_textline(tmp); - - BLI_addtail(&text->lines, tmp); - text->nlines++; - - llen = 0; - continue; - } - llen++; - } - if (llen != 0 || text->nlines == 0) { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); - tmp->format = NULL; - - if (llen) memcpy(tmp->line, &buffer[i - llen], llen); + text_from_buf(text, buffer, len); - tmp->line[llen] = 0; - tmp->len = llen; - - cleanup_textline(tmp); - - BLI_addtail(&text->lines, tmp); - text->nlines++; - } - - text->curl = text->sell = text->lines.first; - text->curc = text->selc = 0; - MEM_freeN(buffer); return 1; } @@ -365,12 +387,11 @@ int BKE_text_reload(Text *text) Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const bool is_internal) { FILE *fp; - int i, llen, len; + int len; unsigned char *buffer; - TextLine *tmp; Text *ta; char str[FILE_MAX]; - struct stat st; + BLI_stat_t st; BLI_strncpy(str, file, FILE_MAX); if (relpath) /* can be NULL (bg mode) */ @@ -388,10 +409,6 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0) ta->flags = TXT_TABSTOSPACES; - fseek(fp, 0L, SEEK_END); - len = ftell(fp); - fseek(fp, 0L, SEEK_SET); - if (is_internal == false) { ta->name = MEM_mallocN(strlen(file) + 1, "text_name"); strcpy(ta->name, file); @@ -400,7 +417,12 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const ta->flags |= TXT_ISMEM | TXT_ISDIRTY; } + /* clear undo buffer */ init_undo_text(ta); + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + fseek(fp, 0L, SEEK_SET); buffer = MEM_mallocN(len, "text_buffer"); // under windows fread can return less then len bytes because @@ -409,56 +431,10 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const fclose(fp); - stat(str, &st); + BLI_stat(str, &st); ta->mtime = st.st_mtime; - ta->nlines = 0; - llen = 0; - for (i = 0; i < len; i++) { - if (buffer[i] == '\n') { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); - tmp->format = NULL; - - if (llen) memcpy(tmp->line, &buffer[i - llen], llen); - tmp->line[llen] = 0; - tmp->len = llen; - - cleanup_textline(tmp); - - BLI_addtail(&ta->lines, tmp); - ta->nlines++; - - llen = 0; - continue; - } - llen++; - } - - /* create new line in cases: - * - rest of line (if last line in file hasn't got \n terminator). - * in this case content of such line would be used to fill text line buffer - * - file is empty. in this case new line is needed to start editing from. - * - last characted in buffer is \n. in this case new line is needed to - * deal with newline at end of file. (see [#28087]) (sergey) */ - if (llen != 0 || ta->nlines == 0 || buffer[len - 1] == '\n') { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); - tmp->format = NULL; - - if (llen) memcpy(tmp->line, &buffer[i - llen], llen); - - tmp->line[llen] = 0; - tmp->len = llen; - - cleanup_textline(tmp); - - BLI_addtail(&ta->lines, tmp); - ta->nlines++; - } - - ta->curl = ta->sell = ta->lines.first; - ta->curc = ta->selc = 0; + text_from_buf(ta, buffer, len); MEM_freeN(buffer); @@ -667,11 +643,11 @@ void BKE_text_write(Text *text, const char *str) /* called directly from rna */ int BKE_text_file_modified_check(Text *text) { - struct stat st; + BLI_stat_t st; int result; char file[FILE_MAX]; - if (!text || !text->name) + if (!text->name) return 0; BLI_strncpy(file, text->name, FILE_MAX); @@ -696,11 +672,11 @@ int BKE_text_file_modified_check(Text *text) void BKE_text_file_modified_ignore(Text *text) { - struct stat st; + BLI_stat_t st; int result; char file[FILE_MAX]; - if (!text || !text->name) return; + if (!text->name) return; BLI_strncpy(file, text->name, FILE_MAX); BLI_path_abs(file, G.main->name); @@ -766,9 +742,7 @@ static TextLine *txt_new_linen(const char *str, int n) void txt_clean_text(Text *text) { TextLine **top, **bot; - - if (!text) return; - + if (!text->lines.first) { if (text->lines.last) text->lines.first = text->lines.last; else text->lines.first = text->lines.last = txt_new_line(NULL); @@ -907,8 +881,7 @@ void txt_move_up(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -930,8 +903,7 @@ void txt_move_down(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -953,8 +925,7 @@ void txt_move_left(Text *text, const bool sel) TextLine **linep; int *charp; int tabsize = 0, i = 0; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -998,8 +969,7 @@ void txt_move_right(Text *text, const bool sel) TextLine **linep; int *charp, i; bool do_tab = false; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -1040,8 +1010,7 @@ void txt_jump_left(Text *text, const bool sel, const bool use_init_step) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -1057,8 +1026,7 @@ void txt_jump_right(Text *text, const bool sel, const bool use_init_step) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -1074,8 +1042,7 @@ void txt_move_bol(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1089,8 +1056,7 @@ void txt_move_eol(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1104,8 +1070,7 @@ void txt_move_bof(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1120,8 +1085,7 @@ void txt_move_eof(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1143,8 +1107,7 @@ void txt_move_to(Text *text, unsigned int line, unsigned int ch, const bool sel) TextLine **linep; int *charp; unsigned int i; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1181,7 +1144,6 @@ static void txt_curs_swap(Text *text) static void txt_pop_first(Text *text) { - if (txt_get_span(text->curl, text->sell) < 0 || (text->curl == text->sell && text->curc > text->selc)) { @@ -1210,7 +1172,6 @@ void txt_pop_sel(Text *text) void txt_order_cursors(Text *text, const bool reverse) { - if (!text) return; if (!text->curl) return; if (!text->sell) return; @@ -1240,8 +1201,7 @@ static void txt_delete_sel(Text *text) { TextLine *tmpl; char *buf; - - if (!text) return; + if (!text->curl) return; if (!text->sell) return; @@ -1277,8 +1237,6 @@ static void txt_delete_sel(Text *text) void txt_sel_all(Text *text) { - if (!text) return; - text->curl = text->lines.first; text->curc = 0; @@ -1286,9 +1244,21 @@ void txt_sel_all(Text *text) text->selc = text->sell->len; } +/** + * Reverse of #txt_pop_sel + * Clears the selection and ensures the cursor is located + * at the selection (where the cursor is visually while editing). + */ +void txt_sel_clear(Text *text) +{ + if (text->sell) { + text->curl = text->sell; + text->curc = text->selc; + } +} + void txt_sel_line(Text *text) { - if (!text) return; if (!text->curl) return; text->curc = 0; @@ -1306,8 +1276,7 @@ char *txt_to_buf(Text *text) TextLine *tmp, *linef, *linel; int charf, charl; char *buf; - - if (!text) return NULL; + if (!text->curl) return NULL; if (!text->sell) return NULL; if (!text->lines.first) return NULL; @@ -1369,7 +1338,7 @@ int txt_find_string(Text *text, const char *findstr, int wrap, int match_case) TextLine *tl, *startl; const char *s = NULL; - if (!text || !text->curl || !text->sell) return 0; + if (!text->curl || !text->sell) return 0; txt_order_cursors(text, false); @@ -1409,8 +1378,7 @@ char *txt_sel_to_buf(Text *text) int length = 0; TextLine *tmp, *linef, *linel; int charf, charl; - - if (!text) return NULL; + if (!text->curl) return NULL; if (!text->sell) return NULL; @@ -1491,7 +1459,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) TextLine *add; char *buffer; - if (!text) return; if (!in_buffer) return; txt_delete_sel(text); @@ -2373,8 +2340,7 @@ void txt_split_curline(Text *text) { TextLine *ins; char *left, *right; - - if (!text) return; + if (!text->curl) return; txt_delete_sel(text); @@ -2416,7 +2382,6 @@ void txt_split_curline(Text *text) static void txt_delete_line(Text *text, TextLine *line) { - if (!text) return; if (!text->curl) return; BLI_remlink(&text->lines, line); @@ -2433,8 +2398,6 @@ static void txt_delete_line(Text *text, TextLine *line) static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb) { char *tmp, *s; - - if (!text) return; if (!linea || !lineb) return; @@ -2458,7 +2421,7 @@ void txt_duplicate_line(Text *text) { TextLine *textline; - if (!text || !text->curl) return; + if (!text->curl) return; if (text->curl == text->sell) { textline = txt_new_line(text->curl->line); @@ -2474,8 +2437,7 @@ void txt_duplicate_line(Text *text) void txt_delete_char(Text *text) { unsigned int c = '\n'; - - if (!text) return; + if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ @@ -2518,7 +2480,6 @@ void txt_backspace_char(Text *text) { unsigned int c = '\n'; - if (!text) return; if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ @@ -2582,8 +2543,7 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs) { char *tmp, ch[BLI_UTF8_MAX]; size_t add_len; - - if (!text) return 0; + if (!text->curl) return 0; if (add == '\n') { @@ -2642,8 +2602,7 @@ bool txt_replace_char(Text *text, unsigned int add) unsigned int del; size_t del_size = 0, add_size; char ch[BLI_UTF8_MAX]; - - if (!text) return 0; + if (!text->curl) return 0; /* If text is selected or we're at the end of the line just use txt_add_char */ @@ -2697,7 +2656,7 @@ void txt_indent(Text *text) /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; - if (ELEM3(NULL, text, text->curl, text->sell)) { + if (ELEM(NULL, text->curl, text->sell)) { return; } @@ -2764,7 +2723,7 @@ void txt_unindent(Text *text) /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; - if (ELEM3(NULL, text, text->curl, text->sell)) { + if (ELEM(NULL, text->curl, text->sell)) { return; } @@ -2817,8 +2776,7 @@ void txt_comment(Text *text) int len, num; char *tmp; char add = '#'; - - if (!text) return; + if (!text->curl) return; if (!text->sell) return; // Need to change this need to check if only one line is selected to more than one @@ -2865,8 +2823,7 @@ void txt_uncomment(Text *text) { int num = 0; char remove = '#'; - - if (!text) return; + if (!text->curl) return; if (!text->sell) return; @@ -2912,7 +2869,7 @@ void txt_move_lines(struct Text *text, const int direction) BLI_assert(ELEM(direction, TXT_MOVE_LINE_UP, TXT_MOVE_LINE_DOWN)); - if (!text || !text->curl || !text->sell) return; + if (!text->curl || !text->sell) return; txt_order_cursors(text, false); @@ -2945,6 +2902,7 @@ int txt_setcurr_tab_spaces(Text *text, int space) const char *comm = "#"; const char indent = (text->flags & TXT_TABSTOSPACES) ? ' ' : '\t'; static const char *back_words[] = {"return", "break", "continue", "pass", "yield", NULL}; + if (!text->curl) return 0; while (text->curl->line[i] == indent) { diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 4fff50153ef..b1981a3a804 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -41,6 +41,7 @@ #include "BLI_math.h" #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" +#include "BLI_math_color.h" #include "DNA_key_types.h" #include "DNA_object_types.h" @@ -145,12 +146,12 @@ void init_tex_mapping(TexMapping *texmap) if (texmap->type == TEXMAP_TYPE_TEXTURE) { /* to transform a texture, the inverse transform needs * to be applied to the texture coordinate */ - mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0); + mul_m4_series(texmap->mat, tmat, rmat, smat); invert_m4(texmap->mat); } else if (texmap->type == TEXMAP_TYPE_POINT) { /* forward transform */ - mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0); + mul_m4_series(texmap->mat, tmat, rmat, smat); } else if (texmap->type == TEXMAP_TYPE_VECTOR) { /* no translation for vectors */ @@ -237,7 +238,7 @@ void init_colorband(ColorBand *coba, bool rangetype) } coba->tot = 2; - + coba->color_mode = COLBAND_BLEND_RGB; } ColorBand *add_colorband(bool rangetype) @@ -252,106 +253,209 @@ ColorBand *add_colorband(bool rangetype) /* ------------------------------------------------------------------------- */ +static float colorband_hue_interp( + const int ipotype_hue, + const float mfac, const float fac, + float h1, float h2) +{ + float h_interp; + int mode = 0; + +#define HUE_INTERP(h_a, h_b) ((mfac * (h_a)) + (fac * (h_b))) +#define HUE_MOD(h) (((h) < 1.0f) ? (h) : (h) - 1.0f) + + h1 = HUE_MOD(h1); + h2 = HUE_MOD(h2); + + BLI_assert(h1 >= 0.0f && h1 < 1.0f); + BLI_assert(h2 >= 0.0f && h2 < 1.0f); + + switch (ipotype_hue) { + case COLBAND_HUE_NEAR: + { + if ((h1 < h2) && (h2 - h1) > +0.5f) mode = 1; + else if ((h1 > h2) && (h2 - h1) < -0.5f) mode = 2; + else mode = 0; + break; + } + case COLBAND_HUE_FAR: + { + if ((h1 < h2) && (h2 - h1) < +0.5f) mode = 1; + else if ((h1 > h2) && (h2 - h1) > -0.5f) mode = 2; + else mode = 0; + break; + } + case COLBAND_HUE_CCW: + { + if (h1 > h2) mode = 2; + else mode = 0; + break; + } + case COLBAND_HUE_CW: + { + if (h1 < h2) mode = 1; + else mode = 0; + break; + } + } + + switch (mode) { + case 0: + h_interp = HUE_INTERP(h1, h2); + break; + case 1: + h_interp = HUE_INTERP(h1 + 1.0f, h2); + h_interp = HUE_MOD(h_interp); + break; + case 2: + h_interp = HUE_INTERP(h1, h2 + 1.0f); + h_interp = HUE_MOD(h_interp); + break; + } + + BLI_assert(h_interp >= 0.0f && h_interp < 1.0f); + +#undef HUE_INTERP +#undef HUE_MOD + + return h_interp; +} + bool do_colorband(const ColorBand *coba, float in, float out[4]) { const CBData *cbd1, *cbd2, *cbd0, *cbd3; - float fac, mfac, t[4]; + float fac; + int ipotype; int a; if (coba == NULL || coba->tot == 0) return 0; cbd1 = coba->data; + + ipotype = (coba->color_mode == COLBAND_BLEND_RGB) ? coba->ipotype : COLBAND_INTERP_LINEAR; + if (coba->tot == 1) { out[0] = cbd1->r; out[1] = cbd1->g; out[2] = cbd1->b; out[3] = cbd1->a; } + else if ((in <= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) { + out[0] = cbd1->r; + out[1] = cbd1->g; + out[2] = cbd1->b; + out[3] = cbd1->a; + } else { - if (in <= cbd1->pos && coba->ipotype < 2) { + CBData left, right; + + /* we're looking for first pos > in */ + for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break; + + if (a == coba->tot) { + cbd2 = cbd1 - 1; + right = *cbd2; + right.pos = 1.0f; + cbd1 = &right; + } + else if (a == 0) { + left = *cbd1; + left.pos = 0.0f; + cbd2 = &left; + } + else { + cbd2 = cbd1 - 1; + } + + if ((in >= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) { out[0] = cbd1->r; out[1] = cbd1->g; out[2] = cbd1->b; out[3] = cbd1->a; } else { - CBData left, right; - - /* we're looking for first pos > in */ - for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break; - - if (a == coba->tot) { - cbd2 = cbd1 - 1; - right = *cbd2; - right.pos = 1.0f; - cbd1 = &right; - } - else if (a == 0) { - left = *cbd1; - left.pos = 0.0f; - cbd2 = &left; + + if (cbd2->pos != cbd1->pos) { + fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos); } else { - cbd2 = cbd1 - 1; + /* was setting to 0.0 in 2.56 & previous, but this + * is incorrect for the last element, see [#26732] */ + fac = (a != coba->tot) ? 0.0f : 1.0f; } - - if (in >= cbd1->pos && coba->ipotype < 2) { - out[0] = cbd1->r; - out[1] = cbd1->g; - out[2] = cbd1->b; - out[3] = cbd1->a; + + if (ipotype == COLBAND_INTERP_CONSTANT) { + /* constant */ + out[0] = cbd2->r; + out[1] = cbd2->g; + out[2] = cbd2->b; + out[3] = cbd2->a; } - else { - - if (cbd2->pos != cbd1->pos) - fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos); + else if (ipotype >= COLBAND_INTERP_B_SPLINE) { + /* ipo from right to left: 3 2 1 0 */ + float t[4]; + + if (a >= coba->tot - 1) cbd0 = cbd1; + else cbd0 = cbd1 + 1; + if (a < 2) cbd3 = cbd2; + else cbd3 = cbd2 - 1; + + CLAMP(fac, 0.0f, 1.0f); + + if (ipotype == COLBAND_INTERP_CARDINAL) { + key_curve_position_weights(fac, t, KEY_CARDINAL); + } else { - /* was setting to 0.0 in 2.56 & previous, but this - * is incorrect for the last element, see [#26732] */ - fac = (a != coba->tot) ? 0.0f : 1.0f; + key_curve_position_weights(fac, t, KEY_BSPLINE); } - - if (coba->ipotype == 4) { - /* constant */ - out[0] = cbd2->r; - out[1] = cbd2->g; - out[2] = cbd2->b; - out[3] = cbd2->a; - return 1; + + out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r; + out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g; + out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b; + out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a; + CLAMP(out[0], 0.0f, 1.0f); + CLAMP(out[1], 0.0f, 1.0f); + CLAMP(out[2], 0.0f, 1.0f); + CLAMP(out[3], 0.0f, 1.0f); + } + else { + float mfac; + + if (ipotype == COLBAND_INTERP_EASE) { + mfac = fac * fac; + fac = 3.0f * mfac - 2.0f * mfac * fac; } - - if (coba->ipotype >= 2) { - /* ipo from right to left: 3 2 1 0 */ - - if (a >= coba->tot - 1) cbd0 = cbd1; - else cbd0 = cbd1 + 1; - if (a < 2) cbd3 = cbd2; - else cbd3 = cbd2 - 1; - - CLAMP(fac, 0.0f, 1.0f); - - if (coba->ipotype == 3) - key_curve_position_weights(fac, t, KEY_CARDINAL); - else - key_curve_position_weights(fac, t, KEY_BSPLINE); - - out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r; - out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g; - out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b; - out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a; - CLAMP(out[0], 0.0f, 1.0f); - CLAMP(out[1], 0.0f, 1.0f); - CLAMP(out[2], 0.0f, 1.0f); - CLAMP(out[3], 0.0f, 1.0f); + + mfac = 1.0f - fac; + + if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSV)) { + float col1[3], col2[3]; + + rgb_to_hsv_v(&cbd1->r, col1); + rgb_to_hsv_v(&cbd2->r, col2); + + out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]); + out[1] = mfac * col1[1] + fac * col2[1]; + out[2] = mfac * col1[2] + fac * col2[2]; + out[3] = mfac * cbd1->a + fac * cbd2->a; + + hsv_to_rgb_v(out, out); + } + else if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSL)) { + float col1[3], col2[3]; + + rgb_to_hsl_v(&cbd1->r, col1); + rgb_to_hsl_v(&cbd2->r, col2); + + out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]); + out[1] = mfac * col1[1] + fac * col2[1]; + out[2] = mfac * col1[2] + fac * col2[2]; + out[3] = mfac * cbd1->a + fac * cbd2->a; + + hsl_to_rgb_v(out, out); } else { - - if (coba->ipotype == 1) { /* EASE */ - mfac = fac * fac; - fac = 3.0f * mfac - 2.0f * mfac * fac; - } - mfac = 1.0f - fac; - + /* COLBAND_BLEND_RGB */ out[0] = mfac * cbd1->r + fac * cbd2->r; out[1] = mfac * cbd1->g + fac * cbd2->g; out[2] = mfac * cbd1->b + fac * cbd2->b; @@ -408,19 +512,18 @@ CBData *colorband_element_add(struct ColorBand *coba, float position) if (coba->tot == MAXCOLORBAND) { return NULL; } - else if (coba->tot > 0) { + else { CBData *xnew; - float col[4]; - - do_colorband(coba, position, col); xnew = &coba->data[coba->tot]; xnew->pos = position; - xnew->r = col[0]; - xnew->g = col[1]; - xnew->b = col[2]; - xnew->a = col[3]; + if (coba->tot != 0) { + do_colorband(coba, position, &xnew->r); + } + else { + zero_v4(&xnew->r); + } } coba->tot++; @@ -474,7 +577,8 @@ void BKE_texture_free(Tex *tex) void default_tex(Tex *tex) { - tex->type = TEX_CLOUDS; + tex->type = TEX_IMAGE; + tex->ima = NULL; tex->stype = 0; tex->flag = TEX_CHECKER_ODD; tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA; @@ -592,7 +696,7 @@ Tex *add_texture(Main *bmain, const char *name) void default_mtex(MTex *mtex) { - mtex->texco = TEXCO_ORCO; + mtex->texco = TEXCO_UV; mtex->mapto = MAP_COL; mtex->object = NULL; mtex->projx = PROJ_X; @@ -705,6 +809,10 @@ MTex *add_mtex_id(ID *id, int slot) MEM_freeN(mtex_ar[slot]); mtex_ar[slot] = NULL; } + else if (GS(id->name) == ID_MA) { + /* Reset this slot's ON/OFF toggle, for materials, when slot was empty. */ + ((Material *)id)->septex &= ~(1 << slot); + } mtex_ar[slot] = add_mtex(); @@ -743,8 +851,7 @@ Tex *localize_texture(Tex *tex) { Tex *texn; - texn = BKE_libblock_copy(&tex->id); - BLI_remlink(&G.main->tex, texn); + texn = BKE_libblock_copy_nolib(&tex->id, false); /* image texture: BKE_texture_free also doesn't decrease */ @@ -1174,8 +1281,11 @@ void set_current_material_texture(Material *ma, Tex *newtex) id_us_min(&tex->id); if (newtex) { - if (!ma->mtex[act]) + if (!ma->mtex[act]) { ma->mtex[act] = add_mtex(); + /* Reset this slot's ON/OFF toggle, for materials, when slot was empty. */ + ma->septex &= ~(1 << act); + } ma->mtex[act]->tex = newtex; id_us_plus(&newtex->id); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 22005892535..40d9dc0d7e0 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -371,6 +371,9 @@ void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingO while (track) { MovieTrackingTrack *new_track = BKE_tracking_track_duplicate(track); + if (track->prev == NULL) { + tracking->act_track = new_track; + } BLI_addtail(tracksbase, new_track); BKE_tracking_track_unique_name(tracksbase, new_track); @@ -1789,13 +1792,19 @@ ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking * if (ibuf->rect_float) { if (undistort) { libmv_cameraIntrinsicsUndistortFloat(distortion->intrinsics, - ibuf->rect_float, resibuf->rect_float, - ibuf->x, ibuf->y, overscan, ibuf->channels); + ibuf->rect_float, + ibuf->x, ibuf->y, + overscan, + ibuf->channels, + resibuf->rect_float); } else { libmv_cameraIntrinsicsDistortFloat(distortion->intrinsics, - ibuf->rect_float, resibuf->rect_float, - ibuf->x, ibuf->y, overscan, ibuf->channels); + ibuf->rect_float, + ibuf->x, ibuf->y, + overscan, + ibuf->channels, + resibuf->rect_float); } if (ibuf->rect) @@ -1804,13 +1813,19 @@ ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking * else { if (undistort) { libmv_cameraIntrinsicsUndistortByte(distortion->intrinsics, - (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, - ibuf->x, ibuf->y, overscan, ibuf->channels); + (unsigned char *)ibuf->rect, + ibuf->x, ibuf->y, + overscan, + ibuf->channels, + (unsigned char *)resibuf->rect); } else { libmv_cameraIntrinsicsDistortByte(distortion->intrinsics, - (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, - ibuf->x, ibuf->y, overscan, ibuf->channels); + (unsigned char *)ibuf->rect, + ibuf->x, ibuf->y, + overscan, + ibuf->channels, + (unsigned char *)resibuf->rect); } } @@ -1891,11 +1906,21 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int cali calibration_height, overscan, false); } -void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2]) +void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, rcti *rect, + bool undistort, float delta[2]) { int a; float pos[2], warped_pos[2]; const int coord_delta = 5; + void (*apply_distortion) (MovieTracking *tracking, + const float pos[2], float out[2]); + + if (undistort) { + apply_distortion = BKE_tracking_undistort_v2; + } + else { + apply_distortion = BKE_tracking_distort_v2; + } delta[0] = delta[1] = -FLT_MAX; @@ -1907,7 +1932,7 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r pos[0] = a; pos[1] = rect->ymin; - BKE_tracking_undistort_v2(tracking, pos, warped_pos); + apply_distortion(tracking, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -1916,7 +1941,7 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r pos[0] = a; pos[1] = rect->ymax; - BKE_tracking_undistort_v2(tracking, pos, warped_pos); + apply_distortion(tracking, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -1933,7 +1958,7 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r pos[0] = rect->xmin; pos[1] = a; - BKE_tracking_undistort_v2(tracking, pos, warped_pos); + apply_distortion(tracking, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -1942,7 +1967,7 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r pos[0] = rect->xmax; pos[1] = a; - BKE_tracking_undistort_v2(tracking, pos, warped_pos); + apply_distortion(tracking, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -2007,14 +2032,14 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea } if (search_ibuf->rect_float) { - libmv_samplePlanarPatch(search_ibuf->rect_float, - search_ibuf->x, search_ibuf->y, 4, - src_pixel_x, src_pixel_y, - num_samples_x, num_samples_y, - mask, - pattern_ibuf->rect_float, - &warped_position_x, - &warped_position_y); + libmv_samplePlanarPatchFloat(search_ibuf->rect_float, + search_ibuf->x, search_ibuf->y, 4, + src_pixel_x, src_pixel_y, + num_samples_x, num_samples_y, + mask, + pattern_ibuf->rect_float, + &warped_position_x, + &warped_position_y); } else { libmv_samplePlanarPatchByte((unsigned char *) search_ibuf->rect, @@ -2175,10 +2200,10 @@ void BKE_tracking_disable_channels(ImBuf *ibuf, bool disable_red, bool disable_g /* ** Channels sort comparators ** */ -static int channels_alpha_sort(void *a, void *b) +static int channels_alpha_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (BLI_strcasecmp(channel_a->track->name, channel_b->track->name) > 0) return 1; @@ -2186,10 +2211,10 @@ static int channels_alpha_sort(void *a, void *b) return 0; } -static int channels_total_track_sort(void *a, void *b) +static int channels_total_track_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (channel_a->total_frames > channel_b->total_frames) return 1; @@ -2197,10 +2222,10 @@ static int channels_total_track_sort(void *a, void *b) return 0; } -static int channels_longest_segment_sort(void *a, void *b) +static int channels_longest_segment_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (channel_a->max_segment > channel_b->max_segment) return 1; @@ -2208,10 +2233,10 @@ static int channels_longest_segment_sort(void *a, void *b) return 0; } -static int channels_average_error_sort(void *a, void *b) +static int channels_average_error_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (channel_a->track->error > channel_b->track->error) return 1; @@ -2219,7 +2244,7 @@ static int channels_average_error_sort(void *a, void *b) return 0; } -static int channels_alpha_inverse_sort(void *a, void *b) +static int channels_alpha_inverse_sort(const void *a, const void *b) { if (channels_alpha_sort(a, b)) return 0; @@ -2227,7 +2252,7 @@ static int channels_alpha_inverse_sort(void *a, void *b) return 1; } -static int channels_total_track_inverse_sort(void *a, void *b) +static int channels_total_track_inverse_sort(const void *a, const void *b) { if (channels_total_track_sort(a, b)) return 0; @@ -2235,7 +2260,7 @@ static int channels_total_track_inverse_sort(void *a, void *b) return 1; } -static int channels_longest_segment_inverse_sort(void *a, void *b) +static int channels_longest_segment_inverse_sort(const void *a, const void *b) { if (channels_longest_segment_sort(a, b)) return 0; @@ -2243,10 +2268,10 @@ static int channels_longest_segment_inverse_sort(void *a, void *b) return 1; } -static int channels_average_error_inverse_sort(void *a, void *b) +static int channels_average_error_inverse_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (channel_a->track->error < channel_b->track->error) return 1; diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c index 76b7ad5d982..c41106f37cb 100644 --- a/source/blender/blenkernel/intern/tracking_region_tracker.c +++ b/source/blender/blenkernel/intern/tracking_region_tracker.c @@ -501,7 +501,7 @@ static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker, static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track, const MovieTrackingMarker *old_marker, int curfra, bool tracked, int frame_width, int frame_height, - double dst_pixel_x[5], double dst_pixel_y[5]) + const double dst_pixel_x[5], const double dst_pixel_y[5]) { MovieTrackingMarker new_marker; int frame_delta = context->backwards ? -1 : 1; @@ -725,6 +725,35 @@ void BKE_tracking_context_finish(MovieTrackingContext *context) } } +static bool refine_marker_reference_frame_get(MovieTrackingTrack *track, + MovieTrackingMarker *marker, + bool backwards, + int *reference_framenr) +{ + const MovieTrackingMarker *first_marker = track->markers; + const MovieTrackingMarker *last_marker = track->markers + track->markersnr - 1; + MovieTrackingMarker *reference = backwards ? marker + 1 : marker - 1; + + while (reference >= first_marker && + reference <= last_marker && + (reference->flag & MARKER_DISABLED) != 0) + { + if (backwards) + reference++; + else + reference--; + } + + if (reference < first_marker || + reference > last_marker) + { + return false; + } + + *reference_framenr = reference->framenr; + return (reference->flag & MARKER_DISABLED) == 0; +} + /* Refine marker's position using previously known keyframe. * Direction of searching for a keyframe depends on backwards flag, * which means if backwards is false, previous keyframe will be as @@ -748,14 +777,15 @@ void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, Movi BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height); - /* Get an image buffer for reference frame, also gets reference marker. - * - * Usually tracking_context_get_reference_ibuf will return current frame - * if marker is keyframed, which is correct for normal tracking. But here - * we'll want to have next/previous frame in such cases. So let's use small - * magic with original frame number used to get reference frame for. - */ - reference_framenr = backwards ? marker->framenr + 1 : marker->framenr - 1; + /* Get an image buffer for reference frame, also gets reference marker. */ + if (!refine_marker_reference_frame_get(track, + marker, + backwards, + &reference_framenr)) + { + return; + } + reference_ibuf = tracking_context_get_reference_ibuf(clip, &user, clip_flag, track, reference_framenr, backwards, &reference_marker); if (reference_ibuf == NULL) { diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index 8cdb547612c..eb224020977 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -82,7 +82,7 @@ static bool stabilization_median_point_get(MovieTracking *tracking, int framenr, * NOTE: frame number should be in clip space, not scene space */ static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height, - float firstmedian[2], float median[2], + const float firstmedian[2], const float median[2], float translation[2], float *scale, float *angle) { MovieTrackingStabilization *stab = &tracking->stabilization; @@ -155,7 +155,7 @@ static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, i } /* For every frame we calculate scale factor needed to eliminate black - * aread and choose largest scale factor as final one. + * area and choose largest scale factor as final one. */ for (cfra = sfra; cfra <= efra; cfra++) { float median[2]; @@ -439,6 +439,6 @@ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ - mul_serie_m4(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat, - scale_mat, inv_center_mat, NULL); + mul_m4_series(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat, + scale_mat, inv_center_mat); } diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 4ebe8494101..0a8293630c7 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/blenkernel/tracking_util.c +/** \file blender/blenkernel/intern/tracking_util.c * \ingroup bke * * This file contains implementation of function which are used diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c index fb55e3d2137..866502c4ae1 100644 --- a/source/blender/blenkernel/intern/treehash.c +++ b/source/blender/blenkernel/intern/treehash.c @@ -59,7 +59,7 @@ static TseGroup *tse_group_create(void) static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem) { - if (tse_group->size == tse_group->allocated) { + if (UNLIKELY(tse_group->size == tse_group->allocated)) { tse_group->allocated *= 2; tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated); } @@ -91,7 +91,7 @@ static unsigned int tse_hash(const void *ptr) return hash.u_int; } -static int tse_cmp(const void *a, const void *b) +static bool tse_cmp(const void *a, const void *b) { const TreeStoreElem *tse_a = a; const TreeStoreElem *tse_b = b; diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index de6424f3145..5a2c77b5619 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -41,6 +41,8 @@ # include "BLI_winstuff.h" #endif +/* no BKE or DNA includes! */ + #define TEMP_STR_SIZE 256 #define SEP_CHR '#' @@ -349,7 +351,7 @@ static void unit_dual_convert(double value, bUnitCollection *usys, bUnitDef **un static size_t unit_as_string(char *str, int len_max, double value, int prec, bUnitCollection *usys, /* non exposed options */ - bUnitDef *unit, char pad) + const bUnitDef *unit, char pad) { double value_conv; size_t len, i; @@ -456,7 +458,7 @@ size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system return unit_as_string(str, len_max, value, prec, usys, NULL, pad ? ' ' : '\0'); } -BLI_INLINE int isalpha_or_utf8(const int ch) +BLI_INLINE bool isalpha_or_utf8(const int ch) { return (ch >= 128 || isalpha(ch)); } @@ -493,11 +495,11 @@ static const char *unit_find_str(const char *str, const char *substr) * * "1m1cm+2mm" - Original value * "1*1#1*0.01#+2*0.001#" - Replace numbers - * "1*1,1*0.01 +2*0.001 " - Add comma's if ( - + * / % ^ < > ) not found in between + * "1*1+1*0.01 +2*0.001 " - Add add signs if ( + - * / | & ~ < > ^ ! = % ) not found in between * */ -/* not too strict, (- = * /) are most common */ +/* not too strict, (+ - * /) are most common */ static bool ch_is_op(char op) { switch (op) { @@ -514,9 +516,11 @@ static bool ch_is_op(char op) case '!': case '=': case '%': - return 1; + return true; + break; default: - return 0; + return false; + break; } } @@ -536,7 +540,7 @@ static int unit_scale_str(char *str, int len_max, char *str_tmp, double scale_pr len_name = strlen(replace_str); len_move = (len - (found_ofs + len_name)) + 1; /* 1+ to copy the string terminator */ - len_num = BLI_snprintf(str_tmp, TEMP_STR_SIZE, "*%g"SEP_STR, unit->scalar / scale_pref); /* # removed later */ + len_num = BLI_snprintf(str_tmp, TEMP_STR_SIZE, "*%.9g"SEP_STR, unit->scalar / scale_pref); /* # removed later */ if (len_num > len_max) len_num = len_max; @@ -579,14 +583,42 @@ static int unit_replace(char *str, int len_max, char *str_tmp, double scale_pref return ofs; } -static int unit_find(const char *str, bUnitDef *unit) +static bool unit_find(const char *str, bUnitDef *unit) { - if (unit_find_str(str, unit->name_short)) return 1; - if (unit_find_str(str, unit->name_plural)) return 1; - if (unit_find_str(str, unit->name_alt)) return 1; - if (unit_find_str(str, unit->name)) return 1; + if (unit_find_str(str, unit->name_short)) return true; + if (unit_find_str(str, unit->name_plural)) return true; + if (unit_find_str(str, unit->name_alt)) return true; + if (unit_find_str(str, unit->name)) return true; - return 0; + return false; +} + +static bUnitDef *unit_detect_from_str(bUnitCollection *usys, const char *str, const char *str_prev) +{ + /* Try to find a default unit from current or previous string. + * This allows us to handle cases like 2 + 2mm, people would expect to get 4mm, not 2.002m! + * Note this does not handle corner cases like 2 + 2cm + 1 + 2.5mm... We can't support everything. */ + bUnitDef *unit = NULL; + + /* see which units the new value has */ + for (unit = usys->units; unit->name; unit++) { + if (unit_find(str, unit)) + break; + } + /* Else, try to infer the default unit from the previous string. */ + if (str_prev && (unit == NULL || unit->name == NULL)) { + /* see which units the original value had */ + for (unit = usys->units; unit->name; unit++) { + if (unit_find(str_prev, unit)) + break; + } + } + /* Else, fall back to default unit. */ + if (unit == NULL || unit->name == NULL) { + unit = unit_default(usys); + } + + return unit; } /* make a copy of the string that replaces the units with numbers @@ -597,37 +629,58 @@ static int unit_find(const char *str, bUnitDef *unit) * 10.1km -> 10.1*1000.0 * ...will be resolved by python. * - * values will be split by a comma's - * 5'2" -> 5'0.0254, 2*0.3048 + * values will be split by an add sign + * 5'2" -> 5*0.3048 + 2*0.0254 * * str_prev is optional, when valid it is used to get a base unit when none is set. * * return true of a change was made. */ -int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type) +bool bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type) { bUnitCollection *usys = unit_get_system(system, type); - bUnitDef *unit; + bUnitDef *unit = NULL, *default_unit; + double scale_pref_base = scale_pref; char str_tmp[TEMP_STR_SIZE]; - int changed = 0; + bool changed = false; if (usys == NULL || usys->units[0].name == NULL) { - return 0; + return changed; } /* make lowercase */ BLI_ascii_strtolower(str, len_max); + /* Try to find a default unit from current or previous string. */ + default_unit = unit_detect_from_str(usys, str, str_prev); + + /* We apply the default unit to the whole expression (default unit is now the reference '1.0' one). */ + scale_pref_base *= default_unit->scalar; + + /* Apply the default unit on the whole expression, this allows to handle nasty cases like '2+2in'. */ + if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)*%.9g", str, default_unit->scalar) < sizeof(str_tmp)) { + strncpy(str, str_tmp, len_max); + } + else { + /* BLI_snprintf would not fit into str_tmp, cant do much in this case + * check for this because otherwise bUnit_ReplaceString could call its self forever */ + return changed; + } + for (unit = usys->units; unit->name; unit++) { /* in case there are multiple instances */ - while (unit_replace(str, len_max, str_tmp, scale_pref, unit)) + while (unit_replace(str, len_max, str_tmp, scale_pref_base, unit)) changed = true; } unit = NULL; { /* try other unit systems now, so we can evaluate imperial when metric is set for eg. */ + /* Note that checking other systems at that point means we do not support their units as 'default' one. + * In other words, when in metrics, typing '2+2in' will give 2 meters 2 inches, not 4 inches. + * I do think this is the desired behavior! + */ bUnitCollection *usys_iter; int system_iter; @@ -638,7 +691,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca for (unit = usys_iter->units; unit->name; unit++) { int ofs = 0; /* in case there are multiple instances */ - while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref, unit))) + while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref_base, unit))) changed = true; } } @@ -647,35 +700,9 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca } unit = NULL; - if (changed == 0) { - /* no units given so infer a unit from the previous string or default */ - if (str_prev) { - /* see which units the original value had */ - for (unit = usys->units; unit->name; unit++) { - if (unit_find(str_prev, unit)) - break; - } - } - - if (unit == NULL || unit->name == NULL) - unit = unit_default(usys); - - /* add the unit prefix and re-run, use brackets in case there was an expression given */ - if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)%s", str, unit->name) < sizeof(str_tmp)) { - strncpy(str, str_tmp, len_max); - return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type); - } - else { - /* BLI_snprintf would not fit into str_tmp, cant do much in this case - * check for this because otherwise bUnit_ReplaceString could call its self forever */ - return 0; - } - - } - - /* replace # with commas when there is no operator between it and the next number + /* replace # with add sign when there is no operator between it and the next number * - * "1*1# 3*100# * 3" -> "1 *1, 3 *100 * 3" + * "1*1# 3*100# * 3" -> "1*1+ 3*100 * 3" * * */ { @@ -683,25 +710,19 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca const char *ch = str; while ((str_found = strchr(str_found, SEP_CHR))) { + bool op_found = false; - int op_found = 0; - /* any operators after this?*/ + /* any operators after this? */ for (ch = str_found + 1; *ch != '\0'; ch++) { - if (*ch == ' ' || *ch == '\t') { - /* do nothing */ - } - else if (ch_is_op(*ch) || *ch == ',') { /* found an op, no need to insert a ',' */ - op_found = 1; - break; - } - else { /* found a non-op character */ - op_found = 0; - break; + continue; } + op_found = (ch_is_op(*ch) || ELEM(*ch, ',', ')')); + break; } - *str_found++ = op_found ? ' ' : ','; + /* If found an op, comma or closing parenthesis, no need to insert a '+', else we need it. */ + *str_found++ = op_found ? ' ' : '+'; } } @@ -771,7 +792,7 @@ double bUnit_BaseScalar(int system, int type) } /* external access */ -int bUnit_IsValid(int system, int type) +bool bUnit_IsValid(int system, int type) { return !(system < 0 || system > UNIT_SYSTEM_TOT || type < 0 || type > B_UNIT_TYPE_TOT); } diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 5065c3ae04f..8e3c92314e6 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -142,8 +142,7 @@ World *localize_world(World *wrld) World *wrldn; int a; - wrldn = BKE_libblock_copy(&wrld->id); - BLI_remlink(&G.main->world, wrldn); + wrldn = BKE_libblock_copy_nolib(&wrld->id, false); for (a = 0; a < MAX_MTEX; a++) { if (wrld->mtex[a]) { diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index a9f040b8650..aef44993912 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -110,7 +110,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) } #endif #ifdef WITH_FFMPEG - if (ELEM4(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) { + if (ELEM(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) { mh.start_movie = BKE_ffmpeg_start; mh.append_movie = BKE_ffmpeg_append; mh.end_movie = BKE_ffmpeg_end; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index dbceba288c7..739db7b7bdb 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -30,13 +30,6 @@ #include <string.h> #include <stdio.h> -#if defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__) -/* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */ -#if _MSC_VER < 1400 -#include <stdint.h> -#endif -#endif - #include <stdlib.h> #include <libavformat/avformat.h> @@ -105,6 +98,7 @@ static AUD_Device *audio_mixdown_device = 0; static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value); static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float value); +static void ffmpeg_set_expert_options(RenderData *rd); /* Delete a picture buffer */ @@ -422,6 +416,11 @@ static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports) current_frame->data, current_frame->linesize); delete_picture(rgb_frame); } + + current_frame->format = PIX_FMT_BGR32; + current_frame->width = width; + current_frame->height = height; + return current_frame; } @@ -488,6 +487,19 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char void *iter; IDProperty *curr; + /* TODO(sergey): This is actually rather stupid, because changing + * codec settings in render panel would also set expert options. + * + * But we need ti here in order to get rid of deprecated settings + * when opening old files in new blender. + * + * For as long we don't allow editing properties in the interface + * it's all good. bug if we allow editing them, we'll need to + * repace it with some smarter code which would port settings + * from deprecated to new one. + */ + ffmpeg_set_expert_options(rd); + if (!rd->ffcodecdata.properties) { return; } @@ -684,12 +696,12 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex } if (codec->sample_fmts) { - /* check if the prefered sample format for this codec is supported. + /* check if the preferred sample format for this codec is supported. * this is because, depending on the version of libav, and with the whole ffmpeg/libav fork situation, * you have various implementations around. float samples in particular are not always supported. */ const enum AVSampleFormat *p = codec->sample_fmts; - for (; *p!=-1; p++) { + for (; *p != -1; p++) { if (*p == st->codec->sample_fmt) break; } |