diff options
author | Jason Wilkins <Jason.A.Wilkins@gmail.com> | 2012-10-07 15:55:49 +0400 |
---|---|---|
committer | Jason Wilkins <Jason.A.Wilkins@gmail.com> | 2012-10-07 15:55:49 +0400 |
commit | e4c70deee87290363d02942ecbbf39216a3620a8 (patch) | |
tree | b98b5477e6ce7c43e6aafac5cda851c3d95cbfaf /source/blender/blenkernel/intern | |
parent | 39d020da482c8859f1a9229c392145f904973387 (diff) | |
parent | 7748133bf2d0a99f37b2a0b0ce438b6726db36fa (diff) |
Merge w/ trunk: r50097-r51140 (also, I got ahead of myself and fixed a lot of warnings before committing)
Diffstat (limited to 'source/blender/blenkernel/intern')
72 files changed, 3378 insertions, 2761 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 387d4775ad4..82ac0736b07 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -1397,7 +1397,7 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss) return eCCGError_None; } -#define VERT_getNo(e, lvl) _vert_getNo(e, lvl, vertDataSize, normalDataOffset) +#define VERT_getNo(e, lvl) _vert_getNo(v, lvl, vertDataSize, normalDataOffset) #define EDGE_getNo(e, lvl, x) _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset) #define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset) #define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize) @@ -1491,7 +1491,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, /* XXX can I reduce the number of normalisations here? */ for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) { CCGVert *v = (CCGVert *) effectedV[ptrIdx]; - float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset); + float length, *no = VERT_getNo(v, lvl); NormZero(no); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 062a790dc71..5ff1ce2aec3 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -59,6 +59,7 @@ #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_object.h" +#include "BKE_object_deform.h" #include "BKE_paint.h" #include "BKE_texture.h" #include "BKE_multires.h" @@ -382,7 +383,7 @@ void DM_ensure_tessface(DerivedMesh *dm) } } - else if (dm->dirty && DM_DIRTY_TESS_CDLAYERS) { + else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) { BLI_assert(CustomData_has_layer(&dm->faceData, CD_POLYINDEX)); DM_update_tessface_data(dm); } @@ -540,7 +541,7 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob) CustomData_free(&me->pdata, me->totpoly); /* ok, this should now use new CD shapekey data, - * which shouuld be fed through the modifier + * which should be fed through the modifier * stack*/ if (tmp.totvert != me->totvert && !did_shapekeys && me->key) { printf("%s: YEEK! this should be recoded! Shape key loss!: ID '%s'\n", __func__, tmp.id.name); @@ -576,6 +577,13 @@ void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask) CustomData_set_only_copy(&dm->vertData, mask); CustomData_set_only_copy(&dm->edgeData, mask); CustomData_set_only_copy(&dm->faceData, mask); + /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with + * weight paint mode when there are modifiers applied, needs further investigation, + * see replies to r50969, Campbell */ +#if 0 + CustomData_set_only_copy(&dm->loopData, mask); + CustomData_set_only_copy(&dm->polyData, mask); +#endif } void DM_add_vert_layer(DerivedMesh *dm, int type, int alloctype, void *layer) @@ -806,7 +814,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL; if (build_shapekey_layers && me->key && (kb = BLI_findlink(&me->key->block, ob->shapenr - 1))) { - key_to_mesh(kb, me); + BKE_key_convert_to_mesh(kb, me); } if (mti->type == eModifierTypeType_OnlyDeform) { @@ -876,7 +884,7 @@ static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free * by a more flexible customdata system, but not simple */ if (!em) { ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - KeyBlock *kb = key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest); + KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest); if (kb->data) return kb->data; @@ -1014,14 +1022,14 @@ static void calc_weightpaint_vert_color( unsigned char r_col[4], MDeformVert *dv, ColorBand *coba, const int defbase_tot, const int defbase_act, - const char *dg_flags, - const int selected, const int draw_flag) + const char *defbase_sel, const int defbase_sel_tot, + const int draw_flag) { float input = 0.0f; int make_black = FALSE; - if ((selected > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { + if ((defbase_sel_tot > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { int was_a_nonzero = FALSE; unsigned int i; @@ -1030,7 +1038,7 @@ static void calc_weightpaint_vert_color( /* in multipaint, get the average if auto normalize is inactive * get the sum if it is active */ if (dw->def_nr < defbase_tot) { - if (dg_flags[dw->def_nr]) { + if (defbase_sel[dw->def_nr]) { if (dw->weight) { input += dw->weight; was_a_nonzero = TRUE; @@ -1044,7 +1052,7 @@ static void calc_weightpaint_vert_color( make_black = TRUE; } else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) { - input /= selected; /* get the average */ + input /= defbase_sel_tot; /* get the average */ } } else { @@ -1089,14 +1097,21 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, i /* variables for multipaint */ const int defbase_tot = BLI_countlist(&ob->defbase); const int defbase_act = ob->actdef - 1; - char *dg_flags = MEM_mallocN(defbase_tot * sizeof(char), __func__); - const int selected = get_selected_defgroups(ob, dg_flags, defbase_tot); + + int defbase_sel_tot = 0; + char *defbase_sel = NULL; + + if (draw_flag & CALC_WP_MULTIPAINT) { + defbase_sel = BKE_objdef_selected_get(ob, defbase_tot, &defbase_sel_tot); + } for (i = numVerts; i != 0; i--, wc += 4, dv++) { - calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, dg_flags, selected, draw_flag); + calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag); } - MEM_freeN(dg_flags); + if (defbase_sel) { + MEM_freeN(defbase_sel); + } } else { int col_i; @@ -1267,7 +1282,7 @@ static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape } if (!kb) { - kb = add_keyblock(me->key, layer->name); + kb = BKE_keyblock_add(me->key, layer->name); kb->uid = layer->uid; } @@ -1792,7 +1807,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos { finaldm->recalcTessellation(finaldm); } - /* Even if tessellation is not needed, some modifiers migh have modified CD layers + /* Even if tessellation is not needed, some modifiers might have modified CD layers * (like mloopcol or mloopuv), hence we have to update those. */ else if (finaldm->dirty & DM_DIRTY_TESS_CDLAYERS) { /* A tessellation already exists, it should always have a CD_POLYINDEX. */ @@ -2072,7 +2087,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D if ((*final_r)->type != DM_TYPE_EDITBMESH) { DM_ensure_tessface(*final_r); } - if (cage_r) { + if (cage_r && *cage_r) { if ((*cage_r)->type != DM_TYPE_EDITBMESH) { if (*cage_r != *final_r) { DM_ensure_tessface(*cage_r); @@ -3186,4 +3201,25 @@ void DM_debug_print(DerivedMesh *dm) MEM_freeN(str); } +void DM_debug_print_cdlayers(CustomData *data) +{ + int i; + CustomDataLayer *layer; + + printf("{\n"); + + for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) { + + const char *name = CustomData_layertype_name(layer->type); + const int size = CustomData_sizeof(layer->type); + const char *structname; + int structnum; + CustomData_file_write_info(layer->type, &structname, &structnum); + printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n", + name, structname, layer->type, (void *)layer->data, size, (int)(MEM_allocN_len(layer->data) / size)); + } + + printf("}\n"); +} + #endif /* NDEBUG */ diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 6a8ddd8e00a..66df7eccbd0 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -526,18 +526,12 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon) bPose *outPose; bPoseChannel *pchan; ListBase listb; - + if (!src) { *dst = NULL; return; } - if (*dst == src) { - printf("BKE_pose_copy_data source and target are the same\n"); - *dst = NULL; - return; - } - outPose = MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); @@ -545,6 +539,7 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon) outPose->iksolver = src->iksolver; outPose->ikdata = NULL; outPose->ikparam = MEM_dupallocN(src->ikparam); + outPose->avs = src->avs; for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { /* TODO: rename this argument... */ @@ -810,7 +805,7 @@ void framechange_poses_clear_unkeyed(void) /* TODO: proxies may/may not be correctly handled here... (this needs checking) */ for (ob = G.main->object.first; ob; ob = ob->id.next) { /* we only need to do this on objects with a pose */ - if ( (pose = ob->pose) ) { + if ((pose = ob->pose)) { for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone) pchan->bone->flag &= ~BONE_UNKEYED; @@ -1220,475 +1215,3 @@ void what_does_obaction(Object *ob, Object *workob, bPose *pose, bAction *act, c } } -/* ********** NLA with non-poses works with ipo channels ********** */ - -#if 0 // XXX OLD ANIMATION SYSTEM (TO BE REMOVED) - -/* ************************ Blending with NLA *************** */ - -static void blend_pose_strides(bPose *dst, bPose *src, float srcweight, short mode) -{ - float dstweight; - - switch (mode) { - case ACTSTRIPMODE_BLEND: - dstweight = 1.0F - srcweight; - break; - case ACTSTRIPMODE_ADD: - dstweight = 1.0F; - break; - default: - dstweight = 1.0F; - } - - interp_v3_v3v3(dst->stride_offset, dst->stride_offset, src->stride_offset, srcweight); -} - - -/* - * bone matching diagram, strips A and B - * - * .------------------------. - * | A | - * '------------------------' - * . . b2 - * . .-------------v----------. - * . | B . | - * . '------------------------' - * . . . - * . . . - * offset: . 0 . A-B . A-b2+B - * . . . - * - * */ - - -static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src, float srcweight, short mode) -{ - /* matching offset bones */ - /* take dst offset, and put src on on that location */ - - if (strip->offs_bone[0] == 0) - return; - - /* are we also blending with matching bones? */ - if (strip->prev && strip->start >= strip->prev->start) { - bPoseChannel *dpchan = BKE_pose_channel_find_name(dst, strip->offs_bone); - if (dpchan) { - bPoseChannel *spchan = BKE_pose_channel_find_name(src, strip->offs_bone); - if (spchan) { - float vec[3]; - - /* dst->ctime has the internal strip->prev action time */ - /* map this time to nla time */ - - float ctime = get_actionstrip_frame(strip, src->ctime, 1); - - if (ctime > strip->prev->end) { - bActionChannel *achan; - - /* add src to dest, minus the position of src on strip->prev->end */ - - ctime = get_actionstrip_frame(strip, strip->prev->end, 0); - - achan = get_action_channel(strip->act, strip->offs_bone); - if (achan && achan->ipo) { - bPoseChannel pchan; - /* Evaluates and sets the internal ipo value */ - calc_ipo(achan->ipo, ctime); - /* This call also sets the pchan flags */ - execute_action_ipo(achan, &pchan); - - /* store offset that moves src to location of pchan */ - sub_v3_v3v3(vec, dpchan->loc, pchan.loc); - - mul_mat3_m4_v3(dpchan->bone->arm_mat, vec); - } - } - else { - /* store offset that moves src to location of dst */ - - sub_v3_v3v3(vec, dpchan->loc, spchan->loc); - mul_mat3_m4_v3(dpchan->bone->arm_mat, vec); - } - - /* if blending, we only add with factor scrweight */ - mul_v3_fl(vec, srcweight); - - add_v3_v3(dst->cyclic_offset, vec); - } - } - } - - add_v3_v3(dst->cyclic_offset, src->cyclic_offset); -} - -/* added "sizecorr" here, to allow armatures to be scaled and still have striding. - * Only works for uniform scaling. In general I'd advise against scaling armatures ever though! (ton) - */ -static float stridechannel_frame(Object *ob, float sizecorr, bActionStrip *strip, Path *path, float pathdist, float *stride_offset) -{ - bAction *act = strip->act; - const char *name = strip->stridechannel; - bActionChannel *achan = get_action_channel(act, name); - int stride_axis = strip->stride_axis; - - if (achan && achan->ipo) { - IpoCurve *icu = NULL; - float minx = 0.0f, maxx = 0.0f, miny = 0.0f, maxy = 0.0f; - int foundvert = 0; - - if (stride_axis == 0) stride_axis = AC_LOC_X; - else if (stride_axis == 1) stride_axis = AC_LOC_Y; - else stride_axis = AC_LOC_Z; - - /* calculate the min/max */ - for (icu = achan->ipo->curve.first; icu; icu = icu->next) { - if (icu->adrcode == stride_axis) { - if (icu->totvert > 1) { - foundvert = 1; - minx = icu->bezt[0].vec[1][0]; - maxx = icu->bezt[icu->totvert - 1].vec[1][0]; - - miny = icu->bezt[0].vec[1][1]; - maxy = icu->bezt[icu->totvert - 1].vec[1][1]; - } - break; - } - } - - if (foundvert && miny != maxy) { - float stridelen = sizecorr * fabs(maxy - miny), striptime; - float actiondist, pdist, pdistNewNormalized, offs; - float vec1[4], vec2[4], dir[3]; - - /* internal cycling, actoffs is in frames */ - offs = stridelen * strip->actoffs / (maxx - minx); - - /* amount path moves object */ - pdist = (float)fmod(pathdist + offs, stridelen); - striptime = pdist / stridelen; - - /* amount stride bone moves */ - actiondist = sizecorr * eval_icu(icu, minx + striptime * (maxx - minx)) - miny; - - pdist = fabs(actiondist) - pdist; - pdistNewNormalized = (pathdist + pdist) / path->totdist; - - /* now we need to go pdist further (or less) on cu path */ - where_on_path(ob, (pathdist) / path->totdist, vec1, dir); /* vec needs size 4 */ - if (pdistNewNormalized <= 1) { - /* search for correction in positive path-direction */ - where_on_path(ob, pdistNewNormalized, vec2, dir); /* vec needs size 4 */ - sub_v3_v3v3(stride_offset, vec2, vec1); - } - else { - /* we reached the end of the path, search backwards instead */ - where_on_path(ob, (pathdist - pdist) / path->totdist, vec2, dir); /* vec needs size 4 */ - sub_v3_v3v3(stride_offset, vec1, vec2); - } - mul_mat3_m4_v3(ob->obmat, stride_offset); - return striptime; - } - } - return 0.0f; -} - -static void cyclic_offs_bone(Object *ob, bPose *pose, bActionStrip *strip, float time) -{ - /* only called when strip has cyclic, so >= 1.0f works... */ - if (time >= 1.0f) { - bActionChannel *achan = get_action_channel(strip->act, strip->offs_bone); - - if (achan && achan->ipo) { - IpoCurve *icu = NULL; - Bone *bone; - float min[3] = {0.0f, 0.0f, 0.0f}, max[3] = {0.0f, 0.0f, 0.0f}; - int index = 0, foundvert = 0; - - /* calculate the min/max */ - for (icu = achan->ipo->curve.first; icu; icu = icu->next) { - if (icu->totvert > 1) { - - if (icu->adrcode == AC_LOC_X) - index = 0; - else if (icu->adrcode == AC_LOC_Y) - index = 1; - else if (icu->adrcode == AC_LOC_Z) - index = 2; - else - continue; - - foundvert = 1; - min[index] = icu->bezt[0].vec[1][1]; - max[index] = icu->bezt[icu->totvert - 1].vec[1][1]; - } - } - if (foundvert) { - /* bring it into armature space */ - sub_v3_v3v3(min, max, min); - bone = BKE_armature_find_bone_name(ob->data, strip->offs_bone); /* weak */ - if (bone) { - mul_mat3_m4_v3(bone->arm_mat, min); - - /* dominant motion, cyclic_offset was cleared in BKE_pose_rest */ - if (strip->flag & (ACTSTRIP_CYCLIC_USEX | ACTSTRIP_CYCLIC_USEY | ACTSTRIP_CYCLIC_USEZ)) { - if (strip->flag & ACTSTRIP_CYCLIC_USEX) pose->cyclic_offset[0] = time * min[0]; - if (strip->flag & ACTSTRIP_CYCLIC_USEY) pose->cyclic_offset[1] = time * min[1]; - if (strip->flag & ACTSTRIP_CYCLIC_USEZ) pose->cyclic_offset[2] = time * min[2]; - } - else { - if (fabsf(min[0]) >= fabsf(min[1]) && fabsf(min[0]) >= fabsf(min[2])) - pose->cyclic_offset[0] = time * min[0]; - else if (fabsf(min[1]) >= fabsf(min[0]) && fabsf(min[1]) >= fabsf(min[2])) - pose->cyclic_offset[1] = time * min[1]; - else - pose->cyclic_offset[2] = time * min[2]; - } - } - } - } - } -} - -/* simple case for now; only the curve path with constraint value > 0.5 */ -/* blending we might do later... */ -static Object *get_parent_path(Object *ob) -{ - bConstraint *con; - - if (ob->parent && ob->parent->type == OB_CURVE) - return ob->parent; - - for (con = ob->constraints.first; con; con = con->next) { - if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) { - if (con->enforce > 0.5f) { - bFollowPathConstraint *data = con->data; - return data->tar; - } - } - } - return NULL; -} - -/* ************** do the action ************ */ - -/* ----- nla, etc. --------- */ - -static void do_nla(Scene *scene, Object *ob, int blocktype) -{ - bPose *tpose = NULL; - Key *key = NULL; - ListBase tchanbase = {NULL, NULL}, chanbase = {NULL, NULL}; - bActionStrip *strip, *striplast = NULL, *stripfirst = NULL; - float striptime, frametime, length, actlength; - float blendfac, stripframe; - float scene_cfra = BKE_scene_frame_get(scene); - int doit, dostride; - - if (blocktype == ID_AR) { - BKE_pose_copy_data(&tpose, ob->pose, 1); - BKE_pose_rest(ob->pose); // potentially destroying current not-keyed pose - } - else { - key = ob_get_key(ob); - } - - /* check on extend to left or right, when no strip is hit by 'cfra' */ - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - /* escape loop on a hit */ - if (scene_cfra >= strip->start && scene_cfra <= strip->end + 0.1f) /* note 0.1 comes back below */ - break; - if (scene_cfra < strip->start) { - if (stripfirst == NULL) - stripfirst = strip; - else if (stripfirst->start > strip->start) - stripfirst = strip; - } - else if (scene_cfra > strip->end) { - if (striplast == NULL) - striplast = strip; - else if (striplast->end < strip->end) - striplast = strip; - } - } - if (strip == NULL) { /* extend */ - if (striplast) - scene_cfra = striplast->end; - else if (stripfirst) - scene_cfra = stripfirst->start; - } - - /* and now go over all strips */ - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - doit = dostride = 0; - - if (strip->act && !(strip->flag & ACTSTRIP_MUTE)) { /* so theres an action */ - - /* Determine if the current frame is within the strip's range */ - length = strip->end - strip->start; - actlength = strip->actend - strip->actstart; - striptime = (scene_cfra - strip->start) / length; - stripframe = (scene_cfra - strip->start); - - if (striptime >= 0.0) { - - if (blocktype == ID_AR) - BKE_pose_rest(tpose); - - /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */ - if (striptime < 1.0f + 0.1f / length) { - - /* Handle path */ - if ((strip->flag & ACTSTRIP_USESTRIDE) && (blocktype == ID_AR) && (ob->ipoflag & OB_DISABLE_PATH) == 0) { - Object *parent = get_parent_path(ob); - - if (parent) { - Curve *cu = parent->data; - float ctime, pdist; - - if (cu->flag & CU_PATH) { - /* Ensure we have a valid path */ - if (cu->path == NULL || cu->path->data == NULL) makeDispListCurveTypes(scene, parent, 0); - if (cu->path) { - - /* Find the position on the path */ - ctime = bsystem_time(scene, ob, scene_cfra, 0.0); - - if (calc_ipo_spec(cu->ipo, CU_SPEED, &ctime) == 0) { - /* correct for actions not starting on zero */ - ctime = (ctime - strip->actstart) / cu->pathlen; - CLAMP(ctime, 0.0, 1.0); - } - pdist = ctime * cu->path->totdist; - - if (tpose && strip->stridechannel[0]) { - striptime = stridechannel_frame(parent, ob->size[0], strip, cu->path, pdist, tpose->stride_offset); - } - else { - if (strip->stridelen) { - striptime = pdist / strip->stridelen; - striptime = (float)fmod(striptime + strip->actoffs, 1.0); - } - else - striptime = 0; - } - - frametime = (striptime * actlength) + strip->actstart; - frametime = bsystem_time(scene, ob, frametime, 0.0); - - if (blocktype == ID_AR) { - extract_pose_from_action(tpose, strip->act, frametime); - } - else if (blocktype == ID_OB) { - extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); - if (key) - extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); - } - doit = dostride = 1; - } - } - } - } - /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */ - else { - - /* Mod to repeat */ - if (strip->repeat != 1.0f) { - float cycle = striptime * strip->repeat; - - striptime = (float)fmod(cycle, 1.0f + 0.1f / length); - cycle -= striptime; - - if (blocktype == ID_AR) - cyclic_offs_bone(ob, tpose, strip, cycle); - } - - frametime = (striptime * actlength) + strip->actstart; - frametime = nla_time(scene, frametime, (float)strip->repeat); - - if (blocktype == ID_AR) { - extract_pose_from_action(tpose, strip->act, frametime); - } - else if (blocktype == ID_OB) { - extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); - if (key) - extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); - } - - doit = 1; - } - } - /* Handle extend */ - else { - if (strip->flag & ACTSTRIP_HOLDLASTFRAME) { - /* we want the strip to hold on the exact fraction of the repeat value */ - - frametime = actlength * (strip->repeat - (int)strip->repeat); - if (frametime <= 0.000001f) frametime = actlength; /* rounding errors... */ - frametime = bsystem_time(scene, ob, frametime + strip->actstart, 0.0); - - if (blocktype == ID_AR) - extract_pose_from_action(tpose, strip->act, frametime); - else if (blocktype == ID_OB) { - extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); - if (key) - extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); - } - - /* handle cycle hold */ - if (strip->repeat != 1.0f) { - if (blocktype == ID_AR) - cyclic_offs_bone(ob, tpose, strip, strip->repeat - 1.0f); - } - - doit = 1; - } - } - - /* Handle blendin & blendout */ - if (doit) { - /* Handle blendin */ - - if (strip->blendin > 0.0 && stripframe <= strip->blendin && scene_cfra >= strip->start) { - blendfac = stripframe / strip->blendin; - } - else if (strip->blendout > 0.0 && stripframe >= (length - strip->blendout) && scene_cfra <= strip->end) { - blendfac = (length - stripframe) / (strip->blendout); - } - else - blendfac = 1; - - if (blocktype == ID_AR) { /* Blend this pose with the accumulated pose */ - /* offset bone, for matching cycles */ - blend_pose_offset_bone(strip, ob->pose, tpose, blendfac, strip->mode); - - blend_poses(ob->pose, tpose, blendfac, strip->mode); - if (dostride) - blend_pose_strides(ob->pose, tpose, blendfac, strip->mode); - } - else { - blend_ipochannels(&chanbase, &tchanbase, blendfac, strip->mode); - BLI_freelistN(&tchanbase); - } - } - } - } - } - - if (blocktype == ID_OB) { - execute_ipochannels(&chanbase); - } - else if (blocktype == ID_AR) { - /* apply stride offset to object */ - add_v3_v3(ob->obmat[3], ob->pose->stride_offset); - } - - /* free */ - if (tpose) - BKE_pose_free(tpose); - if (chanbase.first) - BLI_freelistN(&chanbase); -} - -#endif // XXX OLD ANIMATION SYSTEM (TO BE REMOVED) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 33cdede6fce..58d20fff2bc 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -63,7 +63,6 @@ #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_scene.h" -#include "BKE_utildefines.h" #include "BKE_tessmesh.h" #include "BKE_depsgraph.h" #include "BKE_anim.h" @@ -75,7 +74,8 @@ /* --------------------- */ /* forward declarations */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated); +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, + int level, short flag); /* ******************************************************************** */ /* Animation Visualization */ @@ -282,7 +282,7 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets) /* ........ */ -/* Note on evaluation optimisations: +/* Note on evaluation optimizations: * Optimisations currently used here play tricks with the depsgraph in order to try and * evaluate as few objects as strictly necessary to get nicer performance under standard * production conditions. For those people who really need the accurate version, @@ -323,7 +323,7 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) /* update scene for current frame */ static void motionpaths_calc_update_scene(Scene *scene) { -#if 1 // 'production' optimisations always on +#if 1 // 'production' optimizations always on Base *base, *last = NULL; /* only stuff that moves or needs display still */ @@ -431,7 +431,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) if (efra <= sfra) return; /* optimize the depsgraph for faster updates */ - /* TODO: whether this is used should depend on some setting for the level of optimisations used */ + /* TODO: whether this is used should depend on some setting for the level of optimizations used */ motionpaths_calc_optimise_depsgraph(scene, targets); /* calculate path over requested range */ @@ -494,36 +494,42 @@ void calc_curvepath(Object *ob) /* in a path vertices are with equal differences: path->len = number of verts */ /* NOW WITH BEVELCURVE!!! */ - if (ob == NULL || ob->type != OB_CURVE) return; + if (ob == NULL || ob->type != OB_CURVE) { + return; + } cu = ob->data; - nurbs = BKE_curve_nurbs_get(cu); - nu = nurbs->first; - if (cu->path) free_path(cu->path); cu->path = NULL; + /* weak! can only use first curve */ bl = cu->bev.first; - if (bl == NULL || !bl->nr) return; + if (bl == NULL || !bl->nr) { + return; + } + + nurbs = BKE_curve_nurbs_get(cu); + nu = nurbs->first; cu->path = path = MEM_callocN(sizeof(Path), "calc_curvepath"); /* if POLY: last vertice != first vertice */ cycl = (bl->poly != -1); - if (cycl) tot = bl->nr; - else tot = bl->nr - 1; + tot = cycl ? bl->nr : bl->nr - 1; path->len = tot + 1; /* exception: vector handle paths and polygon paths should be subdivided at least a factor resolu */ - if (path->len < nu->resolu * SEGMENTSU(nu)) path->len = nu->resolu * SEGMENTSU(nu); + if (path->len < nu->resolu * SEGMENTSU(nu)) { + path->len = nu->resolu * SEGMENTSU(nu); + } dist = (float *)MEM_mallocN((tot + 1) * 4, "calcpathdist"); /* all lengths in *dist */ bevp = bevpfirst = (BevPoint *)(bl + 1); fp = dist; - *fp = 0; + *fp = 0.0f; for (a = 0; a < tot; a++) { fp++; if (cycl && a == tot - 1) @@ -558,19 +564,16 @@ void calc_curvepath(Object *ob) fp++; if (bevp < bevplast) bevp++; bevpn = bevp + 1; - if (bevpn > bevplast) { - if (cycl) bevpn = bevpfirst; - else bevpn = bevplast; + if (UNLIKELY(bevpn > bevplast)) { + bevpn = cycl ? bevpfirst : bevplast; } } - fac1 = *(fp) - *(fp - 1); - fac2 = *(fp) - d; - fac1 = fac2 / fac1; + fac1 = (*(fp) - d) / (*(fp) - *(fp - 1)); fac2 = 1.0f - fac1; - + interp_v3_v3v3(pp->vec, bevp->vec, bevpn->vec, fac2); - pp->vec[3] = fac1 * bevp->alfa + fac2 * bevpn->alfa; + pp->vec[3] = fac1 * bevp->alfa + fac2 * bevpn->alfa; pp->radius = fac1 * bevp->radius + fac2 * bevpn->radius; pp->weight = fac1 * bevp->weight + fac2 * bevpn->weight; interp_qt_qtqt(pp->quat, bevp->quat, bevpn->quat, fac2); @@ -582,18 +585,14 @@ void calc_curvepath(Object *ob) MEM_freeN(dist); } - -/* is this only used internally?*/ -int interval_test(int min, int max, int p1, int cycl) +static int interval_test(const int min, const int max, int p1, const int cycl) { if (cycl) { - if (p1 < min) - p1 = ((p1 - min) % (max - min + 1)) + max + 1; - else if (p1 > max) - p1 = ((p1 - min) % (max - min + 1)) + min; + if (p1 < min) p1 = ((p1 - min) % (max - min + 1)) + max + 1; + else if (p1 > max) p1 = ((p1 - min) % (max - min + 1)) + min; } else { - if (p1 < min) p1 = min; + if (p1 < min) p1 = min; else if (p1 > max) p1 = max; } return p1; @@ -701,7 +700,11 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua /* ******************************************************************** */ /* Dupli-Geometry */ -static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, int animated) +#define DUPLILIST_DO_UPDATE 1 +#define DUPLILIST_FOR_RENDER 2 +#define DUPLILIST_ANIMATED 4 + +static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short flag) { DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject"); @@ -713,13 +716,14 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i dob->index = index; dob->particle_index = par_index; dob->type = type; - dob->animated = (type == OB_DUPLIGROUP) && animated; + dob->animated = (type == OB_DUPLIGROUP) && (flag & DUPLILIST_ANIMATED); ob->lay = lay; return dob; } -static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated) +static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, + int level, short flag) { DupliObject *dob; Group *group; @@ -733,9 +737,16 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (level > MAX_DUPLI_RECUR) return; /* handles animated groups, and */ + /* we need to check update for objects that are not in scene... */ - group_handle_recalc_and_update(scene, ob, group); - animated = animated || group_is_animated(ob, group); + if (flag & DUPLILIST_DO_UPDATE) { + /* note: update is optional because we don't always need object + * transformations to be correct. Also fixes bug [#29616]. */ + group_handle_recalc_and_update(scene, ob, group); + } + + if (group_is_animated(ob, group)) + flag |= DUPLILIST_ANIMATED; for (go = group->gobject.first; go; go = go->next) { /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ @@ -751,7 +762,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } - dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, animated); + dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, flag); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ((dob->origlay & group->layer) == 0 || @@ -766,14 +777,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); - object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated); + object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, flag); copy_m4_m4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated) +static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short flag) { extern int enable_cu_speed; /* object.c */ Object copyob; @@ -821,7 +832,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); - dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, animated); + dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, flag); copy_m4_m4(dob->omat, copyob.obmat); } } @@ -845,7 +856,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind typedef struct VertexDupliData { ID *id; /* scene or group, for recursive loops */ int level; - int animated; + short flag; ListBase *lb; float pmat[4][4]; float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */ @@ -889,7 +900,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], origlay = vdd->ob->lay; - dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->animated); + dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->flag); /* restore the original layer so that each dupli will have proper dob->origlay */ vdd->ob->lay = origlay; @@ -901,12 +912,13 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], float tmpmat[4][4]; copy_m4_m4(tmpmat, vdd->ob->obmat); copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated); + object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->flag); copy_m4_m4(vdd->ob->obmat, tmpmat); } } -static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated) +static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, + int level, short flag) { Object *ob, *ob_iter; Mesh *me = par->data; @@ -926,7 +938,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl /* simple preventing of too deep nested groups */ if (level > MAX_DUPLI_RECUR) return; - em = me->edit_btmesh; + em = BMEdit_FromObject(par); if (em) { dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); @@ -934,7 +946,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl else dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); - if (G.is_rendering) { + if (flag & DUPLILIST_FOR_RENDER) { vdd.orco = (float(*)[3])BKE_mesh_orco_verts_get(par); BKE_mesh_orco_verts_transform(me, vdd.orco, me->totvert, 0); } @@ -984,7 +996,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl vdd.id = id; vdd.level = level; - vdd.animated = animated; + vdd.flag = flag; vdd.lb = lb; vdd.ob = ob; vdd.scene = scene; @@ -1029,7 +1041,8 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl dm->release(dm); } -static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated) +static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, + int level, short flag) { Object *ob, *ob_iter; Base *base = NULL; @@ -1052,7 +1065,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa if (level > MAX_DUPLI_RECUR) return; copy_m4_m4(pmat, par->obmat); - em = me->edit_btmesh; + em = BMEdit_FromObject(par); if (em) { dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); @@ -1066,8 +1079,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa mloop = dm->getLoopArray(dm); mvert = dm->getVertArray(dm); - if (G.is_rendering) { - + if (flag & DUPLILIST_FOR_RENDER) { orco = (float(*)[3])BKE_mesh_orco_verts_get(par); BKE_mesh_orco_verts_transform(me, orco, me->totvert, 0); mloopuv = me->mloopuv; @@ -1130,21 +1142,17 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float *v3; /* float *v4; */ /* UNUSED */ float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4]; + float f_no[3]; MLoop *loopstart = mloop + mp->loopstart; - if (mp->totloop < 3) { - /* highly unlikely but to be safe */ + if (UNLIKELY(mp->totloop < 3)) { continue; } else { + BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mvert, f_no); v1 = mvert[(mv1 = loopstart[0].v)].co; v2 = mvert[(mv2 = loopstart[1].v)].co; v3 = mvert[(mv3 = loopstart[2].v)].co; -#if 0 - if (mp->totloop > 3) { - v4 = mvert[(mv4 = loopstart[3].v)].co; - } -#endif } /* translation */ @@ -1160,12 +1168,12 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_v3_v3(obmat[3], cent); /* rotation */ - tri_to_quat(quat, v1, v2, v3); + tri_to_quat_ex(quat, v1, v2, v3, f_no); quat_to_mat3(mat, quat); /* scale */ if (par->transflag & OB_DUPLIFACES_SCALE) { - float size = BKE_mesh_calc_poly_area(mp, loopstart, mvert, NULL); + float size = BKE_mesh_calc_poly_area(mp, loopstart, mvert, f_no); size = sqrtf(size) * par->dupfacesca; mul_m3_fl(mat, size); } @@ -1176,8 +1184,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_m4_m4(tmat, obmat); mul_m4_m4m3(obmat, tmat, mat); - dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, animated); - if (G.is_rendering) { + dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); + if (flag & DUPLILIST_FOR_RENDER) { w = 1.0f / (float)mp->totloop; if (orco) { @@ -1199,7 +1207,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float tmpmat[4][4]; copy_m4_m4(tmpmat, ob->obmat); copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated); + object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, flag); copy_m4_m4(ob->obmat, tmpmat); } } @@ -1219,7 +1227,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, int level, int animated) +static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, + int level, short flag) { GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; @@ -1302,7 +1311,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p /* gather list of objects or single object */ if (part->ren_as == PART_DRAW_GR) { - group_handle_recalc_and_update(scene, par, part->dup_group); + if (flag & DUPLILIST_DO_UPDATE) { + group_handle_recalc_and_update(scene, par, part->dup_group); + } if (part->draw & PART_DRAW_COUNT_GR) { for (dw = part->dupliweights.first; dw; dw = dw->next) @@ -1443,9 +1454,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else copy_m4_m4(mat, tmat); - dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, animated); + dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); copy_m4_m4(dob->omat, obcopylist[b].obmat); - if (G.is_rendering) + if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } @@ -1469,6 +1480,18 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p quat_to_mat4(obmat, q); obmat[3][3] = 1.0f; + /* add scaling if requested */ + if ((part->draw & PART_DRAW_NO_SCALE_OB) == 0) + mult_m4_m4m4(obmat, obmat, size_mat); + } + else if (part->draw & PART_DRAW_NO_SCALE_OB) { + /* remove scaling */ + float size_mat[4][4], original_size[3]; + + mat4_to_size(original_size, obmat); + size_to_mat4(size_mat, original_size); + invert_m4(size_mat); + mult_m4_m4m4(obmat, obmat, size_mat); } @@ -1491,9 +1514,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); + dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); copy_m4_m4(dob->omat, oldobmat); - if (G.is_rendering) + if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } @@ -1545,7 +1568,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) } -static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, int animated) +static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short flag) { Object *ob, *obar[256] = {NULL}; Curve *cu; @@ -1584,7 +1607,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde copy_m4_m4(obmat, par->obmat); copy_v3_v3(obmat[3], vec); - new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, animated); + new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, flag); } } @@ -1593,7 +1616,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde /* ------------- */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated) +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, + int level, short flag) { if ((ob->transflag & OB_DUPLI) == 0) return; @@ -1613,31 +1637,31 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas if (ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; for (; psys; psys = psys->next) - new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated); + new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, flag); } else if (ob->transflag & OB_DUPLIVERTS) { if (ob->type == OB_MESH) { - vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated); + vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); } else if (ob->type == OB_FONT) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - font_duplilist(duplilist, scene, ob, par_index, level + 1, animated); + font_duplilist(duplilist, scene, ob, par_index, level + 1, flag); } } } else if (ob->transflag & OB_DUPLIFACES) { if (ob->type == OB_MESH) - face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated); + face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); } else if (ob->transflag & OB_DUPLIFRAMES) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - frames_duplilist(duplilist, scene, ob, par_index, level + 1, animated); + frames_duplilist(duplilist, scene, ob, par_index, level + 1, flag); } } else if (ob->transflag & OB_DUPLIGROUP) { DupliObject *dob; - group_duplilist(duplilist, scene, ob, par_index, level + 1, animated); /* now recursive */ + group_duplilist(duplilist, scene, ob, par_index, level + 1, flag); /* now recursive */ if (level == 0) { for (dob = duplilist->first; dob; dob = dob->next) @@ -1649,14 +1673,27 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas /* Returns a list of DupliObject * note; group dupli's already set transform matrix. see note in group_duplilist() */ -ListBase *object_duplilist(Scene *sce, Object *ob) +ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render) { ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist"); + int flag = 0; + + if(update) flag |= DUPLILIST_DO_UPDATE; + if(for_render) flag |= DUPLILIST_FOR_RENDER; + duplilist->first = duplilist->last = NULL; - object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0); + object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, flag); return duplilist; } +/* note: previously updating was always done, this is why it defaults to be on + * but there are likely places it can be called without updating */ +ListBase *object_duplilist(Scene *sce, Object *ob, int for_render) +{ + return object_duplilist_ex(sce, ob, TRUE, for_render); +} + + void free_object_duplilist(ListBase *lb) { DupliObject *dob; diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 8e8c98a38e4..5dae2035ab0 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -59,7 +59,6 @@ #include "BKE_main.h" #include "BKE_library.h" #include "BKE_report.h" -#include "BKE_utildefines.h" #include "RNA_access.h" @@ -621,15 +620,30 @@ static char *rna_path_rename_fix(ID *owner_id, const char *prefix, const char *o } /* Check RNA-Paths for a list of F-Curves */ -static void fcurves_path_rename_fix(ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths) +static void fcurves_path_rename_fix(ID *owner_id, const char *prefix, const char *oldName, const char *newName, + const char *oldKey, const char *newKey, ListBase *curves, int verify_paths) { FCurve *fcu; /* we need to check every curve... */ for (fcu = curves->first; fcu; fcu = fcu->next) { - /* firstly, handle the F-Curve's own path */ - if (fcu->rna_path) - fcu->rna_path = rna_path_rename_fix(owner_id, prefix, oldName, newName, fcu->rna_path, verify_paths); + if (fcu->rna_path) { + char *old_path = fcu->rna_path; + + /* firstly, handle the F-Curve's own path */ + fcu->rna_path = rna_path_rename_fix(owner_id, prefix, oldKey, newKey, fcu->rna_path, verify_paths); + + /* if path changed and the F-Curve is grouped, check if its group also needs renaming + * (i.e. F-Curve is first of a bone's F-Curves; hence renaming this should also trigger rename) + */ + if (fcu->rna_path != old_path) { + bActionGroup *agrp = fcu->grp; + + if ((agrp) && strcmp(oldName, agrp->name) == 0) { + BLI_strncpy(agrp->name, newName, sizeof(agrp->name)); + } + } + } } } @@ -675,7 +689,8 @@ static void drivers_path_rename_fix(ID *owner_id, ID *ref_id, const char *prefix } /* Fix all RNA-Paths for Actions linked to NLA Strips */ -static void nlastrips_path_rename_fix(ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths) +static void nlastrips_path_rename_fix(ID *owner_id, const char *prefix, const char *oldName, const char *newName, + const char *oldKey, const char *newKey, ListBase *strips, int verify_paths) { NlaStrip *strip; @@ -683,11 +698,11 @@ static void nlastrips_path_rename_fix(ID *owner_id, const char *prefix, char *ol for (strip = strips->first; strip; strip = strip->next) { /* fix strip's action */ if (strip->act) - fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &strip->act->curves, verify_paths); + fcurves_path_rename_fix(owner_id, prefix, oldName, newName, oldKey, newKey, &strip->act->curves, verify_paths); /* ignore own F-Curves, since those are local... */ /* check sub-strips (if metas) */ - nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, &strip->strips, verify_paths); + nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, oldKey, newKey, &strip->strips, verify_paths); } } @@ -717,16 +732,16 @@ void BKE_animdata_fix_paths_rename(ID *owner_id, AnimData *adt, ID *ref_id, cons /* Active action and temp action */ if (adt->action) - fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->action->curves, verify_paths); + fcurves_path_rename_fix(owner_id, prefix, oldName, newName, oldN, newN, &adt->action->curves, verify_paths); if (adt->tmpact) - fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->tmpact->curves, verify_paths); + fcurves_path_rename_fix(owner_id, prefix, oldName, newName, oldN, newN, &adt->tmpact->curves, verify_paths); /* Drivers - Drivers are really F-Curves */ drivers_path_rename_fix(owner_id, ref_id, prefix, oldName, newName, oldN, newN, &adt->drivers, verify_paths); /* NLA Data - Animation Data for Strips */ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) - nlastrips_path_rename_fix(owner_id, prefix, oldN, newN, &nlt->strips, verify_paths); + nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, oldN, newN, &nlt->strips, verify_paths); /* free the temp names */ MEM_freeN(oldN); @@ -1145,6 +1160,7 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in /* set value - only for animatable numerical values */ if (RNA_property_animateable(&new_ptr, prop)) { int array_len = RNA_property_array_length(&new_ptr, prop); + int written = FALSE; if (array_len && array_index >= array_len) { if (G.debug & G_DEBUG) { @@ -1158,25 +1174,52 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in switch (RNA_property_type(prop)) { case PROP_BOOLEAN: - if (array_len) - RNA_property_boolean_set_index(&new_ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value)); - else - RNA_property_boolean_set(&new_ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value)); + if (array_len) { + if (RNA_property_boolean_get_index(&new_ptr, prop, array_index) != ANIMSYS_FLOAT_AS_BOOL(value)) { + RNA_property_boolean_set_index(&new_ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value)); + written = TRUE; + } + } + else { + if (RNA_property_boolean_get(&new_ptr, prop) != ANIMSYS_FLOAT_AS_BOOL(value)) { + RNA_property_boolean_set(&new_ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value)); + written = TRUE; + } + } break; case PROP_INT: - if (array_len) - RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); - else - RNA_property_int_set(&new_ptr, prop, (int)value); + if (array_len) { + if (RNA_property_int_get_index(&new_ptr, prop, array_index) != (int)value) { + RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); + written = TRUE; + } + } + else { + if (RNA_property_int_get(&new_ptr, prop) != (int)value) { + RNA_property_int_set(&new_ptr, prop, (int)value); + written = TRUE; + } + } break; case PROP_FLOAT: - if (array_len) - RNA_property_float_set_index(&new_ptr, prop, array_index, value); - else - RNA_property_float_set(&new_ptr, prop, value); + if (array_len) { + if (RNA_property_float_get_index(&new_ptr, prop, array_index) != value) { + RNA_property_float_set_index(&new_ptr, prop, array_index, value); + written = TRUE; + } + } + else { + if (RNA_property_float_get(&new_ptr, prop) != value) { + RNA_property_float_set(&new_ptr, prop, value); + written = TRUE; + } + } break; case PROP_ENUM: - RNA_property_enum_set(&new_ptr, prop, (int)value); + if (RNA_property_enum_get(&new_ptr, prop) != (int)value) { + RNA_property_enum_set(&new_ptr, prop, (int)value); + written = TRUE; + } break; default: /* nothing can be done here... so it is unsuccessful? */ @@ -1186,7 +1229,7 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in /* RNA property update disabled for now - [#28525] [#28690] [#28774] [#28777] */ #if 0 /* buffer property update for later flushing */ - if (RNA_property_update_check(prop)) { + if (written && RNA_property_update_check(prop)) { short skip_updates_hack = 0; /* optimization hacks: skip property updates for those properties @@ -1206,7 +1249,7 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in /* as long as we don't do property update, we still tag datablock * as having been updated. this flag does not cause any updates to * be run, it's for e.g. render engines to synchronize data */ - if (new_ptr.id.data) { + if (written && new_ptr.id.data) { ID *id = new_ptr.id.data; id->flag |= LIB_ID_RECALC; DAG_id_type_tag(G.main, GS(id->name)); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 79ee0e96450..b87342f85fa 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1463,7 +1463,7 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[][3]) * * was 0.0000000000001, caused bug [#31333], smaller values give unstable * roll when toggling editmode again... - * No good value here, trying 0.000000001 as best compromize. :/ + * No good value here, trying 0.000000001 as best compromise. :/ */ if (dot_v3v3(axis, axis) > 1.0e-9f) { /* if nor is *not* a multiple of target ... */ @@ -1551,7 +1551,7 @@ void BKE_armature_where_is(bArmature *arm) static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected) { bPose *pose = ob->pose, *frompose = from->pose; - bPoseChannel *pchan, *pchanp, pchanw; + bPoseChannel *pchan, *pchanp; bConstraint *con; int error = 0; @@ -1587,31 +1587,32 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { pchanp = BKE_pose_channel_find_name(frompose, pchan->name); - + if (UNLIKELY(pchanp == NULL)) { /* happens for proxies that become invalid because of a missing link * for regulat cases it shouldn't happen at all */ } else if (pchan->bone->layer & layer_protected) { ListBase proxylocal_constraints = {NULL, NULL}; - + bPoseChannel pchanw = {NULL}; + /* copy posechannel to temp, but restore important pointers */ pchanw = *pchanp; pchanw.prev = pchan->prev; pchanw.next = pchan->next; pchanw.parent = pchan->parent; pchanw.child = pchan->child; - + /* this is freed so copy a copy, else undo crashes */ if (pchanw.prop) { pchanw.prop = IDP_CopyProperty(pchanw.prop); - + /* use the values from the the existing props */ if (pchan->prop) { IDP_SyncGroupValues(pchanw.prop, pchan->prop); } } - + /* constraints - proxy constraints are flushed... local ones are added after * 1. extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints * 2. copy proxy-pchan's constraints on-to new @@ -1622,30 +1623,30 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints); copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE); BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints); - + /* constraints - set target ob pointer to own object */ for (con = pchanw.constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; - + if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); - + for (ct = targets.first; ct; ct = ct->next) { if (ct->tar == from) ct->tar = ob; } - + if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 0); } } - + /* free stuff from current channel */ BKE_pose_channel_free(pchan); - - /* the final copy */ + + /* copy data in temp back over to the cleaned-out (but still allocated) original channel */ *pchan = pchanw; } else { @@ -2516,36 +2517,6 @@ void BKE_pose_where_is(Scene *scene, Object *ob) } } - -/* Returns total selected vgroups, - * wpi.defbase_sel is assumed malloc'd, all values are set */ -int get_selected_defgroups(Object *ob, char *dg_selection, int defbase_tot) -{ - bDeformGroup *defgroup; - unsigned int i; - Object *armob = BKE_object_pose_armature_get(ob); - int dg_flags_sel_tot = 0; - - if (armob) { - bPose *pose = armob->pose; - for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { - bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name); - if (pchan && (pchan->bone->flag & BONE_SELECTED)) { - dg_selection[i] = TRUE; - dg_flags_sel_tot++; - } - else { - dg_selection[i] = FALSE; - } - } - } - else { - memset(dg_selection, FALSE, sizeof(char) * defbase_tot); - } - - return dg_flags_sel_tot; -} - /************** Bounding box ********************/ static int minmax_armature(Object *ob, float r_min[3], float r_max[3]) { diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 0b5d0d90c67..99b788e80ce 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -44,7 +44,8 @@ #include <stdio.h> #include <stddef.h> #include <string.h> -#include <fcntl.h> // for open +#include <fcntl.h> /* for open */ +#include <errno.h> #include "MEM_guardedalloc.h" @@ -80,19 +81,18 @@ #include "BKE_sound.h" #include "RE_pipeline.h" - #include "BLO_undofile.h" #include "BLO_readfile.h" #include "BLO_writefile.h" -#include "BKE_utildefines.h" - #include "RNA_access.h" #include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie +#include "IMB_colormanagement.h" + #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif Global G; @@ -219,8 +219,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* no load screens? */ if (mode) { /* comes from readfile.c */ - extern void lib_link_screen_restore(Main *, bScreen *, Scene *); - SWAP(ListBase, G.main->wm, bfd->main->wm); SWAP(ListBase, G.main->screen, bfd->main->screen); SWAP(ListBase, G.main->script, bfd->main->script); @@ -234,7 +232,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath if (curscreen) curscreen->scene = curscene; /* can run in bgmode */ /* clear_global will free G.main, here we can still restore pointers */ - lib_link_screen_restore(bfd->main, curscreen, curscene); + blo_lib_link_screen_restore(bfd->main, curscreen, curscene); } /* free G.main Main database */ @@ -324,7 +322,11 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* baseflags, groups, make depsgraph, etc */ BKE_scene_set_background(G.main, CTX_data_scene(C)); - + + if (mode != 'u') { + IMB_colormanagement_check_file_config(G.main); + } + MEM_freeN(bfd); (void)curscene; /* quiet warning */ @@ -465,11 +467,10 @@ int blender_test_break(void) #define UNDO_DISK 0 -#define MAXUNDONAME 64 typedef struct UndoElem { struct UndoElem *next, *prev; char str[FILE_MAX]; - char name[MAXUNDONAME]; + char name[BKE_UNDO_STR_MAX]; MemFile memfile; uintptr_t undosize; } UndoElem; @@ -515,8 +516,13 @@ void BKE_write_undo(bContext *C, const char *name) int nr /*, success */ /* UNUSED */; UndoElem *uel; - if ( (U.uiflag & USER_GLOBALUNDO) == 0) return; - if (U.undosteps == 0) return; + if ((U.uiflag & USER_GLOBALUNDO) == 0) { + return; + } + + if (U.undosteps == 0) { + return; + } /* remove all undos after (also when curundo == NULL) */ while (undobase.last != curundo) { @@ -717,38 +723,60 @@ void BKE_undo_save_quit(void) { UndoElem *uel; MemFileChunk *chunk; - int file; char str[FILE_MAX]; - - if ( (U.uiflag & USER_GLOBALUNDO) == 0) return; - + const int flag = O_BINARY + O_WRONLY + O_CREAT + O_TRUNC + O_EXCL; + int file; + + if ((U.uiflag & USER_GLOBALUNDO) == 0) { + return; + } + uel = curundo; if (uel == NULL) { - printf("No undo buffer to save recovery file\n"); + fprintf(stderr, "No undo buffer to save recovery file\n"); return; } - + /* no undo state to save */ - if (undobase.first == undobase.last) return; - + if (undobase.first == undobase.last) { + return; + } + + /* save the undo state as quit.blend */ BLI_make_file_string("/", str, BLI_temporary_dir(), "quit.blend"); - file = BLI_open(str, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); + /* first try create the file, if it exists call without 'O_CREAT', + * to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */ + errno = 0; + file = BLI_open(str, flag, 0666); if (file == -1) { - //XXX error("Unable to save %s, check you have permissions", str); + if (errno == EEXIST) { + errno = 0; + file = BLI_open(str, flag & ~O_CREAT, 0666); + } + } + + if (file == -1) { + fprintf(stderr, "Unable to save '%s': %s\n", + str, errno ? strerror(errno) : "Unknown error opening file"); return; } - chunk = uel->memfile.chunks.first; - while (chunk) { - if (write(file, chunk->buf, chunk->size) != chunk->size) break; - chunk = chunk->next; + for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) { + if (write(file, chunk->buf, chunk->size) != chunk->size) { + break; + } } - + close(file); - if (chunk) ; //XXX error("Unable to save %s, internal error", str); - else printf("Saved session recovery to %s\n", str); + if (chunk) { + fprintf(stderr, "Unable to save '%s': %s\n", + str, errno ? strerror(errno) : "Unknown error writing file"); + } + else { + printf("Saved session recovery to '%s'\n", str); + } } /* sets curscene */ diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index 18161bc6fcb..a7d90f09160 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -96,7 +96,7 @@ void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step) ysize = (bytes + (ibuf->x - 1)) / ibuf->x; if (ysize < ibuf->y) { - /* we're first going to copy all data into a liniar buffer. + /* we're first going to copy all data into a linear buffer. * step can be 4 or 1 bytes, and the data is not sequential because * the bitmap was flipped vertically. */ diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index fde95e0767e..ce39eea5ceb 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -529,7 +529,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf unsigned char *dst, crgb[3]; const float alpha = BKE_brush_alpha_get(scene, brush); float brush_rgb[3]; - + imbflag = (flt) ? IB_rectfloat : IB_rect; xoff = -bufsize / 2.0f + 0.5f; yoff = -bufsize / 2.0f + 0.5f; @@ -563,7 +563,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf else { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); mul_v3_v3v3(dstf, rgba, brush_rgb); - dstf[3] = rgba[3] *alpha *BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); + dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } } } @@ -594,7 +594,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf else if (texfall == 2) { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); mul_v3_v3(rgba, brush->rgb); - alpha_f = rgba[3] *alpha *BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); + alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); rgb_float_to_uchar(dst, rgba); @@ -602,7 +602,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf } else { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); - alpha_f = rgba[3] *alpha *BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); + alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); dst[0] = crgb[0]; dst[1] = crgb[1]; diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 12f4a17b9f1..e93c9373107 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -48,7 +48,6 @@ #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_paint.h" -#include "BKE_utildefines.h" #include "BKE_tessmesh.h" #include "BKE_curve.h" diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index b0de7a5ea6c..4241756a109 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -50,36 +50,7 @@ #include "BKE_modifier.h" #include "BKE_pointcache.h" -#ifdef _WIN32 -void tstart( void ) -{} -void tend( void ) -{ -} -double tval( void ) -{ - return 0; -} -#else -#include <sys/time.h> -static struct timeval _tstart, _tend; -static struct timezone tz; -void tstart( void ) -{ - gettimeofday(&_tstart, &tz); -} -void tend(void) -{ - gettimeofday(&_tend, &tz); -} -double tval(void) -{ - double t1, t2; - t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); - t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); - return t2-t1; -} -#endif +// #include "PIL_time.h" /* timing for debug prints */ /* Our available solvers. */ // 255 is the magic reserved number, so NEVER try to put 255 solvers in here! @@ -410,13 +381,13 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul cloth_apply_vgroup ( clmd, result ); cloth_update_springs( clmd ); - tstart(); + // TIMEIT_START(cloth_step) /* call the solver. */ if (solvers [clmd->sim_parms->solver_type].solver) ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors); - tend(); + // TIMEIT_END(cloth_step) pdEndEffectors(&effectors); diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index af9bb971d05..6631afcddaf 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -161,8 +161,6 @@ void bvhtree_update_from_mvert(BVHTree * bvhtree, MFace *faces, int numfaces, MV /*********************************** Collision modifier code end ***********************************/ -#define mySWAP(a, b) do { double tmp = b ; b = a ; a = tmp ; } while (0) - // w3 is not perfect static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 85d28f68034..1bd5786debd 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -49,6 +49,7 @@ #include "BKE_fcurve.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -105,9 +106,18 @@ void curvemapping_free_data(CurveMapping *cumap) int a; for (a = 0; a < CM_TOT; a++) { - if (cumap->cm[a].curve) MEM_freeN(cumap->cm[a].curve); - if (cumap->cm[a].table) MEM_freeN(cumap->cm[a].table); - if (cumap->cm[a].premultable) MEM_freeN(cumap->cm[a].premultable); + if (cumap->cm[a].curve) { + MEM_freeN(cumap->cm[a].curve); + cumap->cm[a].curve = NULL; + } + if (cumap->cm[a].table) { + MEM_freeN(cumap->cm[a].table); + cumap->cm[a].table = NULL; + } + if (cumap->cm[a].premultable) { + MEM_freeN(cumap->cm[a].premultable); + cumap->cm[a].premultable = NULL; + } } } @@ -165,6 +175,7 @@ void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], con } curvemapping_set_black_white_ex(cumap->black, cumap->white, cumap->bwmul); + cumap->changed_timestamp++; } /* ***************** operations on single curve ************* */ @@ -251,7 +262,7 @@ CurveMapPoint *curvemap_insert(CurveMap *cuma, float x, float y) return newcmp; } -void curvemap_reset(CurveMap *cuma, rctf *clipr, int preset, int slope) +void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope) { if (cuma->curve) MEM_freeN(cuma->curve); @@ -470,7 +481,7 @@ static float curvemap_calc_extend(const CurveMap *cuma, float x, const float fir } /* only creates a table for a single channel in CurveMapping */ -static void curvemap_make_table(CurveMap *cuma, rctf *clipr) +static void curvemap_make_table(CurveMap *cuma, const rctf *clipr) { CurveMapPoint *cmp = cuma->curve; BezTriple *bezt; @@ -668,7 +679,7 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles) CurveMap *cuma = cumap->cm + cumap->cur; CurveMapPoint *cmp = cuma->curve; rctf *clipr = &cumap->clipr; - float thresh = 0.01f * (clipr->xmax - clipr->xmin); + float thresh = 0.01f * BLI_rctf_size_x(clipr); float dx = 0.0f, dy = 0.0f; int a; @@ -987,7 +998,8 @@ static void save_sample_line(Scopes *scopes, const int idx, const float fx, cons } } -void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short use_color_management) +void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { int i, x, y; float *fp; @@ -999,6 +1011,8 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short int y1 = 0.5f + hist->co[0][1] * ibuf->y; int y2 = 0.5f + hist->co[1][1] * ibuf->y; + struct ColormanageProcessor *cm_processor = NULL; + hist->channels = 3; hist->x_resolution = 256; hist->xmax = 1.0f; @@ -1006,6 +1020,9 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; + if (ibuf->rect_float) + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + /* persistent draw */ hist->flag |= HISTO_FLAG_SAMPLELINE; /* keep drawing the flag after */ @@ -1020,10 +1037,8 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); - if (use_color_management) - linearrgb_to_srgb_v3_v3(rgb, fp); - else - copy_v3_v3(rgb, fp); + copy_v3_v3(rgb, fp); + IMB_colormanagement_processor_apply_v3(cm_processor, rgb); hist->data_luma[i] = rgb_to_luma(rgb); hist->data_r[i] = rgb[0]; @@ -1041,9 +1056,13 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short } } } + + if (cm_processor) + IMB_colormanagement_processor_free(cm_processor); } -void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) +void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { int x, y, c; unsigned int n, nl; @@ -1056,6 +1075,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) int ycc_mode = -1; const short is_float = (ibuf->rect_float != NULL); + struct ColormanageProcessor *cm_processor = NULL; + if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; if (scopes->ok == 1) return; @@ -1125,6 +1146,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) else rc = (unsigned char *)ibuf->rect; + if (ibuf->rect_float) + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + for (y = 0; y < ibuf->y; y++) { if (savedlines < scopes->sample_lines && y >= ((savedlines) * ibuf->y) / (scopes->sample_lines + 1)) { saveline = 1; @@ -1135,11 +1159,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) for (x = 0; x < ibuf->x; x++) { if (is_float) { - if (use_color_management) - linearrgb_to_srgb_v3_v3(rgba, rf); - else - copy_v3_v3(rgba, rf); - rgba[3] = rf[3]; + copy_v4_v4(rgba, rf); + IMB_colormanagement_processor_apply_v4(cm_processor, rgba); } else { for (c = 0; c < 4; c++) @@ -1210,6 +1231,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) MEM_freeN(bin_b); MEM_freeN(bin_a); + if (cm_processor) + IMB_colormanagement_processor_free(cm_processor); + scopes->ok = 1; } @@ -1248,3 +1272,58 @@ void scopes_new(Scopes *scopes) scopes->waveform_3 = NULL; scopes->vecscope = NULL; } + +void BKE_color_managed_display_settings_init(ColorManagedDisplaySettings *settings) +{ + const char *display_name = IMB_colormanagement_display_get_default_name(); + + BLI_strncpy(settings->display_device, display_name, sizeof(settings->display_device)); +} + +void BKE_color_managed_display_settings_copy(ColorManagedDisplaySettings *new_settings, + const ColorManagedDisplaySettings *settings) +{ + BLI_strncpy(new_settings->display_device, settings->display_device, sizeof(new_settings->display_device)); +} + +void BKE_color_managed_view_settings_init(ColorManagedViewSettings *settings) +{ + /* OCIO_TODO: use default view transform here when OCIO is completely integrated + * and proper versioning stuff is added. + * for now use NONE to be compatible with all current files + */ + BLI_strncpy(settings->view_transform, "Default", sizeof(settings->view_transform)); + + settings->gamma = 1.0f; + settings->exposure = 0.0f; +} + +void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings, + const ColorManagedViewSettings *settings) +{ + BLI_strncpy(new_settings->view_transform, settings->view_transform, sizeof(new_settings->view_transform)); + + new_settings->flag = settings->flag; + new_settings->exposure = settings->exposure; + new_settings->gamma = settings->gamma; + + if (settings->curve_mapping) + new_settings->curve_mapping = curvemapping_copy(settings->curve_mapping); +} + +void BKE_color_managed_view_settings_free(ColorManagedViewSettings *settings) +{ + if (settings->curve_mapping) + curvemapping_free(settings->curve_mapping); +} + +void BKE_color_managed_colorspace_settings_init(ColorManagedColorspaceSettings *colorspace_settings) +{ + BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name)); +} + +void BKE_color_managed_colorspace_settings_copy(ColorManagedColorspaceSettings *colorspace_settings, + const ColorManagedColorspaceSettings *settings) +{ + BLI_strncpy(colorspace_settings->name, settings->name, sizeof(colorspace_settings->name)); +} diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 00130dd3583..e3f7ae1b1c7 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -416,8 +416,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[][4] static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[][4]) { DerivedMesh *dm = NULL; - Mesh *me = ob->data; - BMEditMesh *em = me->edit_btmesh; + BMEditMesh *em = BMEdit_FromObject(ob); float vec[3] = {0.0f, 0.0f, 0.0f}; float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3]; float imat[3][3], tmat[3][3]; @@ -1031,7 +1030,6 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar if (VALID_CONS_TARGET(ct)) { float size[3], vec[3]; float totmat[3][3]; - float tmat[4][4]; /* Get size property, since ob->size is only the object's own relative size, not its global one */ mat4_to_size(size, cob->matrix); @@ -1054,9 +1052,8 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar vectomat(vec, ct->matrix[2], (short)data->reserved1, (short)data->reserved2, data->flags, totmat); - - copy_m4_m4(tmat, cob->matrix); - mul_m4_m3m4(cob->matrix, totmat, tmat); + + mul_m4_m3m4(cob->matrix, totmat, cob->matrix); } } @@ -2282,7 +2279,6 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t float totmat[3][3]; float tmpmat[3][3]; float invmat[3][3]; - float tmat[4][4]; float mdet; /* Vector object -> target */ @@ -2510,8 +2506,6 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t totmat[1][0] = tmpmat[1][0]; totmat[1][1] = tmpmat[1][1]; totmat[1][2] = tmpmat[1][2]; totmat[2][0] = tmpmat[2][0]; totmat[2][1] = tmpmat[2][1]; totmat[2][2] = tmpmat[2][2]; - copy_m4_m4(tmat, cob->matrix); - mdet = determinant_m3(totmat[0][0], totmat[0][1], totmat[0][2], totmat[1][0], totmat[1][1], totmat[1][2], totmat[2][0], totmat[2][1], totmat[2][2]); @@ -2520,7 +2514,7 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t } /* apply out transformaton to the object */ - mul_m4_m3m4(cob->matrix, totmat, tmat); + mul_m4_m3m4(cob->matrix, totmat, cob->matrix); } } @@ -2718,7 +2712,6 @@ 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 tmat[4][4]; float dist; /* store scaling before destroying obmat */ @@ -2816,9 +2809,8 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t normalize_v3_v3(totmat[2], zz); break; } /* switch (data->plane) */ - - copy_m4_m4(tmat, cob->matrix); - mul_m4_m3m4(cob->matrix, totmat, tmat); + + mul_m4_m3m4(cob->matrix, totmat, cob->matrix); } } @@ -4062,32 +4054,36 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase copy_v3_v3(cob->matrix[3], disp); } - if (data->depth_ob && data->depth_ob->derivedFinal) { + if (data->depth_ob) { Object *depth_ob = data->depth_ob; - BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; - BVHTreeRayHit hit; - float ray_start[3], ray_end[3], ray_nor[3], imat[4][4]; - int result; + DerivedMesh *target = object_get_derived_final(depth_ob); + if (target) { + BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; + BVHTreeRayHit hit; + float ray_start[3], ray_end[3], ray_nor[3], imat[4][4]; + int result; - invert_m4_m4(imat, depth_ob->obmat); + invert_m4_m4(imat, depth_ob->obmat); - mul_v3_m4v3(ray_start, imat, camob->obmat[3]); - mul_v3_m4v3(ray_end, imat, cob->matrix[3]); + mul_v3_m4v3(ray_start, imat, camob->obmat[3]); + mul_v3_m4v3(ray_end, imat, cob->matrix[3]); - sub_v3_v3v3(ray_nor, ray_end, ray_start); + sub_v3_v3v3(ray_nor, ray_end, ray_start); - bvhtree_from_mesh_faces(&treeData, depth_ob->derivedFinal, 0.0f, 4, 6); + bvhtree_from_mesh_faces(&treeData, target, 0.0f, 4, 6); - hit.dist = FLT_MAX; - hit.index = -1; + hit.dist = FLT_MAX; + hit.index = -1; - result = BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData); + result = BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData); - if (result != -1) { - mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co); - } + if (result != -1) { + mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co); + } - free_bvhtree_from_mesh(&treeData); + free_bvhtree_from_mesh(&treeData); + target->release(target); + } } } } @@ -4292,8 +4288,8 @@ bConstraintTypeInfo *get_constraint_typeinfo(int type) } /* only return for valid types */ - if ( (type >= CONSTRAINT_TYPE_NULL) && - (type < NUM_CONSTRAINT_TYPES) ) + if ((type >= CONSTRAINT_TYPE_NULL) && + (type < NUM_CONSTRAINT_TYPES)) { /* there shouldn't be any segfaults here... */ return constraintsTypeInfo[type]; @@ -4514,7 +4510,7 @@ static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED * since we've got the actual ID block, let's just inline this * code. * - * See ID_NEW(a) in BKE_utildefines.h + * See ID_NEW(a) in DNA_ID.h */ if ((*idpoin) && (*idpoin)->newid) (*idpoin) = (void *)(*idpoin)->newid; diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index e2bb1aaa2c7..0bda3b266b8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -429,6 +429,33 @@ void BKE_curve_texspace_calc(Curve *cu) } } +int BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) +{ + Nurb *nu; + int tot = 0; + + for (nu = nurb->first; nu; nu = nu->next) { + int tot_nu; + if (nu->type == CU_BEZIER) { + tot_nu = nu->pntsu; + if (index - tot < tot_nu) { + copy_v3_v3(r_co, nu->bezt[index - tot].vec[1]); + return TRUE; + } + } + else { + tot_nu = nu->pntsu * nu->pntsv; + if (index - tot < tot_nu) { + copy_v3_v3(r_co, nu->bp[index - tot].vec); + return TRUE; + } + } + tot += tot_nu; + } + + return FALSE; +} + int BKE_nurbList_verts_count(ListBase *nurb) { Nurb *nu; @@ -1165,7 +1192,7 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float static void forward_diff_bezier_cotangent(const float p0[3], const float p1[3], const float p2[3], const float p3[3], float p[3], int it, int stride) { - /* note that these are not purpendicular to the curve + /* note that these are not perpendicular to the curve * they need to be rotated for this, * * This could also be optimized like BKE_curve_forward_diff_bezier */ @@ -2741,7 +2768,7 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n if (skip_align) { /* handles need to be updated during animation and applying stuff like hooks, - * but in such situatios it's quite difficult to distinguish in which order + * but in such situations it's quite difficult to distinguish in which order * align handles should be aligned so skip them for now */ return; } @@ -3047,29 +3074,6 @@ void BKE_nurbList_handles_set(ListBase *editnurb, short code) } } -static void swapdata(void *adr1, void *adr2, int len) -{ - - if (len <= 0) return; - - if (len < 65) { - char adr[64]; - - memcpy(adr, adr1, len); - memcpy(adr1, adr2, len); - memcpy(adr2, adr, len); - } - else { - char *adr; - - adr = (char *)MEM_mallocN(len, "curve swap"); - memcpy(adr, adr1, len); - memcpy(adr1, adr2, len); - memcpy(adr2, adr, len); - MEM_freeN(adr); - } -} - void BKE_nurb_direction_switch(Nurb *nu) { BezTriple *bezt1, *bezt2; @@ -3077,7 +3081,9 @@ void BKE_nurb_direction_switch(Nurb *nu) float *fp1, *fp2, *tempf; int a, b; - if (nu->pntsu == 1 && nu->pntsv == 1) return; + if (nu->pntsu == 1 && nu->pntsv == 1) { + return; + } if (nu->type == CU_BEZIER) { a = nu->pntsu; @@ -3086,19 +3092,22 @@ void BKE_nurb_direction_switch(Nurb *nu) if (a & 1) a += 1; /* if odd, also swap middle content */ a /= 2; while (a > 0) { - if (bezt1 != bezt2) + if (bezt1 != bezt2) { SWAP(BezTriple, *bezt1, *bezt2); + } - swapdata(bezt1->vec[0], bezt1->vec[2], 12); - if (bezt1 != bezt2) - swapdata(bezt2->vec[0], bezt2->vec[2], 12); + swap_v3_v3(bezt1->vec[0], bezt1->vec[2]); + + if (bezt1 != bezt2) { + swap_v3_v3(bezt2->vec[0], bezt2->vec[2]); + } SWAP(char, bezt1->h1, bezt1->h2); - SWAP(short, bezt1->f1, bezt1->f3); + SWAP(char, bezt1->f1, bezt1->f3); if (bezt1 != bezt2) { SWAP(char, bezt2->h1, bezt2->h2); - SWAP(short, bezt2->f1, bezt2->f3); + SWAP(char, bezt2->f1, bezt2->f3); bezt1->alfa = -bezt1->alfa; bezt2->alfa = -bezt2->alfa; } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index b04bd5bc47f..de55751f2ec 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -51,7 +51,6 @@ #include "BLI_mempool.h" #include "BLI_utildefines.h" -#include "BKE_utildefines.h" #include "BKE_customdata.h" #include "BKE_customdata_file.h" #include "BKE_global.h" @@ -72,25 +71,29 @@ typedef struct LayerTypeInfo { const char *structname; /* name of the struct used, for file writing */ int structnum; /* number of structs per element, for file writing */ - /* default layer name. + /** + * default layer name. * note! when NULL this is a way to ensure there is only ever one item * see: CustomData_layertype_is_singleton() */ const char *defaultname; - /* a function to copy count elements of this layer's data + /** + * a function to copy count elements of this layer's data * (deep copy if appropriate) * if NULL, memcpy is used */ void (*copy)(const void *source, void *dest, int count); - /* a function to free any dynamically allocated components of this + /** + * a function to free any dynamically allocated components of this * layer's data (note the data pointer itself should not be freed) * size should be the size of one element of this layer's data (e.g. * LayerTypeInfo.size) */ void (*free)(void *data, int count, int size); - /* a function to interpolate between count source elements of this + /** + * a function to interpolate between count source elements of this * layer's data and store the result in dest * if weights == NULL or sub_weights == NULL, they should default to 1 * @@ -98,18 +101,24 @@ typedef struct LayerTypeInfo { * sub_weights gives the sub-element weights for each element in sources * (there should be (sub element count)^2 weights per element) * count gives the number of elements in sources + * + * \note in some cases \a dest pointer is in \a sources + * so all functions have to take this into account and delay + * applying changes while reading from sources. + * See bug [#32395] - Campbell. */ - void (*interp)(void **sources, float *weights, float *sub_weights, + void (*interp)(void **sources, const float *weights, const float *sub_weights, int count, void *dest); - /* a function to swap the data in corners of the element */ + /** a function to swap the data in corners of the element */ void (*swap)(void *data, const int *corner_indices); - /* a function to set a layer's data to default values. if NULL, the + /** + * a function to set a layer's data to default values. if NULL, the * default is assumed to be all zeros */ void (*set_default)(void *data, int count); - /* functions necessary for geometry collapse*/ + /** functions necessary for geometry collapse */ int (*equal)(void *data1, void *data2); void (*multiply)(void *data, float fac); void (*initminmax)(void *min, void *max); @@ -117,13 +126,13 @@ typedef struct LayerTypeInfo { void (*dominmax)(void *data1, void *min, void *max); void (*copyvalue)(void *source, void *dest); - /* a function to read data from a cdf file */ + /** 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 */ + /** a function to write data to a cdf file */ int (*write)(CDataFile *cdf, void *data, int count); - /* a function to determine file size */ + /** a function to determine file size */ size_t (*filesize)(CDataFile *cdf, void *data, int count); } LayerTypeInfo; @@ -203,8 +212,8 @@ static void linklist_free_simple(void *link) MEM_freeN(link); } -static void layerInterp_mdeformvert(void **sources, float *weights, - float *UNUSED(sub_weights), int count, void *dest) +static void layerInterp_mdeformvert(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { MDeformVert *dvert = dest; LinkNode *dest_dw = NULL; /* a list of lists of MDeformWeight pointers */ @@ -243,6 +252,8 @@ static void layerInterp_mdeformvert(void **sources, float *weights, } } + /* delay writing to the destination incase dest is in sources */ + /* now we know how many unique deform weights there are, so realloc */ if (dvert->dw) MEM_freeN(dvert->dw); @@ -260,27 +271,6 @@ static void layerInterp_mdeformvert(void **sources, float *weights, BLI_linklist_free(dest_dw, linklist_free_simple); } - -static void layerInterp_msticky(void **sources, float *weights, - float *UNUSED(sub_weights), int count, void *dest) -{ - float co[2], w; - MSticky *mst; - int i; - - co[0] = co[1] = 0.0f; - for (i = 0; i < count; i++) { - w = weights ? weights[i] : 1.0f; - mst = (MSticky *)sources[i]; - - madd_v2_v2fl(co, mst->co, w); - } - - mst = (MSticky *)dest; - copy_v2_v2(mst->co, co); -} - - static void layerCopy_tface(const void *source, void *dest, int count) { const MTFace *source_tf = (const MTFace *)source; @@ -291,13 +281,13 @@ static void layerCopy_tface(const void *source, void *dest, int count) dest_tf[i] = source_tf[i]; } -static void layerInterp_tface(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_tface(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { MTFace *tf = dest; int i, j, k; float uv[4][2] = {{0.0f}}; - float *sub_weight; + const float *sub_weight; if (count <= 0) return; @@ -318,6 +308,7 @@ static void layerInterp_tface(void **sources, float *weights, } } + /* delay writing to the destination incase dest is in sources */ *tf = *(MTFace *)(*sources); memcpy(tf->uv, uv, sizeof(tf->uv)); } @@ -392,13 +383,13 @@ static void layerCopy_origspace_face(const void *source, void *dest, int count) dest_tf[i] = source_tf[i]; } -static void layerInterp_origspace_face(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_origspace_face(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { OrigSpaceFace *osf = dest; int i, j, k; float uv[4][2] = {{0.0f}}; - float *sub_weight; + const float *sub_weight; if (count <= 0) return; @@ -419,6 +410,8 @@ static void layerInterp_origspace_face(void **sources, float *weights, } } + /* delay writing to the destination incase dest is in sources */ + #if 0 /* no need, this ONLY contains UV's */ *osf = *(OrigSpaceFace *)(*sources); #endif @@ -680,12 +673,12 @@ static void layerDefault_mloopcol(void *data, int count) } -static void layerInterp_mloopcol(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_mloopcol(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { MLoopCol *mc = dest; int i; - float *sub_weight; + const float *sub_weight; struct { float a; float r; @@ -719,7 +712,8 @@ static void layerInterp_mloopcol(void **sources, float *weights, CLAMP(col.r, 0.0f, 255.0f); CLAMP(col.g, 0.0f, 255.0f); CLAMP(col.b, 0.0f, 255.0f); - + + /* delay writing to the destination incase dest is in sources */ mc->r = (int)col.r; mc->g = (int)col.g; mc->b = (int)col.b; @@ -768,11 +762,10 @@ static void layerAdd_mloopuv(void *data1, void *data2) add_v2_v2(l1->uv, l2->uv); } -static void layerInterp_mloopuv(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_mloopuv(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { - MLoopUV *mluv = dest; - float *uv = mluv->uv; + float uv[2]; int i; zero_v2(uv); @@ -793,6 +786,9 @@ static void layerInterp_mloopuv(void **sources, float *weights, madd_v2_v2fl(uv, src->uv, weight); } } + + /* delay writing to the destination incase dest is in sources */ + copy_v2_v2(((MLoopUV *)dest)->uv, uv); } /* origspace is almost exact copy of mloopuv's, keep in sync */ @@ -838,11 +834,10 @@ static void layerAdd_mloop_origspace(void *data1, void *data2) add_v2_v2(l1->uv, l2->uv); } -static void layerInterp_mloop_origspace(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_mloop_origspace(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { - OrigSpaceLoop *mluv = dest; - float *uv = mluv->uv; + float uv[2]; int i; zero_v2(uv); @@ -858,16 +853,19 @@ static void layerInterp_mloop_origspace(void **sources, float *weights, } else { for (i = 0; i < count; i++) { - float weight = weights ? weights[i] : 1; + float weight = weights ? weights[i] : 1.0f; OrigSpaceLoop *src = sources[i]; madd_v2_v2fl(uv, src->uv, weight); } } + + /* delay writing to the destination incase dest is in sources */ + copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv); } /* --- end copy */ -static void layerInterp_mcol(void **sources, float *weights, - float *sub_weights, int count, void *dest) +static void layerInterp_mcol(void **sources, const float *weights, + const float *sub_weights, int count, void *dest) { MCol *mc = dest; int i, j, k; @@ -878,7 +876,7 @@ static void layerInterp_mcol(void **sources, float *weights, float b; } col[4] = {{0.0f}}; - float *sub_weight; + const float *sub_weight; if (count <= 0) return; @@ -907,6 +905,7 @@ static void layerInterp_mcol(void **sources, float *weights, } } + /* delay writing to the destination incase dest is in sources */ for (j = 0; j < 4; ++j) { /* Subdivide smooth or fractal can cause problems without clamping @@ -946,33 +945,36 @@ static void layerDefault_mcol(void *data, int count) } } -static void layerInterp_bweight(void **sources, float *weights, - float *UNUSED(sub_weights), int count, void *dest) +static void layerInterp_bweight(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { - float *f = dest; + float f; float **in = (float **)sources; int i; if (count <= 0) return; - *f = 0.0f; + f = 0.0f; if (weights) { for (i = 0; i < count; ++i) { - *f += *in[i] * weights[i]; + f += *in[i] * weights[i]; } } else { for (i = 0; i < count; ++i) { - *f += *in[i]; + f += *in[i]; } } + + /* delay writing to the destination incase dest is in sources */ + *((float *)dest) = f; } -static void layerInterp_shapekey(void **sources, float *weights, - float *UNUSED(sub_weights), int count, void *dest) +static void layerInterp_shapekey(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { - float *co = dest; + float co[3]; float **in = (float **)sources; int i; @@ -990,6 +992,9 @@ static void layerInterp_shapekey(void **sources, float *weights, add_v3_v3(co, in[i]); } } + + /* delay writing to the destination incase dest is in sources */ + copy_v3_v3((float *)dest, co); } static void layerDefault_mvert_skin(void *data, int count) @@ -1003,8 +1008,8 @@ static void layerDefault_mvert_skin(void *data, int count) } } -static void layerInterp_mvert_skin(void **sources, float *weights, - float *UNUSED(sub_weights), +static void layerInterp_mvert_skin(void **sources, const float *weights, + const float *UNUSED(sub_weights), int count, void *dest) { float radius[3], w; @@ -1019,6 +1024,7 @@ static void layerInterp_mvert_skin(void **sources, float *weights, madd_v3_v3fl(radius, vs->radius, w); } + /* delay writing to the destination incase dest is in sources */ vs = dest; copy_v3_v3(vs->radius, radius); vs->flag &= ~MVERT_SKIN_ROOT; @@ -1027,8 +1033,8 @@ static void layerInterp_mvert_skin(void **sources, float *weights, static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 0: CD_MVERT */ {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, - /* 1: CD_MSTICKY */ - {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL, + /* 1: CD_MSTICKY */ /* DEPRECATED */ + {sizeof(float) * 2, "", 1, NULL, NULL, NULL, NULL, NULL, NULL}, /* 2: CD_MDEFORMVERT */ {sizeof(MDeformVert), "MDeformVert", 1, NULL, layerCopy_mdeformvert, @@ -1127,7 +1133,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(GridPaintMask), "GridPaintMask", 1, NULL, layerCopy_grid_paint_mask, layerFree_grid_paint_mask, NULL, NULL, NULL}, /* 36: CD_SKIN_NODE */ - {sizeof(MVertSkin), "MVertSkin", 1, "Skin", NULL, NULL, + {sizeof(MVertSkin), "MVertSkin", 1, NULL, NULL, NULL, layerInterp_mvert_skin, NULL, layerDefault_mvert_skin} }; @@ -1993,14 +1999,15 @@ void CustomData_interp(const CustomData *source, CustomData *dest, } /* if there are no more dest layers, we're done */ - if (dest_i >= dest->totlayer) return; + if (dest_i >= dest->totlayer) break; /* if we found a matching layer, copy the data */ if (dest->layers[dest_i].type == source->layers[src_i].type) { void *src_data = source->layers[src_i].data; - for (j = 0; j < count; ++j) + for (j = 0; j < count; ++j) { sources[j] = (char *)src_data + typeInfo->size * src_indices[j]; + } dest_offset = dest_index * typeInfo->size; @@ -2590,8 +2597,9 @@ void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights CustomDataLayer *layer = &data->layers[i]; const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if (typeInfo->interp) { - for (j = 0; j < count; ++j) + for (j = 0; j < count; ++j) { sources[j] = (char *)src_blocks[j] + layer->offset; + } typeInfo->interp(sources, weights, sub_weights, count, (char *)dest_block + layer->offset); diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c index 71801c4729f..78449879f72 100644 --- a/source/blender/blenkernel/intern/customdata_file.c +++ b/source/blender/blenkernel/intern/customdata_file.c @@ -32,6 +32,7 @@ #include "BLI_fileops.h" #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BLI_endian_switch.h" #include "BKE_customdata_file.h" #include "BKE_global.h" @@ -165,9 +166,9 @@ static int cdf_read_header(CDataFile *cdf) header->endian = cdf_endian(); if (cdf->switchendian) { - SWITCH_INT(header->type); - SWITCH_INT(header->totlayer); - SWITCH_INT(header->structbytes); + BLI_endian_switch_int32(&header->type); + BLI_endian_switch_int32(&header->totlayer); + BLI_endian_switch_int32(&header->structbytes); } if (!ELEM(header->type, CDF_TYPE_IMAGE, CDF_TYPE_MESH)) @@ -185,10 +186,10 @@ static int cdf_read_header(CDataFile *cdf) return 0; if (cdf->switchendian) { - SWITCH_INT(image->width); - SWITCH_INT(image->height); - SWITCH_INT(image->tile_size); - SWITCH_INT(image->structbytes); + BLI_endian_switch_int32(&image->width); + BLI_endian_switch_int32(&image->height); + BLI_endian_switch_int32(&image->tile_size); + BLI_endian_switch_int32(&image->structbytes); } offset += image->structbytes; @@ -200,7 +201,7 @@ static int cdf_read_header(CDataFile *cdf) return 0; if (cdf->switchendian) - SWITCH_INT(mesh->structbytes); + BLI_endian_switch_int32(&mesh->structbytes); offset += mesh->structbytes; mesh->structbytes = sizeof(CDataFileMeshHeader); @@ -219,10 +220,10 @@ static int cdf_read_header(CDataFile *cdf) return 0; if (cdf->switchendian) { - SWITCH_INT(layer->type); - SWITCH_INT(layer->datatype); - SWITCH_INT64(layer->datasize); - SWITCH_INT(layer->structbytes); + BLI_endian_switch_int32(&layer->type); + BLI_endian_switch_int32(&layer->datatype); + BLI_endian_switch_uint64(&layer->datasize); + BLI_endian_switch_int32(&layer->structbytes); } if (layer->datatype != CDF_DATA_FLOAT) @@ -317,20 +318,13 @@ int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay) int cdf_read_data(CDataFile *cdf, unsigned int size, void *data) { - float *fdata; - unsigned int a; - /* read data */ if (!fread(data, size, 1, cdf->readf)) return 0; /* switch endian if necessary */ if (cdf->switchendian) { - fdata = data; - - for (a = 0; a < size / sizeof(float); a++) { - SWITCH_INT(fdata[a]); - } + BLI_endian_switch_float_array(data, size / sizeof(float)); } return 1; diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 547a64a70d4..4110d4565b2 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -33,6 +33,7 @@ #include <string.h> #include <math.h> #include <ctype.h> +#include <stdlib.h> #include "MEM_guardedalloc.h" @@ -41,7 +42,10 @@ #include "BKE_deform.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_path_util.h" +#include "BLI_string.h" #include "BLI_utildefines.h" @@ -204,13 +208,15 @@ void defvert_normalize(MDeformVert *dvert) } } -void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock) +void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) { if (dvert->totweight <= 0) { /* nothing */ } else if (dvert->totweight == 1) { - dvert->dw[0].weight = 1.0f; + if (def_nr_lock != 0) { + dvert->dw[0].weight = 1.0f; + } } else { MDeformWeight *dw_lock = NULL; @@ -246,6 +252,50 @@ void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock) } } +void defvert_normalize_lock_map(MDeformVert *dvert, const char *lock_flags, const int defbase_tot) +{ + if (dvert->totweight <= 0) { + /* nothing */ + } + else if (dvert->totweight == 1) { + if (LIKELY(defbase_tot >= 1) && lock_flags[0]) { + dvert->dw[0].weight = 1.0f; + } + } + else { + MDeformWeight *dw; + unsigned int i; + float tot_weight = 0.0f; + float lock_iweight = 0.0f; + + for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { + if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { + tot_weight += dw->weight; + } + else { + /* invert after */ + lock_iweight += dw->weight; + } + } + + lock_iweight = maxf(0.0f, 1.0f - lock_iweight); + + if (tot_weight > 0.0f) { + /* paranoid, should be 1.0 but in case of float error clamp anyway */ + + float scalar = (1.0f / tot_weight) * lock_iweight; + for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { + if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { + dw->weight *= scalar; + + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } + } + } + } +} + void defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_len) { MDeformWeight *dw; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 53981cb39cb..48040867ad4 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -75,7 +75,6 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_tracking.h" -#include "BKE_utildefines.h" #include "depsgraph_private.h" @@ -502,7 +501,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (ob->adt) dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation - key = ob_get_key(ob); + key = BKE_key_from_object(ob); if (key && key->adt) dag_add_driver_relation(key->adt, dag, node, 1); @@ -2651,7 +2650,7 @@ static void dag_id_flush_update(Scene *sce, ID *id) /* set flags based on ShapeKey */ if (idtype == ID_KE) { for (obt = bmain->object.first; obt; obt = obt->id.next) { - Key *key = ob_get_key(obt); + Key *key = BKE_key_from_object(obt); if (!(ob && obt == ob) && ((ID *)key == id)) { obt->flag |= (OB_RECALC_OB | OB_RECALC_DATA); lib_id_recalc_tag(bmain, &obt->id); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 8db93f8b44a..d55848514cc 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -669,7 +669,7 @@ static void boundInsert(Bounds3D *b, float point[3]) } } -float getSurfaceDimension(PaintSurfaceData *sData) +static float getSurfaceDimension(PaintSurfaceData *sData) { Bounds3D *mb = &sData->bData->mesh_bounds; return MAX3((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2])); @@ -910,7 +910,7 @@ static void free_bakeData(PaintSurfaceData *data) } /* free surface data if it's not used anymore */ -void surface_freeUnusedData(DynamicPaintSurface *surface) +static void surface_freeUnusedData(DynamicPaintSurface *surface) { if (!surface->data) return; @@ -1368,7 +1368,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for MEM_freeN(temp_data); } -void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) +static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) { PaintSurfaceData *sData = surface->data; PaintPoint *pPoint = (PaintPoint *)sData->type_data; @@ -1605,7 +1605,7 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Deri /* * Apply canvas data to the object derived mesh */ -struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, +static DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *ob, DerivedMesh *dm) { @@ -1830,9 +1830,12 @@ void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface) } } -void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm) +static void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm) { - if (canvas->dm) canvas->dm->release(canvas->dm); + if (canvas->dm) { + canvas->dm->release(canvas->dm); + } + canvas->dm = CDDM_copy(dm); } @@ -1941,7 +1944,7 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh { /* Note: Current method only uses polygon edges to detect neighboring pixels. * -> It doesn't always lead to the optimum pixel but is accurate enough - * and faster/simplier than including possible face tip point links) + * and faster/simpler than including possible face tip point links) */ int x, y; @@ -2595,7 +2598,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_IMF_IMTYPE_OPENEXR : R_IMF_IMTYPE_PNG; char output_file[FILE_MAX]; - if (!sData || !sData->type_data) { setError(surface->canvas, "Image save failed: Invalid surface."); return; } + if (!sData->type_data) { setError(surface->canvas, "Image save failed: Invalid surface."); return; } /* if selected format is openexr, but current build doesnt support one */ #ifndef WITH_OPENEXR if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG; @@ -2748,7 +2751,7 @@ static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats) /* * Get material diffuse color and alpha (including linked textures) in given coordinates */ -void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) +static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) { Material *mat = bMats->mat; MFace *mface = orcoDm->getTessFaceArray(orcoDm); @@ -2849,15 +2852,15 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float c /***************************** Brush Painting Calls ******************************/ -/* - * Mix color values to canvas point. +/** + * Mix color values to canvas point. * - * surface : canvas surface - * index : surface point index - * paintFlags : paint object flags - * paintColor,Alpha,Wetness : to be mixed paint values - * timescale : value used to adjust time dependand - * operations when using substeps + * \param surface canvas surface + * \param index surface point index + * \param paintFlags paint object flags + * \param paintColor,Alpha,Wetness to be mixed paint values + * \param timescale value used to adjust time dependent + * operations when using substeps */ static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index, int paintFlags, const float paintColor[3], float *paintAlpha, float *paintWetness, float *timescale) @@ -3953,7 +3956,7 @@ static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, int } /* find two adjacency points (closest_id) and influence (closest_d) to move paint towards when affected by a force */ -void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2]) +static void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2]) { BakeAdjPoint *bNeighs = sData->bData->bNeighs; int numOfNeighs = sData->adj_data->n_num[index]; @@ -3996,7 +3999,7 @@ void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, floa float force_intersect; float temp; - /* project force vector on the plane determined by these two neightbour points + /* project force vector on the plane determined by these two neighbor points * and calculate relative force angle from it*/ cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir); normalize_v3(tangent); @@ -4158,7 +4161,7 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s pdEndEffectors(&effectors); } - /* Get number of required steps using averate point distance + /* Get number of required steps using average point distance * so that just a few ultra close pixels wont up substeps to max */ /* adjust number of required substep by fastest active effect */ @@ -4221,7 +4224,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force /* Only continue if surrounding point has higher wetness */ if (ePoint->wetness < pPoint->wetness || ePoint->wetness < MIN_WETNESS) continue; - w_factor = 1.0f / numOfNeighs *MIN2(ePoint->wetness, 1.0f) * speed_scale; + w_factor = 1.0f / numOfNeighs * MIN2(ePoint->wetness, 1.0f) * speed_scale; CLAMP(w_factor, 0.0f, 1.0f); /* mix new wetness and color */ @@ -4342,7 +4345,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force } } -void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale) +static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale) { PaintSurfaceData *sData = surface->data; BakeAdjPoint *bNeighs = sData->bData->bNeighs; @@ -4800,7 +4803,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su PaintBakeData *bData = sData->bData; DynamicPaintCanvasSettings *canvas = surface->canvas; int ret = 1; - if (!sData || sData->total_points < 1) return 0; + if (sData->total_points < 1) return 0; dynamicPaint_surfacePreStep(surface, timescale); /* @@ -4875,7 +4878,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su /* Apply brush on the surface depending on it's collision type */ /* Particle brush: */ if (brush->collision == MOD_DPAINT_COL_PSYS) { - if (brush && brush->psys && brush->psys->part && brush->psys->part->type == PART_EMITTER && + if (brush->psys && brush->psys->part && brush->psys->part->type == PART_EMITTER && psys_check_enabled(brushObj, brush->psys)) { diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 925497a4929..d2f2e3f01d2 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -151,7 +151,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm) BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { /* don't consider two-edged faces */ - if (efa->len < 3) { + if (UNLIKELY(efa->len < 3)) { /* do nothing */ } @@ -1834,5 +1834,11 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, BMEditMesh *BMEdit_FromObject(Object *ob) { BLI_assert(ob->type == OB_MESH); + /* sanity check */ +#ifndef NDEBUG + if (((Mesh *)ob->data)->edit_btmesh) { + BLI_assert(((Mesh *)ob->data)->edit_btmesh->ob == ob); + } +#endif return ((Mesh *)ob->data)->edit_btmesh; } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 67e7743c8a4..2dbc63e6944 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -55,7 +55,6 @@ #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_object.h" -#include "BKE_utildefines.h" #include "RNA_access.h" @@ -75,12 +74,10 @@ void free_fcurve(FCurve *fcu) { if (fcu == NULL) return; - + /* free curve data */ - if (fcu) { - if (fcu->bezt) MEM_freeN(fcu->bezt); - if (fcu->fpt) MEM_freeN(fcu->fpt); - } + if (fcu->bezt) MEM_freeN(fcu->bezt); + if (fcu->fpt) MEM_freeN(fcu->fpt); /* free RNA-path, as this were allocated when getting the path string */ if (fcu->rna_path) @@ -365,7 +362,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short /* initialize replace-flag first */ *replace = 0; - /* sneaky optimisations (don't go through searching process if...): + /* sneaky optimizations (don't go through searching process if...): * - keyframe to be added is to be added out of current bounds * - keyframe to be added would replace one of the existing ones on bounds */ @@ -507,8 +504,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo xmaxv = MAX3(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]); } else { - xminv = MIN2(xminv, bezt_first->vec[1][0]); - xmaxv = MAX2(xmaxv, bezt_last->vec[1][0]); + xminv = minf(xminv, bezt_first->vec[1][0]); + xmaxv = maxf(xmaxv, bezt_last->vec[1][0]); } } } @@ -524,8 +521,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo ymaxv = MAX4(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]); } else { - yminv = MIN2(yminv, bezt->vec[1][1]); - ymaxv = MAX2(ymaxv, bezt->vec[1][1]); + yminv = minf(yminv, bezt->vec[1][1]); + ymaxv = maxf(ymaxv, bezt->vec[1][1]); } foundvert = TRUE; @@ -536,8 +533,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo else if (fcu->fpt) { /* frame range can be directly calculated from end verts */ if (xmin || xmax) { - xminv = MIN2(xminv, fcu->fpt[0].vec[0]); - xmaxv = MAX2(xmaxv, fcu->fpt[fcu->totvert - 1].vec[0]); + xminv = minf(xminv, fcu->fpt[0].vec[0]); + xmaxv = maxf(xmaxv, fcu->fpt[fcu->totvert - 1].vec[0]); } /* only loop over keyframes to find extents for values if needed */ @@ -594,15 +591,15 @@ void calc_fcurve_range(FCurve *fcu, float *start, float *end, if (bezt_first) { BLI_assert(bezt_last != NULL); - min = MIN2(min, bezt_first->vec[1][0]); - max = MAX2(max, bezt_last->vec[1][0]); + min = minf(min, bezt_first->vec[1][0]); + max = maxf(max, bezt_last->vec[1][0]); foundvert = TRUE; } } else if (fcu->fpt) { - min = MIN2(min, fcu->fpt[0].vec[0]); - max = MAX2(max, fcu->fpt[fcu->totvert - 1].vec[0]); + min = minf(min, fcu->fpt[0].vec[0]); + max = maxf(max, fcu->fpt[fcu->totvert - 1].vec[0]); foundvert = TRUE; } diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 438188b1e2a..68321076398 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -48,10 +48,6 @@ #include "BKE_fcurve.h" #include "BKE_idprop.h" - -#define SMALL -1.0e-10 -#define SELECT 1 - /* ******************************** F-Modifiers ********************************* */ /* Info ------------------------------- */ @@ -965,8 +961,8 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type) } /* only return for valid types */ - if ( (type >= FMODIFIER_TYPE_NULL) && - (type <= FMODIFIER_NUM_TYPES) ) + if ((type >= FMODIFIER_TYPE_NULL) && + (type < FMODIFIER_NUM_TYPES)) { /* there shouldn't be any segfaults here... */ return fmodifiersTypeInfo[type]; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 0ffd68c9079..8b35974ea62 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -50,7 +50,6 @@ #include "DNA_scene_types.h" #include "DNA_object_types.h" -#include "BKE_utildefines.h" #include "BKE_packedFile.h" #include "BKE_library.h" #include "BKE_font.h" diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 2ec5801746c..84871375788 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -163,7 +163,7 @@ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe) } /* add a new gp-layer and make it the active layer */ -bGPDlayer *gpencil_layer_addnew(bGPdata *gpd) +bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, int setactive) { bGPDlayer *gpl; @@ -182,11 +182,12 @@ bGPDlayer *gpencil_layer_addnew(bGPdata *gpd) gpl->thickness = 3; /* auto-name */ - strcpy(gpl->info, "GP_Layer"); + strcpy(gpl->info, name); BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info)); /* make this one the active one */ - gpencil_layer_setactive(gpd, gpl); + if (setactive) + gpencil_layer_setactive(gpd, gpl); /* return layer */ return gpl; @@ -509,10 +510,8 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active) } /* delete the active gp-layer */ -void gpencil_layer_delactive(bGPdata *gpd) +void gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl) { - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - /* error checking */ if (ELEM(NULL, gpd, gpl)) return; diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 500df1b7b75..634428d9194 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -110,16 +110,6 @@ void BKE_group_unlink(Group *group) if (ob->dup_group == group) { ob->dup_group = NULL; -#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */ - { - bActionStrip *strip; - /* duplicator strips use a group object, we remove it */ - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - if (strip->object) - strip->object = NULL; - } - } -#endif } for (psys = ob->particlesystem.first; psys; psys = psys->next) { @@ -383,57 +373,3 @@ void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group } } } - -#if 0 -Object *group_get_member_with_action(Group *group, bAction *act) -{ - GroupObject *go; - - if (group == NULL || act == NULL) return NULL; - - for (go = group->gobject.first; go; go = go->next) { - if (go->ob) { - if (go->ob->action == act) - return go->ob; - if (go->ob->nlastrips.first) { - bActionStrip *strip; - - for (strip = go->ob->nlastrips.first; strip; strip = strip->next) { - if (strip->act == act) - return go->ob; - } - } - } - } - return NULL; -} - -/* if group has NLA, we try to map the used objects in NLA to group members */ -/* this assuming that object has received a new group link */ -void group_relink_nla_objects(Object *ob) -{ - Group *group; - GroupObject *go; - bActionStrip *strip; - - if (ob == NULL || ob->dup_group == NULL) return; - group = ob->dup_group; - - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - if (strip->object) { - for (go = group->gobject.first; go; go = go->next) { - if (go->ob) { - if (strcmp(go->ob->id.name, strip->object->id.name) == 0) - break; - } - } - if (go) - strip->object = go->ob; - else - strip->object = NULL; - } - - } -} - -#endif diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 8a49cba7649..d8c3e260399 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -65,7 +65,7 @@ static void icon_free(void *val) Icon *icon = val; if (icon) { - if (icon->drawinfo_free) { + if (icon->drawinfo_free) { icon->drawinfo_free(icon->drawinfo); } else if (icon->drawinfo) { @@ -255,7 +255,7 @@ void BKE_icon_changed(int id) prv->changed_timestamp[i]++; } } - } + } } int BKE_icon_getid(struct ID *id) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 7456f9aab8b..8ceaab56f83 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -293,18 +293,6 @@ static IDProperty *IDP_CopyArray(IDProperty *prop) return newp; } -/*taken from readfile.c*/ -#define SWITCH_LONGINT(a) { \ - char s_i, *p_i; \ - p_i = (char *)& (a); \ - s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; \ - s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; \ - s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; \ - s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; \ - } (void)0 - - - /* ---------- String Type ------------ */ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) { @@ -496,7 +484,7 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) BLI_remlink(&group->data.group, loop); IDP_FreeProperty(loop); - MEM_freeN(loop); + MEM_freeN(loop); } else { group->len++; @@ -691,7 +679,7 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n case IDP_DOUBLE: prop = MEM_callocN(sizeof(IDProperty), "IDProperty float"); *(double *)&prop->data.val = val->d; - break; + break; case IDP_ARRAY: { /* for now, we only support float and int and double arrays */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 2b2128439c7..c003a86a0b7 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -47,6 +47,7 @@ #include "MEM_guardedalloc.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -70,6 +71,7 @@ #include "BLI_bpath.h" #include "BKE_bmfont.h" +#include "BKE_colortools.h" #include "BKE_global.h" #include "BKE_icons.h" #include "BKE_image.h" @@ -79,7 +81,6 @@ #include "BKE_scene.h" #include "BKE_node.h" #include "BKE_sequencer.h" /* seq_foreground_frame_get() */ -#include "BKE_utildefines.h" #include "BLF_api.h" @@ -244,6 +245,11 @@ static Image *image_alloc(const char *name, short source, short type) ima->source = source; ima->type = type; + + if (source == IMA_SRC_VIEWER) + ima->flag |= IMA_VIEW_AS_RENDER; + + BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings); } return ima; } @@ -326,6 +332,8 @@ Image *BKE_image_copy(Image *ima) nima->aspx = ima->aspx; nima->aspy = ima->aspy; + BKE_color_managed_colorspace_settings_copy(&nima->colorspace_settings, &ima->colorspace_settings); + return nima; } @@ -595,7 +603,8 @@ Image *BKE_image_load_exists(const char *filepath) return BKE_image_load(filepath); } -static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) +static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, + float color[4], ColorManagedColorspaceSettings *colorspace_settings) { ImBuf *ibuf; unsigned char *rect = NULL; @@ -604,22 +613,36 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char if (floatbuf) { ibuf = IMB_allocImBuf(width, height, depth, IB_rectfloat); rect_float = ibuf->rect_float; - ibuf->profile = IB_PROFILE_LINEAR_RGB; + + if (colorspace_settings->name[0] == '\0') { + const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_FLOAT); + + BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name)); + } + + IMB_colormanagement_check_is_data(ibuf, colorspace_settings->name); } else { ibuf = IMB_allocImBuf(width, height, depth, IB_rect); rect = (unsigned char *)ibuf->rect; - ibuf->profile = IB_PROFILE_SRGB; + + if (colorspace_settings->name[0] == '\0') { + const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE); + + BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name)); + } + + IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace_settings->name); } BLI_strncpy(ibuf->name, name, sizeof(ibuf->name)); ibuf->userflags |= IB_BITMAPDIRTY; - switch (uvtestgrid) { - case 1: + switch (gen_type) { + case IMA_GENTYPE_GRID: BKE_image_buf_fill_checker(rect, rect_float, width, height); break; - case 2: + case IMA_GENTYPE_GRID_COLOR: BKE_image_buf_fill_checker_color(rect, rect_float, width, height); break; default: @@ -630,7 +653,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char } /* adds new image block, creates ImBuf and initializes color */ -Image *BKE_image_add_generated(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short uvtestgrid, float color[4]) +Image *BKE_image_add_generated(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, float color[4]) { /* on save, type is changed to FILE in editsima.c */ Image *ima = image_alloc(name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); @@ -641,10 +664,10 @@ Image *BKE_image_add_generated(unsigned int width, unsigned int height, const ch /* BLI_strncpy(ima->name, name, FILE_MAX); */ /* don't do this, this writes in ain invalid filepath! */ ima->gen_x = width; ima->gen_y = height; - ima->gen_type = uvtestgrid; + ima->gen_type = gen_type; ima->gen_flag |= (floatbuf ? IMA_GEN_FLOAT : 0); - ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, uvtestgrid, 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); ima->ok = IMA_OK_LOADED; @@ -1010,6 +1033,19 @@ int BKE_imtype_supports_quality(const char imtype) return 0; } +int BKE_imtype_requires_linear_float(const char imtype) +{ + switch (imtype) { + case R_IMF_IMTYPE_CINEON: + case R_IMF_IMTYPE_DPX: + case R_IMF_IMTYPE_RADHDR: + case R_IMF_IMTYPE_OPENEXR: + case R_IMF_IMTYPE_MULTILAYER: + return TRUE; + } + return 0; +} + char BKE_imtype_valid_channels(const char imtype) { char chan_flag = IMA_CHAN_FLAG_RGB; /* assume all support rgb */ @@ -1208,6 +1244,9 @@ void BKE_imformat_defaults(ImageFormatData *im_format) im_format->imtype = R_IMF_IMTYPE_PNG; im_format->quality = 90; im_format->compress = 90; + + BKE_color_managed_display_settings_init(&im_format->display_settings); + BKE_color_managed_view_settings_init(&im_format->view_settings); } void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *imbuf) @@ -1478,10 +1517,11 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec int x, y, y_ofs; float h_fixed; const int mono = blf_mono_font_render; // XXX + struct ColorManagedDisplay *display; + const char *display_device; /* this could be an argument if we want to operate on non linear float imbuf's * for now though this is only used for renders which use scene settings */ - const int do_color_management = (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) != 0; #define BUFF_MARGIN_X 2 #define BUFF_MARGIN_Y 1 @@ -1489,6 +1529,9 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec if (!rect && !rectf) return; + display_device = scene->display_settings.display_device; + display = IMB_colormanagement_display_get_named(display_device); + stampdata(scene, camera, &stamp_data, 1); /* TODO, do_versions */ @@ -1498,7 +1541,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* set before return */ BLF_size(mono, scene->r.stamp_font_id, 72); - BLF_buffer(mono, rectf, rect, width, height, channels, do_color_management); + BLF_buffer(mono, rectf, rect, width, height, channels, display); BLF_buffer_col(mono, scene->r.fg_stamp[0], scene->r.fg_stamp[1], scene->r.fg_stamp[2], 1.0); pad = BLF_width_max(mono); @@ -1515,7 +1558,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* also a little of space to the background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and draw the text. */ @@ -1532,7 +1575,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); @@ -1548,7 +1591,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); @@ -1564,7 +1607,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); @@ -1579,7 +1622,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.marker, &w, &h); h = h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ @@ -1595,7 +1638,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.time, &w, &h); h = h_fixed; /* extra space for background */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ @@ -1610,7 +1653,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.frame, &w, &h); h = h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ @@ -1625,7 +1668,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.camera, &w, &h); h = h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.camera); @@ -1638,7 +1681,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.cameralens, &w, &h); h = h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.cameralens); @@ -1651,7 +1694,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec x = width - w - 2; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ @@ -1667,7 +1710,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y = height - h; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); @@ -1879,12 +1922,12 @@ void BKE_makepicstring(char *string, const char *base, const char *relbase, int } /* used by sequencer too */ -struct anim *openanim(const char *name, int flags, int streamindex) +struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE]) { struct anim *anim; struct ImBuf *ibuf; - anim = IMB_open_anim(name, flags, streamindex); + anim = IMB_open_anim(name, flags, streamindex, colorspace); if (anim == NULL) return NULL; ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); @@ -2178,8 +2221,10 @@ void BKE_image_backup_render(Scene *scene, Image *ima) /* in that case we have to build a render-result */ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) { + const char *colorspace = ima->colorspace_settings.name; + int predivide = ima->flag & IMA_CM_PREDIVIDE; - ima->rr = RE_MultilayerConvert(ibuf->userdata, ibuf->x, ibuf->y); + ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y); #ifdef WITH_OPENEXR IMB_exr_close(ibuf->userdata); @@ -2227,7 +2272,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) flag |= IB_premul; /* read ibuf */ - ibuf = IMB_loadiffname(name, flag); + ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name); #if 0 if (ibuf) { @@ -2305,7 +2350,6 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f ibuf->flags |= IB_rectfloat; ibuf->mall = IB_rectfloat; ibuf->channels = rpass->channels; - ibuf->profile = IB_PROFILE_LINEAR_RGB; image_initialize_after_load(ima, ibuf); image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : 0, frame); @@ -2335,7 +2379,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) BKE_image_user_file_path(iuser, ima, str); /* FIXME: make several stream accessible in image editor, too*/ - ima->anim = openanim(str, IB_rect, 0); + ima->anim = openanim(str, IB_rect, 0, ima->colorspace_settings.name); /* let's initialize this user */ if (ima->anim && iuser && iuser->frames == 0) @@ -2386,8 +2430,8 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) flag = IB_rect | IB_multilayer; if (ima->flag & IMA_DO_PREMUL) flag |= IB_premul; - ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, - ima->packedfile->size, flag, "<packed data>"); + ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, ima->packedfile->size, flag, + ima->colorspace_settings.name, "<packed data>"); } else { flag = IB_rect | IB_multilayer | IB_metadata; @@ -2399,7 +2443,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) BKE_image_user_file_path(iuser, ima, str); /* read ibuf */ - ibuf = IMB_loadiffname(str, flag); + ibuf = IMB_loadiffname(str, flag, ima->colorspace_settings.name); } if (ibuf) { @@ -2456,7 +2500,6 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) ibuf->rect_float = rpass->rect; ibuf->flags |= IB_rectfloat; ibuf->channels = rpass->channels; - ibuf->profile = IB_PROFILE_LINEAR_RGB; image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : IMA_NO_INDEX, 0); } @@ -2520,14 +2563,16 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ *lock_r = re; } - /* this gives active layer, composite or seqence result */ + /* this gives active layer, composite or sequence result */ rect = (unsigned int *)rres.rect32; rectf = rres.rectf; rectz = rres.rectz; dither = iuser->scene->r.dither_intensity; /* combined layer gets added as first layer */ - if (rres.have_combined && layer == 0) ; + if (rres.have_combined && layer == 0) { + /* pass */ + } else if (rres.layers.first) { RenderLayer *rl = BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0)); if (rl) { @@ -2560,6 +2605,12 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); } + /* invalidate color managed buffers if render result changed */ + BLI_lock_thread(LOCK_COLORMANAGE); + if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) { + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + } + ibuf->x = rres.rectx; ibuf->y = rres.recty; @@ -2591,8 +2642,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ ibuf->flags &= ~IB_zbuffloat; } - /* since its possible to access the buffer from the image directly, set the profile [#25073] */ - ibuf->profile = (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE; + BLI_unlock_thread(LOCK_COLORMANAGE); + ibuf->dither = dither; if (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) { @@ -2749,7 +2800,8 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) /* UV testgrid or black or solid etc */ if (ima->gen_x == 0) ima->gen_x = 1024; if (ima->gen_y == 0) ima->gen_y = 1024; - ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, color); + ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, + color, &ima->colorspace_settings); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); ima->ok = IMA_OK_LOADED; } @@ -2930,3 +2982,43 @@ int BKE_image_has_alpha(struct Image *image) else return 0; } + +void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) +{ + ImBuf *ibuf = NULL; + void *lock; + + ibuf = BKE_image_acquire_ibuf(image, iuser, &lock); + + if (ibuf && ibuf->x > 0 && ibuf->y > 0) { + *width = ibuf->x; + *height = ibuf->y; + } + else { + *width = IMG_SIZE_FALLBACK; + *height = IMG_SIZE_FALLBACK; + } + + BKE_image_release_ibuf(image, lock); +} + +void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float size[2]) +{ + int width, height; + BKE_image_get_size(image, iuser, &width, &height); + + size[0] = (float)width; + size[1] = (float)height; + +} + +void BKE_image_get_aspect(Image *image, float *aspx, float *aspy) +{ + *aspx = 1.0; + + /* x is always 1 */ + if (image) + *aspy = image->aspy / image->aspx; + else + *aspy = 1.0f; +} diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index 4d7013b9f73..37572eebed6 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -289,7 +289,11 @@ static void checker_board_text(unsigned char *rect, float *rect_float, int width BLF_size(mono, 54, 72); /* hard coded size! */ - BLF_buffer(mono, rect_float, rect, width, height, 4, TRUE); + /* OCIO_TODO: using NULL as display will assume using sRGB display + * this is correct since currently generated images are assumed to be in sRGB space, + * but this would probably needed to be fixed in some way + */ + BLF_buffer(mono, rect_float, rect, width, height, 4, NULL); for (y = 0; y < height; y += step) { text[1] = '1'; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 616214c21ff..ebb95a6561e 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -48,8 +48,11 @@ #include "BKE_global.h" -#define CLOTH_OPENMP_LIMIT 512 +#ifdef _OPENMP +# define CLOTH_OPENMP_LIMIT 512 +#endif +#if 0 /* debug timing */ #ifdef _WIN32 #include <windows.h> static LARGE_INTEGER _itstart, _itend; @@ -81,7 +84,7 @@ double itval(void) static struct timeval _itstart, _itend; static struct timezone itz; -void itstart(void) +static void itstart(void) { gettimeofday(&_itstart, &itz); } @@ -89,7 +92,7 @@ static void itend(void) { gettimeofday(&_itend, &itz); } -double itval(void) +static double itval(void) { double t1, t2; t1 = (double)_itstart.tv_sec + (double)_itstart.tv_usec/(1000*1000); @@ -97,6 +100,7 @@ double itval(void) return t2-t1; } #endif +#endif /* debug timing */ static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; static float ZERO[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; @@ -193,7 +197,7 @@ DO_INLINE lfVector *create_lfvector(unsigned int verts) DO_INLINE void del_lfvector(float (*fLongVector)[3]) { if (fLongVector != NULL) { - MEM_freeN (fLongVector); + MEM_freeN(fLongVector); // cloth_aligned_free(&MEMORY_BASE, fLongVector); } } @@ -523,7 +527,7 @@ DO_INLINE fmatrix3x3 *create_bfmatrix(unsigned int verts, unsigned int springs) DO_INLINE void del_bfmatrix(fmatrix3x3 *matrix) { if (matrix != NULL) { - MEM_freeN (matrix); + MEM_freeN(matrix); } } @@ -1691,13 +1695,13 @@ static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVect mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - - itstart(); - + + // itstart(); + cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ // cg_filtered_pre(dV, A, B, z, S, P, Pinv, bigI); - - itend(); + + // itend(); // printf("cg_filtered calc time: %f\n", (float)itval()); cp_lfvector(olddV, dV, numverts); @@ -1713,7 +1717,7 @@ static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVect * (edge distance constraints) in a lagrangian solver. then add forces to help * guide the implicit solver to that state. this function is called after * collisions*/ -int cloth_calc_helper_forces(Object *UNUSED(ob), ClothModifierData * clmd, float (*initial_cos)[3], float UNUSED(step), float dt) +static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothModifierData * clmd, float (*initial_cos)[3], float UNUSED(step), float dt) { Cloth *cloth= clmd->clothObject; float (*cos)[3] = MEM_callocN(sizeof(float)*3*cloth->numverts, "cos cloth_calc_helper_forces"); diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index b2a9e229be9..5216aefab58 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -32,7 +32,7 @@ /* NOTE: * - * This file is no longer used to provide tools for the depreceated IPO system. Instead, it + * This file is no longer used to provide tools for the deprecated IPO system. Instead, it * is only used to house the conversion code to the new system. * * -- Joshua Leung, Jan 2009 @@ -1757,15 +1757,15 @@ void do_versions_ipos_to_animato(Main *main) { /* If we have any empty action actuators, assume they were - converted IPO Actuators using the object IPO */ + * converted IPO Actuators using the object IPO */ bActuator *act; bActionActuator *aa; for (act = ob->actuators.first; act; act = act->next) { /* Any actuators set to ACT_IPO at this point are actually Action Actuators that - need this converted IPO to finish converting the actuator. */ + * need this converted IPO to finish converting the actuator. */ if (act->type == ACT_IPO) { - aa = (bActionActuator*)act->data; + aa = (bActionActuator *)act->data; aa->act = ob->adt->action; act->type = ACT_ACTION; } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 17a3c595ea7..b9bf2fd01a3 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -94,7 +94,7 @@ void BKE_key_free(Key *key) } -void free_key_nolib(Key *key) +void BKE_key_free_nolib(Key *key) { KeyBlock *kb; @@ -121,7 +121,7 @@ void free_key_nolib(Key *key) /* from misc_util: flip the bytes from x */ /* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ -Key *add_key(ID *id) /* common function */ +Key *BKE_key_add(ID *id) /* common function */ { Key *key; char *el; @@ -133,7 +133,7 @@ Key *add_key(ID *id) /* common function */ key->uidgen = 1; - /* XXX the code here uses some defines which will soon be depreceated... */ + /* XXX the code here uses some defines which will soon be deprecated... */ switch (GS(id->name)) { case ID_ME: el = key->elemstr; @@ -196,7 +196,7 @@ Key *BKE_key_copy(Key *key) } -Key *copy_key_nolib(Key *key) +Key *BKE_key_copy_nolib(Key *key) { Key *keyn; KeyBlock *kbn, *kb; @@ -241,7 +241,7 @@ void BKE_key_make_local(Key *key) * currently being called. */ -void sort_keys(Key *key) +void BKE_key_sort(Key *key) { KeyBlock *kb; KeyBlock *kb2; @@ -691,8 +691,8 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const if (nu->bp) { step = nu->pntsu * nu->pntsv; - a1 = MAX2(a, start); - a2 = MIN2(a + step, end); + a1 = maxi(a, start); + a2 = mini(a + step, end); if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BPOINT); } @@ -700,8 +700,8 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const step = 3 * nu->pntsu; /* exception because keys prefer to work with complete blocks */ - a1 = MAX2(a, start); - a2 = MIN2(a + step, end); + a1 = maxi(a, start); + a2 = mini(a + step, end); if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BEZTRIPLE); } @@ -711,7 +711,7 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const } } -void do_rel_key(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode) +void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode) { KeyBlock *kb; int *ofsp, ofs[3], elemsize, b; @@ -1071,7 +1071,7 @@ static float *get_weights_array(Object *ob, char *vgroup) static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { - KeyBlock *k[4], *actkb = ob_get_keyblock(ob); + KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob); float t[4]; int flag = 0; @@ -1106,7 +1106,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int kb->weights = get_weights_array(ob, kb->vgroup); } - do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY); + BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY); for (kb = key->block.first; kb; kb = kb->next) { if (kb->weights) MEM_freeN(kb->weights); @@ -1154,11 +1154,11 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const for (a = 0, nu = cu->nurb.first; nu; nu = nu->next, a += step) { if (nu->bp) { step = nu->pntsu * nu->pntsv; - do_rel_key(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT); + BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT); } else if (nu->bezt) { step = 3 * nu->pntsu; - do_rel_key(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE); + BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE); } else { step = 0; @@ -1169,7 +1169,7 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { Curve *cu = ob->data; - KeyBlock *k[4], *actkb = ob_get_keyblock(ob); + KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob); float t[4]; int flag = 0; @@ -1217,7 +1217,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const in remain = step; } - count = MIN2(remain, estep); + count = mini(remain, estep); if (mode == KEY_MODE_BEZTRIPLE) { count += 3 - count % 3; } @@ -1251,7 +1251,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const in static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { Lattice *lt = ob->data; - KeyBlock *k[4], *actkb = ob_get_keyblock(ob); + KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob); float t[4]; int flag; @@ -1277,7 +1277,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int for (kb = key->block.first; kb; kb = kb->next) kb->weights = get_weights_array(ob, kb->vgroup); - do_rel_key(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY); + BKE_key_evaluate_relative(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY); for (kb = key->block.first; kb; kb = kb->next) { if (kb->weights) MEM_freeN(kb->weights); @@ -1302,8 +1302,8 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int /* returns key coordinates (+ tilt) when key applied, NULL otherwise */ float *do_ob_key(Scene *scene, Object *ob) { - Key *key = ob_get_key(ob); - KeyBlock *actkb = ob_get_keyblock(ob); + Key *key = BKE_key_from_object(ob); + KeyBlock *actkb = BKE_keyblock_from_object(ob); char *out; int tot = 0, size = 0; @@ -1386,7 +1386,7 @@ float *do_ob_key(Scene *scene, Object *ob) return (float *)out; } -Key *ob_get_key(Object *ob) +Key *BKE_key_from_object(Object *ob) { if (ob == NULL) return NULL; @@ -1405,7 +1405,7 @@ Key *ob_get_key(Object *ob) return NULL; } -KeyBlock *add_keyblock(Key *key, const char *name) +KeyBlock *BKE_keyblock_add(Key *key, const char *name) { KeyBlock *kb; float curpos = -0.1; @@ -1439,7 +1439,7 @@ KeyBlock *add_keyblock(Key *key, const char *name) /** * \note caller may want to set this to current time, but don't do it here since we need to sort - * which could cause problems in some cases, see #add_keyblock_ctime */ + * which could cause problems in some cases, see #BKE_keyblock_add_ctime */ kb->pos = curpos + 0.1f; /* only used for absolute shape keys */ return kb; @@ -1453,22 +1453,22 @@ KeyBlock *add_keyblock(Key *key, const char *name) * \param name Optional name for the new keyblock. * \param do_force always use ctime even for relative keys. */ -KeyBlock *add_keyblock_ctime(Key *key, const char *name, const short do_force) +KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const short do_force) { - KeyBlock *kb = add_keyblock(key, name); + KeyBlock *kb = BKE_keyblock_add(key, name); if (do_force || (key->type != KEY_RELATIVE)) { kb->pos = key->ctime / 100.0f; - sort_keys(key); + BKE_key_sort(key); } return kb; } /* only the active keyblock */ -KeyBlock *ob_get_keyblock(Object *ob) +KeyBlock *BKE_keyblock_from_object(Object *ob) { - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); if (key) { KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1); @@ -1478,9 +1478,9 @@ KeyBlock *ob_get_keyblock(Object *ob) return NULL; } -KeyBlock *ob_get_reference_keyblock(Object *ob) +KeyBlock *BKE_keyblock_from_object_reference(Object *ob) { - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); if (key) return key->refkey; @@ -1489,7 +1489,7 @@ KeyBlock *ob_get_reference_keyblock(Object *ob) } /* get the appropriate KeyBlock given an index */ -KeyBlock *key_get_keyblock(Key *key, int index) +KeyBlock *BKE_keyblock_from_key(Key *key, int index) { KeyBlock *kb; int i; @@ -1509,18 +1509,29 @@ KeyBlock *key_get_keyblock(Key *key, int index) } /* get the appropriate KeyBlock given a name to search for */ -KeyBlock *key_get_named_keyblock(Key *key, const char name[]) +KeyBlock *BKE_keyblock_find_name(Key *key, const char name[]) { - if (key && name) - return BLI_findstring(&key->block, name, offsetof(KeyBlock, name)); - - return NULL; + return BLI_findstring(&key->block, name, offsetof(KeyBlock, name)); +} + +/** + * \brief copy shape-key attributes, but not key data.or name/uid + */ +void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src) +{ + kb_dst->pos = kb_src->pos; + kb_dst->curval = kb_src->curval; + kb_dst->type = kb_src->type; + kb_dst->relative = kb_src->relative; + BLI_strncpy(kb_dst->vgroup, kb_src->vgroup, sizeof(kb_dst->vgroup)); + kb_dst->slidermin = kb_src->slidermin; + kb_dst->slidermax = kb_src->slidermax; } /* Get RNA-Path for 'value' setting of the given ShapeKey * NOTE: the user needs to free the returned string once they're finish with it */ -char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb) +char *BKE_keyblock_curval_rnapath_get(Key *key, KeyBlock *kb) { PointerRNA ptr; PropertyRNA *prop; @@ -1542,7 +1553,7 @@ char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb) /* conversion functions */ /************************* Lattice ************************/ -void latt_to_key(Lattice *lt, KeyBlock *kb) +void BKE_key_convert_from_lattice(Lattice *lt, KeyBlock *kb) { BPoint *bp; float *fp; @@ -1563,7 +1574,7 @@ void latt_to_key(Lattice *lt, KeyBlock *kb) } } -void key_to_latt(KeyBlock *kb, Lattice *lt) +void BKE_key_convert_to_lattice(KeyBlock *kb, Lattice *lt) { BPoint *bp; float *fp; @@ -1573,7 +1584,7 @@ void key_to_latt(KeyBlock *kb, Lattice *lt) fp = kb->data; tot = lt->pntsu * lt->pntsv * lt->pntsw; - tot = MIN2(kb->totelem, tot); + tot = mini(kb->totelem, tot); for (a = 0; a < tot; a++, fp += 3, bp++) { copy_v3_v3(bp->vec, fp); @@ -1581,7 +1592,7 @@ void key_to_latt(KeyBlock *kb, Lattice *lt) } /************************* Curve ************************/ -void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb) +void BKE_key_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb) { Nurb *nu; BezTriple *bezt; @@ -1632,7 +1643,7 @@ void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb) } } -void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) +void BKE_key_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) { Nurb *nu; BezTriple *bezt; @@ -1645,7 +1656,7 @@ void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) tot = BKE_nurbList_verts_count(nurb); - tot = MIN2(kb->totelem, tot); + tot = mini(kb->totelem, tot); while (nu && tot > 0) { @@ -1683,7 +1694,7 @@ void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) } /************************* Mesh ************************/ -void mesh_to_key(Mesh *me, KeyBlock *kb) +void BKE_key_convert_from_mesh(Mesh *me, KeyBlock *kb) { MVert *mvert; float *fp; @@ -1704,7 +1715,7 @@ void mesh_to_key(Mesh *me, KeyBlock *kb) } } -void key_to_mesh(KeyBlock *kb, Mesh *me) +void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me) { MVert *mvert; float *fp; @@ -1713,7 +1724,7 @@ void key_to_mesh(KeyBlock *kb, Mesh *me) mvert = me->mvert; fp = kb->data; - tot = MIN2(kb->totelem, me->totvert); + tot = mini(kb->totelem, me->totvert); for (a = 0; a < tot; a++, fp += 3, mvert++) { copy_v3_v3(mvert->co, fp); @@ -1721,7 +1732,7 @@ void key_to_mesh(KeyBlock *kb, Mesh *me) } /************************* vert coords ************************/ -float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3] +float (*BKE_key_convert_to_vertcos(Object * ob, KeyBlock * kb))[3] { float (*vertCos)[3], *co; float *fp = kb->data; @@ -1743,7 +1754,7 @@ float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3] if (tot == 0) return NULL; - vertCos = MEM_callocN(tot * sizeof(*vertCos), "key_to_vertcos vertCos"); + vertCos = MEM_callocN(tot * sizeof(*vertCos), "BKE_key_convert_to_vertcos vertCos"); /* Copy coords to array */ co = (float *)vertCos; @@ -1797,7 +1808,7 @@ float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3] return vertCos; } -void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) +void BKE_key_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) { float *co = (float *)vertCos, *fp; int tot = 0, a, elemsize; @@ -1826,7 +1837,7 @@ void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) return; } - fp = kb->data = MEM_callocN(tot * elemsize, "key_to_vertcos vertCos"); + fp = kb->data = MEM_callocN(tot * elemsize, "BKE_key_convert_to_vertcos vertCos"); /* Copy coords to keyblock */ @@ -1877,7 +1888,7 @@ void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) } } -void offset_to_key(Object *ob, KeyBlock *kb, float (*ofs)[3]) +void BKE_key_convert_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3]) { int a; float *co = (float *)ofs, *fp = kb->data; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 0e73d10fa5f..17e4103c7d3 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -488,7 +488,7 @@ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir /* test for cyclic */ bl = cu->bev.first; if (!bl->nr) return 0; - if (bl && bl->poly > -1) cycl = 1; + if (bl->poly > -1) cycl = 1; if (cycl == 0) { ctime1 = CLAMPIS(ctime, 0.0f, 1.0f); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index e073cfdf76d..45364f5aafa 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -107,7 +107,6 @@ #include "BKE_gpencil.h" #include "BKE_fcurve.h" #include "BKE_speaker.h" -#include "BKE_utildefines.h" #include "BKE_movieclip.h" #include "BKE_mask.h" @@ -801,6 +800,7 @@ static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata /* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */ void BKE_libblock_free(ListBase *lb, void *idv) { + Main *bmain = G.main; /* should eventually be an arg */ ID *id = idv; #ifdef WITH_PYTHON @@ -863,7 +863,7 @@ void BKE_libblock_free(ListBase *lb, void *idv) BKE_text_free((Text *)id); break; case ID_SCRIPT: - //XXX free_script((Script *)id); + /* deprecated */ break; case ID_SPK: BKE_speaker_free((Speaker *)id); @@ -900,7 +900,7 @@ void BKE_libblock_free(ListBase *lb, void *idv) BKE_movieclip_free((MovieClip *)id); break; case ID_MSK: - BKE_mask_free((Mask *)id); + BKE_mask_free(bmain, (Mask *)id); break; } @@ -912,7 +912,7 @@ void BKE_libblock_free(ListBase *lb, void *idv) BLI_remlink(lb, id); /* this ID may be a driver target! */ - BKE_animdata_main_cb(G.main, animdata_dtar_clear_cb, (void *)id); + BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id); MEM_freeN(id); } @@ -947,9 +947,52 @@ void free_main(Main *mainvar) ID *id; while ( (id = lb->first) ) { +#if 1 BKE_libblock_free(lb, id); +#else + /* errors freeing ID's can be hard to track down, + * enable this so valgrind will give the line number in its error log */ + switch (a) { + case 0: BKE_libblock_free(lb, id); break; + case 1: BKE_libblock_free(lb, id); break; + case 2: BKE_libblock_free(lb, id); break; + case 3: BKE_libblock_free(lb, id); break; + case 4: BKE_libblock_free(lb, id); break; + case 5: BKE_libblock_free(lb, id); break; + case 6: BKE_libblock_free(lb, id); break; + case 7: BKE_libblock_free(lb, id); break; + case 8: BKE_libblock_free(lb, id); break; + case 9: BKE_libblock_free(lb, id); break; + case 10: BKE_libblock_free(lb, id); break; + case 11: BKE_libblock_free(lb, id); break; + case 12: BKE_libblock_free(lb, id); break; + case 13: BKE_libblock_free(lb, id); break; + case 14: BKE_libblock_free(lb, id); break; + case 15: BKE_libblock_free(lb, id); break; + case 16: BKE_libblock_free(lb, id); break; + case 17: BKE_libblock_free(lb, id); break; + case 18: BKE_libblock_free(lb, id); break; + case 19: BKE_libblock_free(lb, id); break; + case 20: BKE_libblock_free(lb, id); break; + case 21: BKE_libblock_free(lb, id); break; + case 22: BKE_libblock_free(lb, id); break; + case 23: BKE_libblock_free(lb, id); break; + case 24: BKE_libblock_free(lb, id); break; + case 25: BKE_libblock_free(lb, id); break; + case 26: BKE_libblock_free(lb, id); break; + case 27: BKE_libblock_free(lb, id); break; + case 28: BKE_libblock_free(lb, id); break; + case 29: BKE_libblock_free(lb, id); break; + case 30: BKE_libblock_free(lb, id); break; + case 31: BKE_libblock_free(lb, id); break; + case 32: BKE_libblock_free(lb, id); break; + default: + BLI_assert(0); + } +#endif } } + a = set_listbasepointers(mainvar, lbarray); MEM_freeN(mainvar); } @@ -1528,7 +1571,7 @@ void BKE_library_filepath_set(Library *lib, const char *filepath) /* not essential but set filepath is an absolute copy of value which * is more useful if its kept in sync */ - if (strncmp(lib->filepath, "//", 2) == 0) { + if (BLI_path_is_rel(lib->filepath)) { /* note that the file may be unsaved, in this case, setting the * filepath on an indirectly linked path is not allowed from the * outliner, and its not really supported but allow from here for now diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 1e1cbf8610e..aa19350c456 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -19,7 +19,8 @@ * All rights reserved. * * Contributor(s): Blender Foundation, - * Sergey Sharybin + * Sergey Sharybin, + * Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ @@ -41,12 +42,8 @@ #include "DNA_mask_types.h" #include "DNA_node_types.h" -#include "DNA_scene_types.h" -#include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "DNA_movieclip_types.h" -#include "DNA_tracking_types.h" #include "DNA_sequence_types.h" #include "BKE_curve.h" @@ -58,7 +55,7 @@ #include "BKE_sequencer.h" #include "BKE_tracking.h" #include "BKE_movieclip.h" -#include "BKE_utildefines.h" +#include "BKE_image.h" static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) { @@ -90,7 +87,7 @@ static MaskSplinePoint *mask_spline_point_prev(MaskSpline *spline, MaskSplinePoi } } -static BezTriple *mask_spline_point_next_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) +BezTriple *BKE_mask_spline_point_next_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) { if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) { @@ -158,7 +155,7 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name) mask->masklay_tot++; - masklay->blend = MASK_BLEND_MERGE; + masklay->blend = MASK_BLEND_MERGE_ADD; masklay->alpha = 1.0f; return masklay; @@ -269,588 +266,6 @@ MaskSpline *BKE_mask_spline_add(MaskLayer *masklay) return spline; } -unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) -{ - float max_segment = 0.01f; - unsigned int i, resol = 1; - - if (width != 0 && height != 0) { - if (width >= height) - max_segment = 1.0f / (float) width; - else - max_segment = 1.0f / (float) height; - } - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - BezTriple *bezt, *bezt_next; - float a, b, c, len; - unsigned int cur_resol; - - bezt = &point->bezt; - bezt_next = mask_spline_point_next_bezt(spline, spline->points, point); - - if (bezt_next == NULL) { - break; - } - - a = len_v3v3(bezt->vec[1], bezt->vec[2]); - b = len_v3v3(bezt->vec[2], bezt_next->vec[0]); - c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]); - - len = a + b + c; - cur_resol = len / max_segment; - - resol = MAX2(resol, cur_resol); - - if (resol >= MASK_RESOL_MAX) { - break; - } - } - - return CLAMPIS(resol, 1, MASK_RESOL_MAX); -} - -unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height) -{ - const float max_segment = 0.005; - unsigned int resol = BKE_mask_spline_resolution(spline, width, height); - float max_jump = 0.0f; - int i; - - /* avoid checking the featrher if we already hit the maximum value */ - if (resol >= MASK_RESOL_MAX) { - return MASK_RESOL_MAX; - } - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - float prev_u, prev_w; - int j; - - prev_u = 0.0f; - prev_w = point->bezt.weight; - - for (j = 0; j < point->tot_uw; j++) { - const float w_diff = (point->uw[j].w - prev_w); - const float u_diff = (point->uw[j].u - prev_u); - - /* avoid divide by zero and very high values, - * though these get clamped eventually */ - if (u_diff > FLT_EPSILON) { - float jump = fabsf(w_diff / u_diff); - - max_jump = MAX2(max_jump, jump); - } - - prev_u = point->uw[j].u; - prev_w = point->uw[j].w; - } - } - - resol += max_jump / max_segment; - - return CLAMPIS(resol, 1, MASK_RESOL_MAX); -} - -int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol) -{ - if (spline->flag & MASK_SPLINE_CYCLIC) { - return spline->tot_point * resol; - } - else { - return ((spline->tot_point - 1) * resol) + 1; - } -} - -float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline, - int *tot_diff_point, - const unsigned int resol - ))[2] -{ - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - - MaskSplinePoint *point, *prev; - float (*diff_points)[2], (*fp)[2]; - const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); - int a; - - if (spline->tot_point <= 1) { - /* nothing to differentiate */ - *tot_diff_point = 0; - return NULL; - } - - /* len+1 because of 'forward_diff_bezier' function */ - *tot_diff_point = tot; - diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets"); - - a = spline->tot_point - 1; - if (spline->flag & MASK_SPLINE_CYCLIC) - a++; - - prev = points_array; - point = prev + 1; - - while (a--) { - BezTriple *prevbezt; - BezTriple *bezt; - int j; - - if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) - point = points_array; - - prevbezt = &prev->bezt; - bezt = &point->bezt; - - for (j = 0; j < 2; j++) { - BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], prevbezt->vec[2][j], - bezt->vec[0][j], bezt->vec[1][j], - &(*fp)[j], resol, 2 * sizeof(float)); - } - - fp += resol; - - if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { - copy_v2_v2(*fp, bezt->vec[1]); - } - - prev = point; - point++; - } - - return diff_points; -} - -float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height, - int *tot_diff_point - ))[2] -{ - int unsigned resol = BKE_mask_spline_resolution(spline, width, height); - - return BKE_mask_spline_differentiate_with_resolution_ex(spline, tot_diff_point, resol); -} - -float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2] -{ - return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point); -} - -/* ** feather points self-intersection collapse routine ** */ - -typedef struct FeatherEdgesBucket { - int tot_segment; - int (*segments)[2]; - int alloc_segment; -} FeatherEdgesBucket; - -static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end) -{ - const int alloc_delta = 256; - - if (bucket->tot_segment >= bucket->alloc_segment) { - if (!bucket->segments) { - bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments"); - } - else { - bucket->segments = MEM_reallocN(bucket->segments, - (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); - } - - bucket->alloc_segment += alloc_delta; - } - - bucket->segments[bucket->tot_segment][0] = start; - bucket->segments[bucket->tot_segment][1] = end; - - bucket->tot_segment++; -} - -static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket, - int cur_a, int cur_b) -{ - int i; - - float *v1 = (float *) feather_points[cur_a]; - float *v2 = (float *) feather_points[cur_b]; - - for (i = 0; i < bucket->tot_segment; i++) { - int check_a = bucket->segments[i][0]; - int check_b = bucket->segments[i][1]; - - float *v3 = (float *) feather_points[check_a]; - float *v4 = (float *) feather_points[check_b]; - - if (check_a >= cur_a - 1 || cur_b == check_a) - continue; - - if (isect_seg_seg_v2(v1, v2, v3, v4)) { - int k; - float p[2]; - float min_a[2], max_a[2]; - float min_b[2], max_b[2]; - - isect_seg_seg_v2_point(v1, v2, v3, v4, p); - - INIT_MINMAX2(min_a, max_a); - INIT_MINMAX2(min_b, max_b); - - /* collapse loop with smaller AABB */ - for (k = 0; k < tot_feather_point; k++) { - if (k >= check_b && k <= cur_a) { - DO_MINMAX2(feather_points[k], min_a, max_a); - } - else { - DO_MINMAX2(feather_points[k], min_b, max_b); - } - } - - if (max_a[0] - min_a[0] < max_b[0] - min_b[0] || - max_a[1] - min_a[1] < max_b[1] - min_b[1]) - { - for (k = check_b; k <= cur_a; k++) { - copy_v2_v2(feather_points[k], p); - } - } - else { - for (k = 0; k <= check_a; k++) { - copy_v2_v2(feather_points[k], p); - } - - if (cur_b != 0) { - for (k = cur_b; k < tot_feather_point; k++) { - copy_v2_v2(feather_points[k], p); - } - } - } - } - } -} - -static int feather_bucket_index_from_coord(float co[2], const float min[2], const float bucket_scale[2], - const int buckets_per_side) -{ - int x = (int) ((co[0] - min[0]) * bucket_scale[0]); - int y = (int) ((co[1] - min[1]) * bucket_scale[1]); - - if (x == buckets_per_side) - x--; - - if (y == buckets_per_side) - y--; - - return y * buckets_per_side + x; -} - -static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index, - int buckets_per_side, FeatherEdgesBucket **diagonal_bucket_a_r, - FeatherEdgesBucket **diagonal_bucket_b_r) -{ - int start_bucket_x = start_bucket_index % buckets_per_side; - int start_bucket_y = start_bucket_index / buckets_per_side; - - int end_bucket_x = end_bucket_index % buckets_per_side; - int end_bucket_y = end_bucket_index / buckets_per_side; - - int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x; - int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x; - - *diagonal_bucket_a_r = &buckets[diagonal_bucket_a_index]; - *diagonal_bucket_b_r = &buckets[diagonal_bucket_b_index]; -} - -void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feather_points)[2], const int tot_feather_point) -{ -#define BUCKET_INDEX(co) \ - feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side) - - int buckets_per_side, tot_bucket; - float bucket_size, bucket_scale[2]; - - FeatherEdgesBucket *buckets; - - int i; - float min[2], max[2]; - float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta; - - if (tot_feather_point < 4) { - /* self-intersection works only for quads at least, - * in other cases polygon can't be self-intersecting anyway - */ - - return; - } - - /* find min/max corners of mask to build buckets in that space */ - INIT_MINMAX2(min, max); - - for (i = 0; i < tot_feather_point; i++) { - int next = i + 1; - float delta; - - DO_MINMAX2(feather_points[i], min, max); - - if (next == tot_feather_point) { - if (spline->flag & MASK_SPLINE_CYCLIC) - next = 0; - else - break; - } - - delta = fabsf(feather_points[i][0] - feather_points[next][0]); - if (delta > max_delta_x) - max_delta_x = delta; - - delta = fabsf(feather_points[i][1] - feather_points[next][1]); - if (delta > max_delta_y) - max_delta_y = delta; - } - - /* prevent divisionsby zero by ensuring bounding box is not collapsed */ - if (max[0] - min[0] < FLT_EPSILON) { - max[0] += 0.01f; - min[0] -= 0.01f; - } - - if (max[1] - min[1] < FLT_EPSILON) { - max[1] += 0.01f; - min[1] -= 0.01f; - } - - /* use dynamically calculated buckets per side, so we likely wouldn't - * run into a situation when segment doesn't fit two buckets which is - * pain collecting candidates for intersection - */ - - max_delta_x /= max[0] - min[0]; - max_delta_y /= max[1] - min[1]; - - max_delta = MAX2(max_delta_x, max_delta_y); - - buckets_per_side = MIN2(512, 0.9f / max_delta); - - if (buckets_per_side == 0) { - /* happens when some segment fills the whole bounding box across some of dimension */ - - buckets_per_side = 1; - } - - tot_bucket = buckets_per_side * buckets_per_side; - bucket_size = 1.0f / buckets_per_side; - - /* pre-compute multipliers, to save mathematical operations in loops */ - bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size); - bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size); - - /* fill in buckets' edges */ - buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets"); - - for (i = 0; i < tot_feather_point; i++) { - int start = i, end = i + 1; - int start_bucket_index, end_bucket_index; - - if (end == tot_feather_point) { - if (spline->flag & MASK_SPLINE_CYCLIC) - end = 0; - else - break; - } - - start_bucket_index = BUCKET_INDEX(feather_points[start]); - end_bucket_index = BUCKET_INDEX(feather_points[end]); - - feather_bucket_add_edge(&buckets[start_bucket_index], start, end); - - if (start_bucket_index != end_bucket_index) { - FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; - FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; - - feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side, - &diagonal_bucket_a, &diagonal_bucket_b); - - feather_bucket_add_edge(end_bucket, start, end); - feather_bucket_add_edge(diagonal_bucket_a, start, end); - feather_bucket_add_edge(diagonal_bucket_a, start, end); - } - } - - /* check all edges for intersection with edges from their buckets */ - for (i = 0; i < tot_feather_point; i++) { - int cur_a = i, cur_b = i + 1; - int start_bucket_index, end_bucket_index; - - FeatherEdgesBucket *start_bucket; - - if (cur_b == tot_feather_point) - cur_b = 0; - - start_bucket_index = BUCKET_INDEX(feather_points[cur_a]); - end_bucket_index = BUCKET_INDEX(feather_points[cur_b]); - - start_bucket = &buckets[start_bucket_index]; - - feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b); - - if (start_bucket_index != end_bucket_index) { - FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; - FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; - - feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side, - &diagonal_bucket_a, &diagonal_bucket_b); - - feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b); - feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b); - feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b); - } - } - - /* free buckets */ - for (i = 0; i < tot_bucket; i++) { - if (buckets[i].segments) - MEM_freeN(buckets[i].segments); - } - - MEM_freeN(buckets); - -#undef BUCKET_INDEX -} - -/** - * values align with #BKE_mask_spline_differentiate_with_resolution_ex - * when \a resol arguments match. - */ -float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline, - int *tot_feather_point, - const unsigned int resol, - const int do_feather_isect - ))[2] -{ - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - MaskSplinePoint *point, *prev; - float (*feather)[2], (*fp)[2]; - - const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); - int a; - - /* tot+1 because of 'forward_diff_bezier' function */ - feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points"); - - a = spline->tot_point - 1; - if (spline->flag & MASK_SPLINE_CYCLIC) - a++; - - prev = points_array; - point = prev + 1; - - while (a--) { - /* BezTriple *prevbezt; */ /* UNUSED */ - /* BezTriple *bezt; */ /* UNUSED */ - int j; - - if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) - point = points_array; - - - /* prevbezt = &prev->bezt; */ - /* bezt = &point->bezt; */ - - for (j = 0; j < resol; j++, fp++) { - float u = (float) j / resol, weight; - float co[2], n[2]; - - /* TODO - these calls all calculate similar things - * could be unified for some speed */ - BKE_mask_point_segment_co(spline, prev, u, co); - BKE_mask_point_normal(spline, prev, u, n); - weight = BKE_mask_point_weight(spline, prev, u); - - madd_v2_v2v2fl(*fp, co, n, weight); - } - - if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { - float u = 1.0f, weight; - float co[2], n[2]; - - BKE_mask_point_segment_co(spline, prev, u, co); - BKE_mask_point_normal(spline, prev, u, n); - weight = BKE_mask_point_weight(spline, prev, u); - - madd_v2_v2v2fl(*fp, co, n, weight); - } - - prev = point; - point++; - } - - *tot_feather_point = tot; - - if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { - BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); - } - - return feather; -} - -float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height, - int *tot_feather_point, const int do_feather_isect))[2] -{ - unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); - - return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, tot_feather_point, resol, do_feather_isect); -} - -float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2] -{ - return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point, TRUE); -} - -float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] -{ - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - - int i, tot = 0; - float (*feather)[2], (*fp)[2]; - - /* count */ - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &points_array[i]; - - tot += point->tot_uw + 1; - } - - /* create data */ - feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); - - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &points_array[i]; - BezTriple *bezt = &point->bezt; - float weight, n[2]; - int j; - - BKE_mask_point_normal(spline, point, 0.0f, n); - weight = BKE_mask_point_weight(spline, point, 0.0f); - - madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); - fp++; - - for (j = 0; j < point->tot_uw; j++) { - float u = point->uw[j].u; - float co[2]; - - BKE_mask_point_segment_co(spline, point, u, co); - BKE_mask_point_normal(spline, point, u, n); - weight = BKE_mask_point_weight(spline, point, u); - - madd_v2_v2v2fl(*fp, co, n, weight); - fp++; - } - } - - *tot_feather_point = tot; - - return feather; -} - void BKE_mask_point_direction_switch(MaskSplinePoint *point) { const int tot_uw = point->tot_uw; @@ -1069,73 +484,6 @@ void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_di } } -float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, - int width, int height, - unsigned int *tot_feather_point) -{ - float *feather, *fp; - unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); - unsigned int i; - - feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); - - for (i = 0; i < resol; i++, fp += 2) { - float u = (float)(i % resol) / resol, weight; - float co[2], n[2]; - - BKE_mask_point_segment_co(spline, point, u, co); - BKE_mask_point_normal(spline, point, u, n); - weight = BKE_mask_point_weight(spline, point, u); - - fp[0] = co[0] + n[0] * weight; - fp[1] = co[1] + n[1] * weight; - } - - *tot_feather_point = resol; - - return feather; -} - -float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_feather_point) -{ - return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point); -} - -float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, - int width, int height, unsigned int *tot_diff_point) -{ - MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - - BezTriple *bezt, *bezt_next; - float *diff_points, *fp; - int j, resol = BKE_mask_spline_resolution(spline, width, height); - - bezt = &point->bezt; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); - - if (!bezt_next) - return NULL; - - /* resol+1 because of 'forward_diff_bezier' function */ - *tot_diff_point = resol + 1; - diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets"); - - for (j = 0; j < 2; j++) { - BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j], - bezt_next->vec[0][j], bezt_next->vec[1][j], - fp + j, resol, 2 * sizeof(float)); - } - - copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]); - - return diff_points; -} - -float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_diff_point) -{ - return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point); -} - void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2]) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); @@ -1143,7 +491,7 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float BezTriple *bezt = &point->bezt, *bezt_next; float q0[2], q1[2], q2[2], r0[2], r1[2]; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { copy_v2_v2(co, bezt->vec[1]); @@ -1167,7 +515,7 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, BezTriple *bezt = &point->bezt, *bezt_next; float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { BKE_mask_point_handle(point, vec); @@ -1202,7 +550,7 @@ float BKE_mask_point_weight_scalar(MaskSpline *spline, MaskSplinePoint *point, c MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); BezTriple *bezt = &point->bezt, *bezt_next; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { return bezt->weight; @@ -1223,7 +571,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, const fl MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); BezTriple *bezt = &point->bezt, *bezt_next; - bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { return bezt->weight; @@ -1562,25 +910,13 @@ void BKE_mask_layer_free_list(ListBase *masklayers) } } -void BKE_mask_free(Mask *mask) +/** free for temp copy, but don't manage unlinking from other pointers */ +void BKE_mask_free_nolib(Mask *mask) { BKE_mask_layer_free_list(&mask->masklayers); } - -static void ntree_unlink_mask_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree) -{ - ID *id = (ID *)calldata; - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id == id) { - node->id = NULL; - } - } -} - -void BKE_mask_unlink(Main *bmain, Mask *mask) +void BKE_mask_free(Main *bmain, Mask *mask) { bScreen *scr; ScrArea *area; @@ -1626,24 +962,15 @@ void BKE_mask_unlink(Main *bmain, Mask *mask) } SEQ_END } - - - if (scene->nodetree) { - bNode *node; - for (node = scene->nodetree->nodes.first; node; node = node->next) { - if (node->id == &mask->id) { - node->id = NULL; - } - } - } } { bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT); - treetype->foreach_nodetree(bmain, (void *)mask, &ntree_unlink_mask_cb); + treetype->foreach_nodetree(bmain, (void *)mask, &BKE_node_tree_unlink_id_cb); } - BKE_libblock_free(&bmain->mask, mask); + /* free mask data */ + BKE_mask_layer_free_list(&mask->masklayers); } void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2]) @@ -1663,14 +990,26 @@ void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float fra } void BKE_mask_coord_from_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2]) { - int width, height; + float aspx, aspy; float frame_size[2]; /* scaling for the clip */ - BKE_movieclip_get_size(clip, user, &width, &height); + BKE_movieclip_get_size_fl(clip, user, frame_size); + BKE_movieclip_get_aspect(clip, &aspx, &aspy); - frame_size[0] = (float)width; - frame_size[1] = (float)height; + frame_size[1] *= (aspy / aspx); + + BKE_mask_coord_from_frame(r_co, co, frame_size); +} +void BKE_mask_coord_from_image(Image *image, ImageUser *iuser, float r_co[2], const float co[2]) +{ + float aspx, aspy; + float frame_size[2]; + + BKE_image_get_size_fl(image, iuser, frame_size); + BKE_image_get_aspect(image, &aspx, &aspy); + + frame_size[1] *= (aspy / aspx); BKE_mask_coord_from_frame(r_co, co, frame_size); } @@ -1693,14 +1032,27 @@ void BKE_mask_coord_to_frame(float r_co[2], const float co[2], const float frame } void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2]) { - int width, height; + float aspx, aspy; + float frame_size[2]; + + /* scaling for the clip */ + BKE_movieclip_get_size_fl(clip, user, frame_size); + BKE_movieclip_get_aspect(clip, &aspx, &aspy); + + frame_size[1] /= (aspy / aspx); + + BKE_mask_coord_to_frame(r_co, co, frame_size); +} +void BKE_mask_coord_to_image(Image *image, ImageUser *iuser, float r_co[2], const float co[2]) +{ + float aspx, aspy; float frame_size[2]; /* scaling for the clip */ - BKE_movieclip_get_size(clip, user, &width, &height); + BKE_image_get_size_fl(image, iuser, frame_size); + BKE_image_get_aspect(image, &aspx, &aspy); - frame_size[0] = (float)width; - frame_size[1] = (float)height; + frame_size[1] /= (aspy / aspx); BKE_mask_coord_to_frame(r_co, co, frame_size); } @@ -1737,7 +1089,8 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[ return FALSE; } -int BKE_mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2]) +/* could make external but for now its only used internally */ +static int mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2]) { float parent_co[2]; @@ -1847,17 +1200,6 @@ void BKE_mask_calc_handle_point(MaskSpline *spline, MaskSplinePoint *point) mask_calc_point_handle(point, point_prev, point_next); } -static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dist) -{ - if (!equals_v2v2(v2, v1)) { - float nor[2]; - - sub_v2_v2v2(nor, v1, v2); - normalize_v2(nor); - madd_v2_v2v2fl(v1, v2, nor, dist); - } -} - void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *point, const float u) { /* TODO! - make this interpolate between siblings - not always midpoint! */ @@ -1899,8 +1241,8 @@ void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *p length_average /= (float)length_tot; weight_average /= (float)length_tot; - enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); - enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); point->bezt.weight = weight_average; } } @@ -1932,8 +1274,8 @@ void BKE_mask_calc_handle_point_auto(MaskSpline *spline, MaskSplinePoint *point, /* preserve length by applying it back */ if (do_recalc_length == FALSE) { - enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); - enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); } } @@ -2088,7 +1430,7 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do *point_deform = *point; point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; - if (BKE_mask_evaluate_parent_delta(&point->parent, ctime, delta)) { + if (mask_evaluate_parent_delta(&point->parent, ctime, delta)) { add_v2_v2(point_deform->bezt.vec[0], delta); add_v2_v2(point_deform->bezt.vec[1], delta); add_v2_v2(point_deform->bezt.vec[2], delta); @@ -2183,7 +1525,7 @@ void BKE_mask_parent_init(MaskParent *parent) } -/* *** own animation/shapekey implimentation *** +/* *** own animation/shapekey implementation *** * BKE_mask_layer_shape_XXX */ int BKE_mask_layer_shape_totvert(MaskLayer *masklay) diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c new file mode 100644 index 00000000000..4a8601df0b8 --- /dev/null +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -0,0 +1,863 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/mask_evaluate.c + * \ingroup bke + * + * Functions for evaluating the mask beziers into points for the outline and feather. + */ + +#include <stddef.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "DNA_mask_types.h" +#include "DNA_node_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_movieclip_types.h" +#include "DNA_tracking_types.h" +#include "DNA_sequence_types.h" + +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_mask.h" +#include "BKE_node.h" +#include "BKE_sequencer.h" +#include "BKE_tracking.h" +#include "BKE_movieclip.h" + + +unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) +{ + float max_segment = 0.01f; + unsigned int i, resol = 1; + + if (width != 0 && height != 0) { + max_segment = 1.0f / (float)maxi(width, height); + } + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + BezTriple *bezt_curr, *bezt_next; + float a, b, c, len; + unsigned int cur_resol; + + bezt_curr = &point->bezt; + bezt_next = BKE_mask_spline_point_next_bezt(spline, spline->points, point); + + if (bezt_next == NULL) { + break; + } + + a = len_v3v3(bezt_curr->vec[1], bezt_curr->vec[2]); + b = len_v3v3(bezt_curr->vec[2], bezt_next->vec[0]); + c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]); + + len = a + b + c; + cur_resol = len / max_segment; + + resol = MAX2(resol, cur_resol); + + if (resol >= MASK_RESOL_MAX) { + break; + } + } + + return CLAMPIS(resol, 1, MASK_RESOL_MAX); +} + +unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height) +{ + const float max_segment = 0.005; + unsigned int resol = BKE_mask_spline_resolution(spline, width, height); + float max_jump = 0.0f; + int i; + + /* avoid checking the featrher if we already hit the maximum value */ + if (resol >= MASK_RESOL_MAX) { + return MASK_RESOL_MAX; + } + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + float prev_u, prev_w; + int j; + + prev_u = 0.0f; + prev_w = point->bezt.weight; + + for (j = 0; j < point->tot_uw; j++) { + const float w_diff = (point->uw[j].w - prev_w); + const float u_diff = (point->uw[j].u - prev_u); + + /* avoid divide by zero and very high values, + * though these get clamped eventually */ + if (u_diff > FLT_EPSILON) { + float jump = fabsf(w_diff / u_diff); + + max_jump = MAX2(max_jump, jump); + } + + prev_u = point->uw[j].u; + prev_w = point->uw[j].w; + } + } + + resol += max_jump / max_segment; + + return CLAMPIS(resol, 1, MASK_RESOL_MAX); +} + +int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol) +{ + if (spline->flag & MASK_SPLINE_CYCLIC) { + return spline->tot_point * resol; + } + else { + return ((spline->tot_point - 1) * resol) + 1; + } +} + +float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline, + int *tot_diff_point, + const unsigned int resol + ))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + MaskSplinePoint *point_curr, *point_prev; + float (*diff_points)[2], (*fp)[2]; + const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); + int a; + + if (spline->tot_point <= 1) { + /* nothing to differentiate */ + *tot_diff_point = 0; + return NULL; + } + + /* len+1 because of 'forward_diff_bezier' function */ + *tot_diff_point = tot; + diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets"); + + a = spline->tot_point - 1; + if (spline->flag & MASK_SPLINE_CYCLIC) + a++; + + point_prev = points_array; + point_curr = point_prev + 1; + + while (a--) { + BezTriple *bezt_prev; + BezTriple *bezt_curr; + int j; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) + point_curr = points_array; + + bezt_prev = &point_prev->bezt; + bezt_curr = &point_curr->bezt; + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j], + bezt_curr->vec[0][j], bezt_curr->vec[1][j], + &(*fp)[j], resol, 2 * sizeof(float)); + } + + fp += resol; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { + copy_v2_v2(*fp, bezt_curr->vec[1]); + } + + point_prev = point_curr; + point_curr++; + } + + return diff_points; +} + +float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height, + int *tot_diff_point + ))[2] +{ + int unsigned resol = BKE_mask_spline_resolution(spline, width, height); + + return BKE_mask_spline_differentiate_with_resolution_ex(spline, tot_diff_point, resol); +} + +float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2] +{ + return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point); +} + +/* ** feather points self-intersection collapse routine ** */ + +typedef struct FeatherEdgesBucket { + int tot_segment; + int (*segments)[2]; + int alloc_segment; +} FeatherEdgesBucket; + +static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end) +{ + const int alloc_delta = 256; + + if (bucket->tot_segment >= bucket->alloc_segment) { + if (!bucket->segments) { + bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments"); + } + else { + bucket->segments = MEM_reallocN(bucket->segments, + (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); + } + + bucket->alloc_segment += alloc_delta; + } + + bucket->segments[bucket->tot_segment][0] = start; + bucket->segments[bucket->tot_segment][1] = end; + + bucket->tot_segment++; +} + +static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket, + int cur_a, int cur_b) +{ + int i; + + float *v1 = (float *) feather_points[cur_a]; + float *v2 = (float *) feather_points[cur_b]; + + for (i = 0; i < bucket->tot_segment; i++) { + int check_a = bucket->segments[i][0]; + int check_b = bucket->segments[i][1]; + + float *v3 = (float *) feather_points[check_a]; + float *v4 = (float *) feather_points[check_b]; + + if (check_a >= cur_a - 1 || cur_b == check_a) + continue; + + if (isect_seg_seg_v2(v1, v2, v3, v4)) { + int k; + float p[2]; + float min_a[2], max_a[2]; + float min_b[2], max_b[2]; + + isect_seg_seg_v2_point(v1, v2, v3, v4, p); + + INIT_MINMAX2(min_a, max_a); + INIT_MINMAX2(min_b, max_b); + + /* collapse loop with smaller AABB */ + for (k = 0; k < tot_feather_point; k++) { + if (k >= check_b && k <= cur_a) { + DO_MINMAX2(feather_points[k], min_a, max_a); + } + else { + DO_MINMAX2(feather_points[k], min_b, max_b); + } + } + + if (max_a[0] - min_a[0] < max_b[0] - min_b[0] || + max_a[1] - min_a[1] < max_b[1] - min_b[1]) + { + for (k = check_b; k <= cur_a; k++) { + copy_v2_v2(feather_points[k], p); + } + } + else { + for (k = 0; k <= check_a; k++) { + copy_v2_v2(feather_points[k], p); + } + + if (cur_b != 0) { + for (k = cur_b; k < tot_feather_point; k++) { + copy_v2_v2(feather_points[k], p); + } + } + } + } + } +} + +static int feather_bucket_index_from_coord(float co[2], const float min[2], const float bucket_scale[2], + const int buckets_per_side) +{ + int x = (int) ((co[0] - min[0]) * bucket_scale[0]); + int y = (int) ((co[1] - min[1]) * bucket_scale[1]); + + if (x == buckets_per_side) + x--; + + if (y == buckets_per_side) + y--; + + return y * buckets_per_side + x; +} + +static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index, + int buckets_per_side, FeatherEdgesBucket **diagonal_bucket_a_r, + FeatherEdgesBucket **diagonal_bucket_b_r) +{ + int start_bucket_x = start_bucket_index % buckets_per_side; + int start_bucket_y = start_bucket_index / buckets_per_side; + + int end_bucket_x = end_bucket_index % buckets_per_side; + int end_bucket_y = end_bucket_index / buckets_per_side; + + int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x; + int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x; + + *diagonal_bucket_a_r = &buckets[diagonal_bucket_a_index]; + *diagonal_bucket_b_r = &buckets[diagonal_bucket_b_index]; +} + +void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feather_points)[2], const int tot_feather_point) +{ +#define BUCKET_INDEX(co) \ + feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side) + + int buckets_per_side, tot_bucket; + float bucket_size, bucket_scale[2]; + + FeatherEdgesBucket *buckets; + + int i; + float min[2], max[2]; + float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta; + + if (tot_feather_point < 4) { + /* self-intersection works only for quads at least, + * in other cases polygon can't be self-intersecting anyway + */ + + return; + } + + /* find min/max corners of mask to build buckets in that space */ + INIT_MINMAX2(min, max); + + for (i = 0; i < tot_feather_point; i++) { + int next = i + 1; + float delta; + + DO_MINMAX2(feather_points[i], min, max); + + if (next == tot_feather_point) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = 0; + else + break; + } + + delta = fabsf(feather_points[i][0] - feather_points[next][0]); + if (delta > max_delta_x) + max_delta_x = delta; + + delta = fabsf(feather_points[i][1] - feather_points[next][1]); + if (delta > max_delta_y) + max_delta_y = delta; + } + + /* prevent divisionsby zero by ensuring bounding box is not collapsed */ + if (max[0] - min[0] < FLT_EPSILON) { + max[0] += 0.01f; + min[0] -= 0.01f; + } + + if (max[1] - min[1] < FLT_EPSILON) { + max[1] += 0.01f; + min[1] -= 0.01f; + } + + /* use dynamically calculated buckets per side, so we likely wouldn't + * run into a situation when segment doesn't fit two buckets which is + * pain collecting candidates for intersection + */ + + max_delta_x /= max[0] - min[0]; + max_delta_y /= max[1] - min[1]; + + max_delta = MAX2(max_delta_x, max_delta_y); + + buckets_per_side = MIN2(512, 0.9f / max_delta); + + if (buckets_per_side == 0) { + /* happens when some segment fills the whole bounding box across some of dimension */ + + buckets_per_side = 1; + } + + tot_bucket = buckets_per_side * buckets_per_side; + bucket_size = 1.0f / buckets_per_side; + + /* pre-compute multipliers, to save mathematical operations in loops */ + bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size); + bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size); + + /* fill in buckets' edges */ + buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets"); + + for (i = 0; i < tot_feather_point; i++) { + int start = i, end = i + 1; + int start_bucket_index, end_bucket_index; + + if (end == tot_feather_point) { + if (spline->flag & MASK_SPLINE_CYCLIC) + end = 0; + else + break; + } + + start_bucket_index = BUCKET_INDEX(feather_points[start]); + end_bucket_index = BUCKET_INDEX(feather_points[end]); + + feather_bucket_add_edge(&buckets[start_bucket_index], start, end); + + if (start_bucket_index != end_bucket_index) { + FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; + FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; + + feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side, + &diagonal_bucket_a, &diagonal_bucket_b); + + feather_bucket_add_edge(end_bucket, start, end); + feather_bucket_add_edge(diagonal_bucket_a, start, end); + feather_bucket_add_edge(diagonal_bucket_a, start, end); + } + } + + /* check all edges for intersection with edges from their buckets */ + for (i = 0; i < tot_feather_point; i++) { + int cur_a = i, cur_b = i + 1; + int start_bucket_index, end_bucket_index; + + FeatherEdgesBucket *start_bucket; + + if (cur_b == tot_feather_point) + cur_b = 0; + + start_bucket_index = BUCKET_INDEX(feather_points[cur_a]); + end_bucket_index = BUCKET_INDEX(feather_points[cur_b]); + + start_bucket = &buckets[start_bucket_index]; + + feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b); + + if (start_bucket_index != end_bucket_index) { + FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; + FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; + + feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side, + &diagonal_bucket_a, &diagonal_bucket_b); + + feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b); + feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b); + feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b); + } + } + + /* free buckets */ + for (i = 0; i < tot_bucket; i++) { + if (buckets[i].segments) + MEM_freeN(buckets[i].segments); + } + + MEM_freeN(buckets); + +#undef BUCKET_INDEX +} + +/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */ +static float (*mask_spline_feather_differentiated_points_with_resolution_ex__even(MaskSpline *spline, + int *tot_feather_point, + const unsigned int resol, + const int do_feather_isect + ))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + MaskSplinePoint *point_curr, *point_prev; + float (*feather)[2], (*fp)[2]; + + const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); + int a; + + /* tot+1 because of 'forward_diff_bezier' function */ + feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points"); + + a = spline->tot_point - 1; + if (spline->flag & MASK_SPLINE_CYCLIC) + a++; + + point_prev = points_array; + point_curr = point_prev + 1; + + while (a--) { + /* BezTriple *bezt_prev; */ /* UNUSED */ + /* BezTriple *bezt_curr; */ /* UNUSED */ + int j; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) + point_curr = points_array; + + + /* bezt_prev = &point_prev->bezt; */ + /* bezt_curr = &point_curr->bezt; */ + + for (j = 0; j < resol; j++, fp++) { + float u = (float) j / resol, weight; + float co[2], n[2]; + + /* TODO - these calls all calculate similar things + * could be unified for some speed */ + BKE_mask_point_segment_co(spline, point_prev, u, co); + BKE_mask_point_normal(spline, point_prev, u, n); + weight = BKE_mask_point_weight(spline, point_prev, u); + + madd_v2_v2v2fl(*fp, co, n, weight); + } + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { + float u = 1.0f, weight; + float co[2], n[2]; + + BKE_mask_point_segment_co(spline, point_prev, u, co); + BKE_mask_point_normal(spline, point_prev, u, n); + weight = BKE_mask_point_weight(spline, point_prev, u); + + madd_v2_v2v2fl(*fp, co, n, weight); + } + + point_prev = point_curr; + point_curr++; + } + + *tot_feather_point = tot; + + if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { + BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); + } + + return feather; +} + +/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */ +static float (*mask_spline_feather_differentiated_points_with_resolution_ex__double(MaskSpline *spline, + int *tot_feather_point, + const unsigned int resol, + const int do_feather_isect + ))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + MaskSplinePoint *point_curr, *point_prev; + float (*feather)[2], (*fp)[2]; + const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); + int a; + + if (spline->tot_point <= 1) { + /* nothing to differentiate */ + *tot_feather_point = 0; + return NULL; + } + + /* len+1 because of 'forward_diff_bezier' function */ + *tot_feather_point = tot; + feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets"); + + a = spline->tot_point - 1; + if (spline->flag & MASK_SPLINE_CYCLIC) + a++; + + point_prev = points_array; + point_curr = point_prev + 1; + + while (a--) { + BezTriple local_prevbezt; + BezTriple local_bezt; + float point_prev_n[2], point_curr_n[2], tvec[2]; + float weight_prev, weight_curr; + float len_base, len_feather, len_scalar; + + BezTriple *bezt_prev; + BezTriple *bezt_curr; + int j; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) + point_curr = points_array; + + bezt_prev = &point_prev->bezt; + bezt_curr = &point_curr->bezt; + + /* modified copy for feather */ + local_prevbezt = *bezt_prev; + local_bezt = *bezt_curr; + + bezt_prev = &local_prevbezt; + bezt_curr = &local_bezt; + + /* calc the normals */ + sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]); + normalize_v2(tvec); + point_prev_n[0] = -tvec[1]; + point_prev_n[1] = tvec[0]; + + sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]); + normalize_v2(tvec); + point_curr_n[0] = -tvec[1]; + point_curr_n[1] = tvec[0]; + + weight_prev = bezt_prev->weight; + weight_curr = bezt_curr->weight; + + mul_v2_fl(point_prev_n, weight_prev); + mul_v2_fl(point_curr_n, weight_curr); + + /* before we transform verts */ + len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); + + // add_v2_v2(bezt_prev->vec[0], point_prev_n); // not needed + add_v2_v2(bezt_prev->vec[1], point_prev_n); + add_v2_v2(bezt_prev->vec[2], point_prev_n); + + add_v2_v2(bezt_curr->vec[0], point_curr_n); + add_v2_v2(bezt_curr->vec[1], point_curr_n); + // add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed + + len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); + + /* scale by chane in length */ + len_scalar = len_feather / len_base; + dist_ensure_v2_v2fl(bezt_prev->vec[2], bezt_prev->vec[1], len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1])); + dist_ensure_v2_v2fl(bezt_curr->vec[0], bezt_curr->vec[1], len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1])); + + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j], + bezt_curr->vec[0][j], bezt_curr->vec[1][j], + &(*fp)[j], resol, 2 * sizeof(float)); + } + + + /* scale by the uw's */ + if (point_prev->tot_uw) { + for (j = 0; j < resol; j++, fp++) { + float u = (float) j / resol; + float weight_uw, weight_scalar; + float co[2]; + + /* TODO - these calls all calculate similar things + * could be unified for some speed */ + BKE_mask_point_segment_co(spline, point_prev, u, co); + + weight_uw = BKE_mask_point_weight(spline, point_prev, u); + weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u); + + dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar)); + } + } + else { + fp += resol; + } + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { + copy_v2_v2(*fp, bezt_curr->vec[1]); + } + + point_prev = point_curr; + point_curr++; + } + + if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { + BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); + } + + return feather; +} + +/** + * values align with #BKE_mask_spline_differentiate_with_resolution_ex + * when \a resol arguments match. + */ +float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline, + int *tot_feather_point, + const unsigned int resol, + const int do_feather_isect + ))[2] +{ + switch (spline->offset_mode) { + case MASK_SPLINE_OFFSET_EVEN: + return mask_spline_feather_differentiated_points_with_resolution_ex__even(spline, tot_feather_point, resol, do_feather_isect); + break; + case MASK_SPLINE_OFFSET_SMOOTH: + default: + return mask_spline_feather_differentiated_points_with_resolution_ex__double(spline, tot_feather_point, resol, do_feather_isect); + break; + } +} + +float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height, + int *tot_feather_point, const int do_feather_isect))[2] +{ + unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); + + return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, tot_feather_point, resol, do_feather_isect); +} + +float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2] +{ + return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point, TRUE); +} + +float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + int i, tot = 0; + float (*feather)[2], (*fp)[2]; + + /* count */ + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &points_array[i]; + + tot += point->tot_uw + 1; + } + + /* create data */ + feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &points_array[i]; + BezTriple *bezt = &point->bezt; + float weight, n[2]; + int j; + + BKE_mask_point_normal(spline, point, 0.0f, n); + weight = BKE_mask_point_weight(spline, point, 0.0f); + + madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); + fp++; + + for (j = 0; j < point->tot_uw; j++) { + float u = point->uw[j].u; + float co[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + madd_v2_v2v2fl(*fp, co, n, weight); + fp++; + } + } + + *tot_feather_point = tot; + + return feather; +} + +/* *** mask point functions which involve evaluation *** */ +float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, + int width, int height, + unsigned int *tot_feather_point) +{ + float *feather, *fp; + unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); + unsigned int i; + + feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); + + for (i = 0; i < resol; i++, fp += 2) { + float u = (float)(i % resol) / resol, weight; + float co[2], n[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + fp[0] = co[0] + n[0] * weight; + fp[1] = co[1] + n[1] * weight; + } + + *tot_feather_point = resol; + + return feather; +} + +float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_feather_point) +{ + return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point); +} + +float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, + int width, int height, unsigned int *tot_diff_point) +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + + BezTriple *bezt, *bezt_next; + float *diff_points, *fp; + int j, resol = BKE_mask_spline_resolution(spline, width, height); + + bezt = &point->bezt; + bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); + + if (!bezt_next) + return NULL; + + /* resol+1 because of 'forward_diff_bezier' function */ + *tot_diff_point = resol + 1; + diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets"); + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j], + bezt_next->vec[0][j], bezt_next->vec[1][j], + fp + j, resol, 2 * sizeof(float)); + } + + copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]); + + return diff_points; +} + +float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_diff_point) +{ + return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point); +} diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index d39be3b8ed6..13ad9962aff 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -26,6 +26,46 @@ /** \file blender/blenkernel/intern/mask_rasterize.c * \ingroup bke + * + * This module exposes a rasterizer that works as a black box - implementation details are confined to this file, + * + * The basic method to access is: + * - create & initialize a handle from a #Mask datablock. + * - execute pixel lookups. + * - free the handle. + * + * This file is admittedly a bit confusticated, in quite few areas speed was chosen over readability, + * though it is commented - so shouldn't be so hard to see whats going on. + * + * + * Implementation: + * + * To rasterize the mask its converted into geometry that use a ray-cast for each pixel lookup. + * + * Initially 'kdopbvh' was used but this ended up being too slow. + * + * To gain some extra speed we take advantage of a few shortcuts that can be made rasterizing masks specifically. + * - all triangles are known to be completely white - so no depth check is done on triangle intersection. + * - all quads are known to be feather outlines - the 1 and 0 depths are known by the vertex order in the quad, + * - there is no color - just a value for each mask pixel. + * - the mask spacial structure always maps to space 0-1 on X and Y axis. + * - bucketing is used to speed up lookups for geometry. + * + * Other Details: + * - used unsigned values all over for some extra speed on some arch's. + * - anti-aliasing is faked, just ensuring at least one pixel feather - avoids oversampling. + * - initializing the spacial structure doesn't need to be as optimized as pixel lookups are. + * - mask lookups need not be pixel aligned so any sub-pixel values from x/y (0 - 1), can be found. + * (perhaps masks can be used as a vector texture in 3D later on) + * + * + * Currently, to build the spacial structure we have to calculate the total number of faces ahead of time. + * + * This is getting a bit complicated with the addition of unfilled splines and end capping - + * If large changes are needed here we would be better off using an iterable + * BLI_mempool for triangles and converting to a contiguous array afterwards. + * + * - Campbell */ #include "MEM_guardedalloc.h" @@ -213,9 +253,9 @@ void BKE_maskrasterize_handle_free(MaskRasterHandle *mr_handle) } -void maskrasterize_spline_differentiate_point_outset(float (*diff_feather_points)[2], float (*diff_points)[2], - const unsigned int tot_diff_point, const float ofs, - const short do_test) +static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather_points)[2], float (*diff_points)[2], + const unsigned int tot_diff_point, const float ofs, + const short do_test) { unsigned int k_prev = tot_diff_point - 2; unsigned int k_curr = tot_diff_point - 1; @@ -370,8 +410,8 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) { MemArena *arena = BLI_memarena_new(1 << 16, __func__); - const float bucket_dim_x = BLI_RCT_SIZE_X(&layer->bounds); - const float bucket_dim_y = BLI_RCT_SIZE_Y(&layer->bounds); + const float bucket_dim_x = BLI_rctf_size_x(&layer->bounds); + const float bucket_dim_y = BLI_rctf_size_y(&layer->bounds); layer->buckets_x = (bucket_dim_x / pixel_size) / (float)BUCKET_PIXELS_PER_CELL; layer->buckets_y = (bucket_dim_y / pixel_size) / (float)BUCKET_PIXELS_PER_CELL; @@ -1168,7 +1208,7 @@ static float maskrasterize_layer_isect(unsigned int *face, float (*cos)[3], cons /* needs work */ #if 1 - /* quad check fails for bowtie, so keep using 2 tri checks */ + /* quad check fails for bow-tie, so keep using 2 tri checks */ //if (isect_point_quad_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]], cos[face[3]])) if (isect_point_tri_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]]) || isect_point_tri_v2(xy, cos[face[0]], cos[face[2]], cos[face[3]])) @@ -1176,7 +1216,7 @@ static float maskrasterize_layer_isect(unsigned int *face, float (*cos)[3], cons return maskrasterize_layer_z_depth_quad(xy, cos[face[0]], cos[face[1]], cos[face[2]], cos[face[3]]); } #elif 1 - /* don't use isect_point_tri_v2_cw because we could have bowtie quads */ + /* don't use isect_point_tri_v2_cw because we could have bow-tie quads */ if (isect_point_tri_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]])) { return maskrasterize_layer_z_depth_tri(xy, cos[face[0]], cos[face[1]], cos[face[2]]); @@ -1196,7 +1236,7 @@ static float maskrasterize_layer_isect(unsigned int *face, float (*cos)[3], cons BLI_INLINE unsigned int layer_bucket_index_from_xy(MaskRasterLayer *layer, const float xy[2]) { - BLI_assert(BLI_in_rctf_v(&layer->bounds, xy)); + BLI_assert(BLI_rctf_isect_pt_v(&layer->bounds, xy)); return ( (unsigned int)((xy[0] - layer->bounds.xmin) * layer->buckets_xy_scalar[0])) + (((unsigned int)((xy[1] - layer->bounds.ymin) * layer->buckets_xy_scalar[1])) * layer->buckets_x); @@ -1233,7 +1273,7 @@ static float layer_bucket_depth_from_xy(MaskRasterLayer *layer, const float xy[2 float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float xy[2]) { /* can't do this because some layers may invert */ - /* if (BLI_in_rctf_v(&mr_handle->bounds, xy)) */ + /* if (BLI_rctf_isect_pt_v(&mr_handle->bounds, xy)) */ const unsigned int layers_tot = mr_handle->layers_tot; unsigned int i; @@ -1246,7 +1286,7 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x float value_layer; /* also used as signal for unused layer (when render is disabled) */ - if (layer->alpha != 0.0f && BLI_in_rctf_v(&layer->bounds, xy)) { + if (layer->alpha != 0.0f && BLI_rctf_isect_pt_v(&layer->bounds, xy)) { value_layer = 1.0f - layer_bucket_depth_from_xy(layer, xy); switch (layer->falloff) { @@ -1282,9 +1322,12 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x } switch (layer->blend) { - case MASK_BLEND_MERGE: + case MASK_BLEND_MERGE_ADD: value += value_layer * (1.0f - value); break; + case MASK_BLEND_MERGE_SUBTRACT: + value -= value_layer * value; + break; case MASK_BLEND_ADD: value += value_layer; break; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index e5f392e4bce..bea0e33da9a 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -80,12 +80,18 @@ void init_def_material(void) /* not material itself */ void BKE_material_free(Material *ma) { + BKE_material_free_ex(ma, TRUE); +} + +/* not material itself */ +void BKE_material_free_ex(Material *ma, int do_id_user) +{ MTex *mtex; int a; for (a = 0; a < MAX_MTEX; a++) { mtex = ma->mtex[a]; - if (mtex && mtex->tex) mtex->tex->id.us--; + if (do_id_user && mtex && mtex->tex) mtex->tex->id.us--; if (mtex) MEM_freeN(mtex); } @@ -101,7 +107,7 @@ void BKE_material_free(Material *ma) /* is no lib link block, but material extension */ if (ma->nodetree) { - ntreeFreeTree(ma->nodetree); + ntreeFreeTree_ex(ma->nodetree, do_id_user); MEM_freeN(ma->nodetree); } @@ -235,7 +241,7 @@ Material *BKE_material_copy(Material *ma) if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview); if (ma->nodetree) { - man->nodetree = ntreeCopyTree(ma->nodetree); /* 0 == full new tree */ + man->nodetree = ntreeCopyTree(ma->nodetree); } man->gpumaterial.first = man->gpumaterial.last = NULL; @@ -807,7 +813,7 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type) *totcolp = act; } - // Determine the object/mesh linking + /* Determine the object/mesh linking */ if (assign_type == BKE_MAT_ASSIGN_USERPREF && ob->totcol && ob->actcol) { /* copy from previous material */ bit = ob->matbits[ob->actcol - 1]; @@ -935,7 +941,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) if (ma->texco & (TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM | TEXCO_STRAND | TEXCO_STRESS)) needuv = 1; else if (ma->texco & (TEXCO_GLOB | TEXCO_UV | TEXCO_OBJECT | TEXCO_SPEED)) needuv = 1; - else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW | TEXCO_STICKY)) needuv = 1; + else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW)) needuv = 1; if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT)) needtang = 1; @@ -1321,9 +1327,9 @@ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) r_col[2] = facm * (r_col[2]) + fac * (r_col[2]) / col[2]; break; case MA_RAMP_DIFF: - r_col[0] = facm * (r_col[0]) + fac *fabsf(r_col[0] - col[0]); - r_col[1] = facm * (r_col[1]) + fac *fabsf(r_col[1] - col[1]); - r_col[2] = facm * (r_col[2]) + fac *fabsf(r_col[2] - col[2]); + r_col[0] = facm * (r_col[0]) + fac * fabsf(r_col[0] - col[0]); + r_col[1] = facm * (r_col[1]) + fac * fabsf(r_col[1] - col[1]); + r_col[2] = facm * (r_col[2]) + fac * fabsf(r_col[2] - col[2]); break; case MA_RAMP_DARK: tmp = col[0] + ((1 - col[0]) * facm); @@ -1483,7 +1489,11 @@ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) } } -/* copy/paste buffer, if we had a propper py api that would be better */ +/** + * \brief copy/paste buffer, if we had a proper py api that would be better + * \note matcopybuf.nodetree does _NOT_ use ID's + * \todo matcopybuf.nodetree's node->id's are NOT validated, this will crash! + */ static Material matcopybuf; static short matcopied = 0; @@ -1511,7 +1521,7 @@ void free_matcopybuf(void) matcopybuf.ramp_spec = NULL; if (matcopybuf.nodetree) { - ntreeFreeTree(matcopybuf.nodetree); + ntreeFreeTree_ex(matcopybuf.nodetree, FALSE); MEM_freeN(matcopybuf.nodetree); matcopybuf.nodetree = NULL; } @@ -1537,7 +1547,7 @@ void copy_matcopybuf(Material *ma) matcopybuf.mtex[a] = MEM_dupallocN(mtex); } } - matcopybuf.nodetree = ntreeCopyTree(ma->nodetree); + matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, FALSE); matcopybuf.preview = NULL; matcopybuf.gpumaterial.first = matcopybuf.gpumaterial.last = NULL; matcopied = 1; @@ -1582,7 +1592,7 @@ void paste_matcopybuf(Material *ma) } } - ma->nodetree = ntreeCopyTree(matcopybuf.nodetree); + ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, FALSE); } @@ -1623,7 +1633,7 @@ static void decode_tfaceflag(Material *ma, int flag, int convertall) /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ flag -= 1; - alphablend = flag >> 15; //encoded in the encode_tfaceflag function + alphablend = flag >> 15; /* encoded in the encode_tfaceflag function */ (*game).flag = 0; /* General Material Options */ @@ -2023,8 +2033,7 @@ int do_version_tface(Main *main, int fileload) nowarning = 0; } else - convert_tfacematerial(main, ma); - continue; + convert_tfacematerial(main, ma); continue; } /* no conflicts in this material - 90% of cases diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 5c8ff7ad14f..9eea075c97a 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -163,11 +163,13 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, float (*function)(float, float, float), float p[3], MetaBall *mb, int f); /* Global variables */ +static struct { + float thresh; + int totelem; + MetaElem **mainb; + octal_tree *metaball_tree; +} G_mb = {0}; -static float thresh = 0.6f; -static int totelem = 0; -static MetaElem **mainb; -static octal_tree *metaball_tree = NULL; /* Functions */ void BKE_mball_unlink(MetaBall *mb) @@ -184,7 +186,7 @@ void BKE_mball_unlink(MetaBall *mb) /* do not free mball itself */ void BKE_mball_free(MetaBall *mb) { - BKE_mball_unlink(mb); + BKE_mball_unlink(mb); if (mb->adt) { BKE_free_animdata((ID *)mb); @@ -523,7 +525,7 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - totelem = 0; + G_mb.totelem = 0; /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ if (F_ERROR == BKE_scene_base_iter_next(&sce_iter, 0, NULL, NULL)) @@ -560,13 +562,14 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) basis = ob; basisnr = obnr; } - } + } } } - while (ml) { - if (!(ml->flag & MB_HIDE)) totelem++; - ml = ml->next; + for ( ; ml; ml = ml->next) { + if (!(ml->flag & MB_HIDE)) { + G_mb.totelem++; + } } } } @@ -633,66 +636,68 @@ static float densfunc(MetaElem *ball, float x, float y, float z) mul_m4_v3((float (*)[4])ball->imat, dvec); - if (ball->type == MB_BALL) { - } - else if (ball->type == MB_TUBEX) { - if (dvec[0] > ball->len) dvec[0] -= ball->len; - else if (dvec[0] < -ball->len) dvec[0] += ball->len; - else dvec[0] = 0.0; - } - else if (ball->type == MB_TUBEY) { - if (dvec[1] > ball->len) dvec[1] -= ball->len; - else if (dvec[1] < -ball->len) dvec[1] += ball->len; - else dvec[1] = 0.0; - } - else if (ball->type == MB_TUBEZ) { - if (dvec[2] > ball->len) dvec[2] -= ball->len; - else if (dvec[2] < -ball->len) dvec[2] += ball->len; - else dvec[2] = 0.0; - } - else if (ball->type == MB_TUBE) { - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; - } - else if (ball->type == MB_PLANE) { - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; - if (dvec[1] > ball->expy) dvec[1] -= ball->expy; - else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; - else dvec[1] = 0.0; - } - else if (ball->type == MB_ELIPSOID) { - dvec[0] *= 1 / ball->expx; - dvec[1] *= 1 / ball->expy; - dvec[2] *= 1 / ball->expz; - } - else if (ball->type == MB_CUBE) { - if (dvec[0] > ball->expx) dvec[0] -= ball->expx; - else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; - else dvec[0] = 0.0; - if (dvec[1] > ball->expy) dvec[1] -= ball->expy; - else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; - else dvec[1] = 0.0; - if (dvec[2] > ball->expz) dvec[2] -= ball->expz; - else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; - else dvec[2] = 0.0; - } - - dist2 = len_v3(dvec); - - if (ball->flag & MB_NEGATIVE) { - dist2 = 1.0f - (dist2 / ball->rad2); - if (dist2 < 0.0f) return 0.5f; - - return 0.5f - ball->s * dist2 * dist2 * dist2; + switch (ball->type) { + case MB_BALL: + /* do nothing */ + break; + case MB_TUBE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + break; + case MB_PLANE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + if (dvec[1] > ball->expy) dvec[1] -= ball->expy; + else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; + else dvec[1] = 0.0; + break; + case MB_ELIPSOID: + dvec[0] /= ball->expx; + dvec[1] /= ball->expy; + dvec[2] /= ball->expz; + break; + case MB_CUBE: + if (dvec[0] > ball->expx) dvec[0] -= ball->expx; + else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; + else dvec[0] = 0.0; + + if (dvec[1] > ball->expy) dvec[1] -= ball->expy; + else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; + else dvec[1] = 0.0; + + if (dvec[2] > ball->expz) dvec[2] -= ball->expz; + else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; + else dvec[2] = 0.0; + break; + + /* *** deprecated, could be removed?, do-versioned at least *** */ + case MB_TUBEX: + if (dvec[0] > ball->len) dvec[0] -= ball->len; + else if (dvec[0] < -ball->len) dvec[0] += ball->len; + else dvec[0] = 0.0; + break; + case MB_TUBEY: + if (dvec[1] > ball->len) dvec[1] -= ball->len; + else if (dvec[1] < -ball->len) dvec[1] += ball->len; + else dvec[1] = 0.0; + break; + case MB_TUBEZ: + if (dvec[2] > ball->len) dvec[2] -= ball->len; + else if (dvec[2] < -ball->len) dvec[2] += ball->len; + else dvec[2] = 0.0; + break; + /* *** end deprecated *** */ } - else { - dist2 = 1.0f - (dist2 / ball->rad2); - if (dist2 < 0.0f) return -0.5f; - return ball->s * dist2 * dist2 * dist2 - 0.5f; + dist2 = 1.0f - (len_squared_v3(dvec) / ball->rad2); + + if ((ball->flag & MB_NEGATIVE) == 0) { + return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f; + } + else { + return (dist2 < 0.0f) ? 0.5f : 0.5f - (ball->s * dist2 * dist2 * dist2); } } @@ -727,7 +732,7 @@ static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, return find_metaball_octal_node(node->nodes[2], x, y, z, depth--); else return node; - } + } } } else { @@ -757,7 +762,7 @@ static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, return find_metaball_octal_node(node->nodes[6], x, y, z, depth--); else return node; - } + } } } @@ -772,30 +777,27 @@ static float metaball(float x, float y, float z) float dens = 0; int a; - if (totelem > 1) { - node = find_metaball_octal_node(metaball_tree->first, x, y, z, metaball_tree->depth); + if (G_mb.totelem > 1) { + node = find_metaball_octal_node(G_mb.metaball_tree->first, x, y, z, G_mb.metaball_tree->depth); if (node) { - ml_p = node->elems.first; - - while (ml_p) { + for (ml_p = node->elems.first; ml_p; ml_p = ml_p->next) { dens += densfunc(ml_p->ml, x, y, z); - ml_p = ml_p->next; } - dens += -0.5f * (metaball_tree->pos - node->pos); - dens += 0.5f * (metaball_tree->neg - node->neg); + dens += -0.5f * (G_mb.metaball_tree->pos - node->pos); + dens += 0.5f * (G_mb.metaball_tree->neg - node->neg); } else { - for (a = 0; a < totelem; a++) { - dens += densfunc(mainb[a], x, y, z); + for (a = 0; a < G_mb.totelem; a++) { + dens += densfunc(G_mb.mainb[a], x, y, z); } } } else { - dens += densfunc(mainb[0], x, y, z); + dens += densfunc(G_mb.mainb[0], x, y, z); } - return thresh - dens; + return G_mb.thresh - dens; } /* ******************************************** */ @@ -859,7 +861,7 @@ static void *new_pgn_element(int size) } BLI_freelistN(&lb); - return NULL; + return NULL; } size = 4 * ( (size + 3) / 4); @@ -1497,7 +1499,7 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) MetaElem *ml; float f = 0.0f; - ml = mainb[a]; + ml = G_mb.mainb[a]; f = 1.0 - (mb->thresh / ml->s); /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be @@ -1591,10 +1593,12 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) /* add CUBE (with indexes c_i, c_j, c_k) to the stack, * this cube includes found point of Implicit Surface */ - if (ml->flag & MB_NEGATIVE) - add_cube(mbproc, c_i, c_j, c_k, 2); - else + if ((ml->flag & MB_NEGATIVE) == 0) { add_cube(mbproc, c_i, c_j, c_k, 1); + } + else { + add_cube(mbproc, c_i, c_j, c_k, 2); + } } len = len_v3v3(workp, in); workp_v = tmp_v; @@ -1621,10 +1625,10 @@ static void polygonize(PROCESS *mbproc, MetaBall *mb) mbproc->edges = MEM_callocN(2 * HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); makecubetable(); - for (a = 0; a < totelem; a++) { + for (a = 0; a < G_mb.totelem; a++) { /* try to find 8 points on the surface for each MetaElem */ - find_first_points(mbproc, mb, a); + find_first_points(mbproc, mb, a); } /* polygonize all MetaElems of current MetaBall */ @@ -1714,7 +1718,7 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ ml_count++; ml = ml->next; } - totelem -= ml_count; + G_mb.totelem -= ml_count; } else { while (ml) { @@ -1743,9 +1747,9 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ mult_m4_m4m4(temp1, temp2, temp3); /* make a copy because of duplicates */ - mainb[a] = new_pgn_element(sizeof(MetaElem)); - *(mainb[a]) = *ml; - mainb[a]->bb = new_pgn_element(sizeof(BoundBox)); + G_mb.mainb[a] = new_pgn_element(sizeof(MetaElem)); + *(G_mb.mainb[a]) = *ml; + G_mb.mainb[a]->bb = new_pgn_element(sizeof(BoundBox)); mat = new_pgn_element(4 * 4 * sizeof(float)); imat = new_pgn_element(4 * 4 * sizeof(float)); @@ -1758,70 +1762,70 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ invert_m4_m4(imat, mat); - mainb[a]->rad2 = ml->rad * ml->rad; + G_mb.mainb[a]->rad2 = ml->rad * ml->rad; - mainb[a]->mat = (float *) mat; - mainb[a]->imat = (float *) imat; + G_mb.mainb[a]->mat = (float *) mat; + G_mb.mainb[a]->imat = (float *) imat; /* untransformed Bounding Box of MetaElem */ /* 0 */ - mainb[a]->bb->vec[0][0] = -ml->expx; - mainb[a]->bb->vec[0][1] = -ml->expy; - mainb[a]->bb->vec[0][2] = -ml->expz; + G_mb.mainb[a]->bb->vec[0][0] = -ml->expx; + G_mb.mainb[a]->bb->vec[0][1] = -ml->expy; + G_mb.mainb[a]->bb->vec[0][2] = -ml->expz; /* 1 */ - mainb[a]->bb->vec[1][0] = ml->expx; - mainb[a]->bb->vec[1][1] = -ml->expy; - mainb[a]->bb->vec[1][2] = -ml->expz; + G_mb.mainb[a]->bb->vec[1][0] = ml->expx; + G_mb.mainb[a]->bb->vec[1][1] = -ml->expy; + G_mb.mainb[a]->bb->vec[1][2] = -ml->expz; /* 2 */ - mainb[a]->bb->vec[2][0] = ml->expx; - mainb[a]->bb->vec[2][1] = ml->expy; - mainb[a]->bb->vec[2][2] = -ml->expz; + G_mb.mainb[a]->bb->vec[2][0] = ml->expx; + G_mb.mainb[a]->bb->vec[2][1] = ml->expy; + G_mb.mainb[a]->bb->vec[2][2] = -ml->expz; /* 3 */ - mainb[a]->bb->vec[3][0] = -ml->expx; - mainb[a]->bb->vec[3][1] = ml->expy; - mainb[a]->bb->vec[3][2] = -ml->expz; + G_mb.mainb[a]->bb->vec[3][0] = -ml->expx; + G_mb.mainb[a]->bb->vec[3][1] = ml->expy; + G_mb.mainb[a]->bb->vec[3][2] = -ml->expz; /* 4 */ - mainb[a]->bb->vec[4][0] = -ml->expx; - mainb[a]->bb->vec[4][1] = -ml->expy; - mainb[a]->bb->vec[4][2] = ml->expz; + G_mb.mainb[a]->bb->vec[4][0] = -ml->expx; + G_mb.mainb[a]->bb->vec[4][1] = -ml->expy; + G_mb.mainb[a]->bb->vec[4][2] = ml->expz; /* 5 */ - mainb[a]->bb->vec[5][0] = ml->expx; - mainb[a]->bb->vec[5][1] = -ml->expy; - mainb[a]->bb->vec[5][2] = ml->expz; + G_mb.mainb[a]->bb->vec[5][0] = ml->expx; + G_mb.mainb[a]->bb->vec[5][1] = -ml->expy; + G_mb.mainb[a]->bb->vec[5][2] = ml->expz; /* 6 */ - mainb[a]->bb->vec[6][0] = ml->expx; - mainb[a]->bb->vec[6][1] = ml->expy; - mainb[a]->bb->vec[6][2] = ml->expz; + G_mb.mainb[a]->bb->vec[6][0] = ml->expx; + G_mb.mainb[a]->bb->vec[6][1] = ml->expy; + G_mb.mainb[a]->bb->vec[6][2] = ml->expz; /* 7 */ - mainb[a]->bb->vec[7][0] = -ml->expx; - mainb[a]->bb->vec[7][1] = ml->expy; - mainb[a]->bb->vec[7][2] = ml->expz; + G_mb.mainb[a]->bb->vec[7][0] = -ml->expx; + G_mb.mainb[a]->bb->vec[7][1] = ml->expy; + G_mb.mainb[a]->bb->vec[7][2] = ml->expz; /* transformation of Metalem bb */ for (i = 0; i < 8; i++) - mul_m4_v3((float (*)[4])mat, mainb[a]->bb->vec[i]); + mul_m4_v3((float (*)[4])mat, G_mb.mainb[a]->bb->vec[i]); /* find max and min of transformed bb */ for (i = 0; i < 8; i++) { /* find maximums */ - if (mainb[a]->bb->vec[i][0] > max_x) max_x = mainb[a]->bb->vec[i][0]; - if (mainb[a]->bb->vec[i][1] > max_y) max_y = mainb[a]->bb->vec[i][1]; - if (mainb[a]->bb->vec[i][2] > max_z) max_z = mainb[a]->bb->vec[i][2]; + if (G_mb.mainb[a]->bb->vec[i][0] > max_x) max_x = G_mb.mainb[a]->bb->vec[i][0]; + if (G_mb.mainb[a]->bb->vec[i][1] > max_y) max_y = G_mb.mainb[a]->bb->vec[i][1]; + if (G_mb.mainb[a]->bb->vec[i][2] > max_z) max_z = G_mb.mainb[a]->bb->vec[i][2]; /* find minimums */ - if (mainb[a]->bb->vec[i][0] < min_x) min_x = mainb[a]->bb->vec[i][0]; - if (mainb[a]->bb->vec[i][1] < min_y) min_y = mainb[a]->bb->vec[i][1]; - if (mainb[a]->bb->vec[i][2] < min_z) min_z = mainb[a]->bb->vec[i][2]; + if (G_mb.mainb[a]->bb->vec[i][0] < min_x) min_x = G_mb.mainb[a]->bb->vec[i][0]; + if (G_mb.mainb[a]->bb->vec[i][1] < min_y) min_y = G_mb.mainb[a]->bb->vec[i][1]; + if (G_mb.mainb[a]->bb->vec[i][2] < min_z) min_z = G_mb.mainb[a]->bb->vec[i][2]; } /* create "new" bb, only point 0 and 6, which are * necessary for octal tree filling */ - mainb[a]->bb->vec[0][0] = min_x - ml->rad; - mainb[a]->bb->vec[0][1] = min_y - ml->rad; - mainb[a]->bb->vec[0][2] = min_z - ml->rad; + G_mb.mainb[a]->bb->vec[0][0] = min_x - ml->rad; + G_mb.mainb[a]->bb->vec[0][1] = min_y - ml->rad; + G_mb.mainb[a]->bb->vec[0][2] = min_z - ml->rad; - mainb[a]->bb->vec[6][0] = max_x + ml->rad; - mainb[a]->bb->vec[6][1] = max_y + ml->rad; - mainb[a]->bb->vec[6][2] = max_z + ml->rad; + G_mb.mainb[a]->bb->vec[6][0] = max_x + ml->rad; + G_mb.mainb[a]->bb->vec[6][1] = max_y + ml->rad; + G_mb.mainb[a]->bb->vec[6][2] = max_z + ml->rad; a++; } @@ -1834,13 +1838,13 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ /* totsize (= 'manhattan' radius) */ totsize = 0.0; - for (a = 0; a < totelem; a++) { + for (a = 0; a < G_mb.totelem; a++) { - vec[0] = mainb[a]->x + mainb[a]->rad + mainb[a]->expx; - vec[1] = mainb[a]->y + mainb[a]->rad + mainb[a]->expy; - vec[2] = mainb[a]->z + mainb[a]->rad + mainb[a]->expz; + vec[0] = G_mb.mainb[a]->x + G_mb.mainb[a]->rad + G_mb.mainb[a]->expx; + vec[1] = G_mb.mainb[a]->y + G_mb.mainb[a]->rad + G_mb.mainb[a]->expy; + vec[2] = G_mb.mainb[a]->z + G_mb.mainb[a]->rad + G_mb.mainb[a]->expz; - calc_mballco(mainb[a], vec); + calc_mballco(G_mb.mainb[a], vec); size = fabsf(vec[0]); if (size > totsize) totsize = size; @@ -1849,11 +1853,11 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ size = fabsf(vec[2]); if (size > totsize) totsize = size; - vec[0] = mainb[a]->x - mainb[a]->rad; - vec[1] = mainb[a]->y - mainb[a]->rad; - vec[2] = mainb[a]->z - mainb[a]->rad; + vec[0] = G_mb.mainb[a]->x - G_mb.mainb[a]->rad; + vec[1] = G_mb.mainb[a]->y - G_mb.mainb[a]->rad; + vec[2] = G_mb.mainb[a]->z - G_mb.mainb[a]->rad; - calc_mballco(mainb[a], vec); + calc_mballco(G_mb.mainb[a], vec); size = fabsf(vec[0]); if (size > totsize) totsize = size; @@ -1863,8 +1867,8 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */ if (size > totsize) totsize = size; } - for (a = 0; a < totelem; a++) { - thresh += densfunc(mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); + for (a = 0; a < G_mb.totelem; a++) { + G_mb.thresh += densfunc(G_mb.mainb[a], 2.0f * totsize, 2.0f * totsize, 2.0f * totsize); } return totsize; @@ -1882,11 +1886,11 @@ static void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i) BLI_addtail(&(node->nodes[i]->elems), ml_p); node->count++; - if (ml->flag & MB_NEGATIVE) { - node->nodes[i]->neg++; + if ((ml->flag & MB_NEGATIVE) == 0) { + node->nodes[i]->pos++; } else { - node->nodes[i]->pos++; + node->nodes[i]->neg++; } } @@ -2034,7 +2038,7 @@ static void subdivide_metaball_octal_node(octal_node *node, float size_x, float } - /* ml belongs to the (4)5th node too */ + /* ml belongs to the (4)5th node too */ if (ml->bb->vec[6][2] >= z) { fill_metaball_octal_node(node, ml, 4); } @@ -2180,13 +2184,13 @@ static void init_metaball_octal_tree(int depth) float size[3]; int a; - metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); - metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); + G_mb.metaball_tree = MEM_mallocN(sizeof(octal_tree), "metaball_octal_tree"); + G_mb.metaball_tree->first = node = MEM_mallocN(sizeof(octal_node), "metaball_octal_node"); /* maximal depth of octree */ - metaball_tree->depth = depth; + G_mb.metaball_tree->depth = depth; - metaball_tree->neg = node->neg = 0; - metaball_tree->pos = node->pos = 0; + G_mb.metaball_tree->neg = node->neg = 0; + G_mb.metaball_tree->pos = node->pos = 0; node->elems.first = NULL; node->elems.last = NULL; @@ -2199,36 +2203,36 @@ static void init_metaball_octal_tree(int depth) node->x_max = node->y_max = node->z_max = -FLT_MAX; /* size of octal tree scene */ - for (a = 0; a < totelem; a++) { - if (mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = mainb[a]->bb->vec[0][0]; - if (mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = mainb[a]->bb->vec[0][1]; - if (mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = mainb[a]->bb->vec[0][2]; + for (a = 0; a < G_mb.totelem; a++) { + if (G_mb.mainb[a]->bb->vec[0][0] < node->x_min) node->x_min = G_mb.mainb[a]->bb->vec[0][0]; + if (G_mb.mainb[a]->bb->vec[0][1] < node->y_min) node->y_min = G_mb.mainb[a]->bb->vec[0][1]; + if (G_mb.mainb[a]->bb->vec[0][2] < node->z_min) node->z_min = G_mb.mainb[a]->bb->vec[0][2]; - if (mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = mainb[a]->bb->vec[6][0]; - if (mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = mainb[a]->bb->vec[6][1]; - if (mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = mainb[a]->bb->vec[6][2]; + if (G_mb.mainb[a]->bb->vec[6][0] > node->x_max) node->x_max = G_mb.mainb[a]->bb->vec[6][0]; + if (G_mb.mainb[a]->bb->vec[6][1] > node->y_max) node->y_max = G_mb.mainb[a]->bb->vec[6][1]; + if (G_mb.mainb[a]->bb->vec[6][2] > node->z_max) node->z_max = G_mb.mainb[a]->bb->vec[6][2]; ml_p = MEM_mallocN(sizeof(ml_pointer), "ml_pointer"); - ml_p->ml = mainb[a]; + ml_p->ml = G_mb.mainb[a]; BLI_addtail(&node->elems, ml_p); - if (mainb[a]->flag & MB_NEGATIVE) { - /* number of negative MetaElem in scene */ - metaball_tree->neg++; + if ((G_mb.mainb[a]->flag & MB_NEGATIVE) == 0) { + /* number of positive MetaElem in scene */ + G_mb.metaball_tree->pos++; } else { - /* number of positive MetaElem in scene */ - metaball_tree->pos++; + /* number of negative MetaElem in scene */ + G_mb.metaball_tree->neg++; } } - /* size of first node */ + /* size of first node */ size[0] = node->x_max - node->x_min; size[1] = node->y_max - node->y_min; size[2] = node->z_max - node->z_min; /* first node is subdivided recursively */ - subdivide_metaball_octal_node(node, size[0], size[1], size[2], metaball_tree->depth); + subdivide_metaball_octal_node(node, size[0], size[1], size[2], G_mb.metaball_tree->depth); } void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) @@ -2241,48 +2245,48 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) mb = ob->data; - if (totelem == 0) return; + if (G_mb.totelem == 0) return; if ((G.is_rendering == FALSE) && (mb->flag == MB_UPDATE_NEVER)) return; if (G.moving && mb->flag == MB_UPDATE_FAST) return; curindex = totindex = 0; indices = NULL; - thresh = mb->thresh; + G_mb.thresh = mb->thresh; /* total number of MetaElems (totelem) is precomputed in find_basis_mball() function */ - mainb = MEM_mallocN(sizeof(void *) * totelem, "mainb"); + G_mb.mainb = MEM_mallocN(sizeof(void *) * G_mb.totelem, "mainb"); /* initialize all mainb (MetaElems) */ totsize = init_meta(scene, ob); - if (metaball_tree) { - free_metaball_octal_node(metaball_tree->first); - MEM_freeN(metaball_tree); - metaball_tree = NULL; + if (G_mb.metaball_tree) { + free_metaball_octal_node(G_mb.metaball_tree->first); + MEM_freeN(G_mb.metaball_tree); + G_mb.metaball_tree = NULL; } /* if scene includes more then one MetaElem, then octal tree optimization is used */ - if ((totelem > 1) && (totelem <= 64)) init_metaball_octal_tree(1); - if ((totelem > 64) && (totelem <= 128)) init_metaball_octal_tree(2); - if ((totelem > 128) && (totelem <= 512)) init_metaball_octal_tree(3); - if ((totelem > 512) && (totelem <= 1024)) init_metaball_octal_tree(4); - if (totelem > 1024) init_metaball_octal_tree(5); + if ((G_mb.totelem > 1) && (G_mb.totelem <= 64)) init_metaball_octal_tree(1); + if ((G_mb.totelem > 64) && (G_mb.totelem <= 128)) init_metaball_octal_tree(2); + if ((G_mb.totelem > 128) && (G_mb.totelem <= 512)) init_metaball_octal_tree(3); + if ((G_mb.totelem > 512) && (G_mb.totelem <= 1024)) init_metaball_octal_tree(4); + if (G_mb.totelem > 1024) init_metaball_octal_tree(5); /* don't polygonize metaballs with too high resolution (base mball to small) * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */ - if (metaball_tree) { - if (ob->size[0] <= 0.00001f * (metaball_tree->first->x_max - metaball_tree->first->x_min) || - ob->size[1] <= 0.00001f * (metaball_tree->first->y_max - metaball_tree->first->y_min) || - ob->size[2] <= 0.00001f * (metaball_tree->first->z_max - metaball_tree->first->z_min)) + if (G_mb.metaball_tree) { + if (ob->size[0] <= 0.00001f * (G_mb.metaball_tree->first->x_max - G_mb.metaball_tree->first->x_min) || + ob->size[1] <= 0.00001f * (G_mb.metaball_tree->first->y_max - G_mb.metaball_tree->first->y_min) || + ob->size[2] <= 0.00001f * (G_mb.metaball_tree->first->z_max - G_mb.metaball_tree->first->z_min)) { new_pgn_element(-1); /* free values created by init_meta */ - MEM_freeN(mainb); + MEM_freeN(G_mb.mainb); /* free tree */ - free_metaball_octal_node(metaball_tree->first); - MEM_freeN(metaball_tree); - metaball_tree = NULL; + free_metaball_octal_node(G_mb.metaball_tree->first); + MEM_freeN(G_mb.metaball_tree); + G_mb.metaball_tree = NULL; return; } @@ -2306,13 +2310,13 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) polygonize(&mbproc, mb); - MEM_freeN(mainb); + MEM_freeN(G_mb.mainb); /* free octal tree */ - if (totelem > 1) { - free_metaball_octal_node(metaball_tree->first); - MEM_freeN(metaball_tree); - metaball_tree = NULL; + if (G_mb.totelem > 1) { + free_metaball_octal_node(G_mb.metaball_tree->first); + MEM_freeN(G_mb.metaball_tree); + G_mb.metaball_tree = NULL; } if (curindex) { @@ -2384,7 +2388,7 @@ int BKE_mball_center_bounds(MetaBall *mb, float r_cent[3]) return 0; } -void BKE_mball_translate(MetaBall *mb, float offset[3]) +void BKE_mball_translate(MetaBall *mb, const float offset[3]) { MetaElem *ml; @@ -2392,3 +2396,32 @@ void BKE_mball_translate(MetaBall *mb, float offset[3]) add_v3_v3(&ml->x, offset); } } + +/* *** select funcs *** */ +void BKE_mball_select_all(struct MetaBall *mb) +{ + MetaElem *ml; + + for (ml = mb->editelems->first; ml; ml = ml->next) { + ml->flag |= SELECT; + } +} + +void BKE_mball_deselect_all(MetaBall *mb) +{ + MetaElem *ml; + + for (ml = mb->editelems->first; ml; ml = ml->next) { + ml->flag &= ~SELECT; + } +} + +void BKE_mball_select_swap(struct MetaBall *mb) +{ + MetaElem *ml; + + for (ml = mb->editelems->first; ml; ml = ml->next) { + ml->flag ^= SELECT; + } +} + diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index f5ae3c7da2b..1aaeebf5109 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -367,7 +367,6 @@ void mesh_update_customdata_pointers(Mesh *me, const short do_ensure_tess_cd) me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); - me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY); me->medge = CustomData_get_layer(&me->edata, CD_MEDGE); @@ -789,7 +788,7 @@ int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) nr--; } - /* check corrupt cases, bowtie geometry, cant handle these because edge data wont exist so just return 0 */ + /* check corrupt cases, bow-tie geometry, cant handle these because edge data wont exist so just return 0 */ if (nr == 3) { if ( /* real edges */ @@ -1865,7 +1864,7 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, int numVerts, /* only calc poly normals */ mp = mpolys; for (i = 0; i < numPolys; i++, mp++) { - mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); + BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); } } @@ -1915,7 +1914,7 @@ void BKE_mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpo mp = mpolys; for (i = 0; i < numPolys; i++, mp++) { - mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); + BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); ml = mloop + mp->loopstart; BLI_array_empty(vertcos); @@ -1944,8 +1943,9 @@ void BKE_mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpo MVert *mv = &mverts[i]; float *no = tnorms[i]; - if (normalize_v3(no) == 0.0f) + if (UNLIKELY(normalize_v3(no) == 0.0f)) { normalize_v3_v3(no, mv->co); + } normal_float_to_short_v3(mv->no, no); } @@ -1981,8 +1981,9 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, MVert *mv = &mverts[i]; float *no = tnorms[i]; - if (normalize_v3(no) == 0.0f) + if (UNLIKELY(normalize_v3(no) == 0.0f)) { normalize_v3_v3(no, mv->co); + } normal_float_to_short_v3(mv->no, no); } @@ -2042,7 +2043,7 @@ static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, int side, corners; if (CustomData_external_test(fdata, CD_MDISPS)) { - if (id) { + if (id && fdata->external) { CustomData_external_add(ldata, id, CD_MDISPS, totloop, fdata->external->filename); } @@ -2702,13 +2703,13 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, #endif { /* sort loop indices to ensure winding is correct */ - if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); - if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3); - if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2); + if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3); + if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2); - if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); - if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3); - if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2); + if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2); + if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3); + if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2); } /* end abusing the edcode */ @@ -2899,8 +2900,8 @@ static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart, } } -void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart, - MVert *mvarray, float no[3]) +void BKE_mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart, + MVert *mvarray, float no[3]) { if (mpoly->totloop > 4) { mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no); @@ -3015,7 +3016,7 @@ void BKE_mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart, /* note, passing polynormal is only a speedup so we can skip calculating it */ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, - MVert *mvarray, float polynormal[3]) + MVert *mvarray, const float polynormal[3]) { if (mpoly->totloop == 3) { return area_tri_v3(mvarray[loopstart[0].v].co, @@ -3034,7 +3035,7 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, int i; MLoop *l_iter = loopstart; float area, polynorm_local[3], (*vertexcos)[3]; - float *no = polynormal ? polynormal : polynorm_local; + const float *no = polynormal ? polynormal : polynorm_local; BLI_array_fixedstack_declare(vertexcos, BM_NGON_STACK_SIZE, mpoly->totloop, __func__); /* pack vertex cos into an array for area_poly_v3 */ @@ -3044,7 +3045,7 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, /* need normal for area_poly_v3 as well */ if (polynormal == NULL) { - mesh_calc_poly_normal(mpoly, loopstart, mvarray, no); + BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, polynorm_local); } /* finally calculate the area */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 65538e5bea2..28de80a7157 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -482,7 +482,7 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob) } /* shape key modifier, not yet for curves */ - if (ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) { + if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) { if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE)) smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage; else diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 72c3cda9272..dc3d4a89e62 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -49,7 +49,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) MLoop *mloop, *ml; BMVert *v, **vtable, **verts = NULL; BMEdge *e, **etable, **edges = NULL; - float has_face_normals; + float (*face_normals)[3]; BMFace *f; BMIter liter; BLI_array_declare(verts); @@ -72,8 +72,8 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); - vtable = MEM_callocN(sizeof(void **) * totvert, "vert table in BMDM_Copy"); - etable = MEM_callocN(sizeof(void **) * totedge, "edge table in BMDM_Copy"); + vtable = MEM_callocN(sizeof(void **) * totvert, __func__); + etable = MEM_callocN(sizeof(void **) * totedge, __func__); /*do verts*/ mv = mvert = dm->dupVertArray(dm); @@ -110,7 +110,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) /*do faces*/ mp = dm->getPolyArray(dm); mloop = dm->getLoopArray(dm); - has_face_normals = CustomData_has_layer(&dm->polyData, CD_NORMAL); + face_normals = CustomData_get_layer(&dm->polyData, CD_NORMAL); /* can be NULL */ for (i = 0; i < dm->numPolyData; i++, mp++) { BMLoop *l; @@ -129,8 +129,9 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, FALSE); - if (!f) + if (UNLIKELY(f == NULL)) { continue; + } f->head.hflag = BM_face_flag_from_mflag(mp->flag); f->mat_nr = mp->mat_nr; @@ -143,11 +144,11 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data); - if (has_face_normals) { - float *fno; - - fno = CustomData_bmesh_get(&bm->pdata, &f->head.data, CD_NORMAL); - copy_v3_v3(f->no, fno); + if (face_normals) { + copy_v3_v3(f->no, face_normals[i]); + } + else { + BM_face_normal_update(f); } } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 4c23a370a5d..0aa1f9e0822 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -52,6 +52,7 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_movieclip_types.h" +#include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_view3d_types.h" @@ -66,14 +67,16 @@ #include "BKE_animsys.h" #include "BKE_constraint.h" +#include "BKE_colortools.h" #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" -#include "BKE_utildefines.h" #include "BKE_movieclip.h" +#include "BKE_node.h" #include "BKE_image.h" /* openanim */ #include "BKE_tracking.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_moviecache.h" @@ -198,19 +201,25 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, struct ImBuf *ibuf; char name[FILE_MAX]; int loadflag, use_proxy = FALSE; + char *colorspace; use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL; if (use_proxy) { int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT; get_proxy_fname(clip, user->render_size, undistort, framenr, name); + + /* proxies were built using default color space settings */ + colorspace = NULL; } - else + else { get_sequence_fname(clip, framenr, name); + colorspace = clip->colorspace_settings.name; + } loadflag = IB_rect | IB_multilayer; /* read ibuf */ - ibuf = IMB_loadiffname(name, loadflag); + ibuf = IMB_loadiffname(name, loadflag, colorspace); return ibuf; } @@ -224,7 +233,7 @@ static void movieclip_open_anim_file(MovieClip *clip) BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id)); /* FIXME: make several stream accessible in image editor, too */ - clip->anim = openanim(str, IB_rect, 0); + clip->anim = openanim(str, IB_rect, 0, clip->colorspace_settings.name); if (clip->anim) { if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) { @@ -285,11 +294,11 @@ static void movieclip_calc_length(MovieClip *clip) clip->len = framenr + 1; } else { - for (;; ) { + for (;;) { get_sequence_fname(clip, framenr, name); if (!BLI_exists(name)) { - clip->len = framenr + 1; + clip->len = framenr; break; } @@ -384,7 +393,7 @@ static int moviecache_hashcmp(const void *av, const void *bv) return 0; } -void *moviecache_getprioritydata(void *key_v) +static void *moviecache_getprioritydata(void *key_v) { MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *) key_v; MovieClipCachePriorityData *priority_data; @@ -395,7 +404,7 @@ void *moviecache_getprioritydata(void *key_v) return priority_data; } -int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v) +static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v) { MovieClipImBufCacheKey *last_userkey = (MovieClipImBufCacheKey *) last_userkey_v; MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v; @@ -403,7 +412,7 @@ int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v) return -abs(last_userkey->framenr - priority_data->framenr); } -void moviecache_prioritydeleter(void *priority_data_v) +static void moviecache_prioritydeleter(void *priority_data_v) { MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v; @@ -479,6 +488,7 @@ static MovieClip *movieclip_alloc(const char *name) clip->aspx = clip->aspy = 1.0f; BKE_tracking_settings_init(&clip->tracking); + BKE_color_managed_colorspace_settings_init(&clip->colorspace_settings); clip->proxy.build_size_flag = IMB_PROXY_25; clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN | @@ -616,24 +626,22 @@ static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *dist return undistibuf; } -static int need_undistortion_postprocess(MovieClipUser *user, int flag) +static int need_undistortion_postprocess(MovieClipUser *user) { int result = 0; /* only full undistorted render can be used as on-fly undistorting image */ - if (flag & MCLIP_USE_PROXY) { - result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) && - (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; - } + result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) && + (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; return result; } -static int need_postprocessed_frame(MovieClipUser *user, int flag, int postprocess_flag) +static int need_postprocessed_frame(MovieClipUser *user, int postprocess_flag) { int result = postprocess_flag; - result |= need_undistortion_postprocess(user, flag); + result |= need_undistortion_postprocess(user); return result; } @@ -680,7 +688,7 @@ static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *use if (cache->postprocessed.flag != postprocess_flag) return NULL; - if (need_undistortion_postprocess(user, flag)) { + if (need_undistortion_postprocess(user)) { if (!check_undistortion_cache_flags(clip)) return NULL; } @@ -711,7 +719,7 @@ static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *u cache->postprocessed.render_flag = 0; } - if (need_undistortion_postprocess(user, flag)) { + if (need_undistortion_postprocess(user)) { copy_v2_v2(cache->postprocessed.principal, camera->principal); copy_v3_v3(&cache->postprocessed.k1, &camera->k1); cache->postprocessed.undistortion_used = TRUE; @@ -755,7 +763,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *u BLI_lock_thread(LOCK_MOVIECLIP); /* try to obtain cached postprocessed frame first */ - if (need_postprocessed_frame(user, flag, postprocess_flag)) { + if (need_postprocessed_frame(user, postprocess_flag)) { ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag); if (!ibuf) @@ -1002,6 +1010,14 @@ void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, in IMB_freeImBuf(ibuf); } } +void BKE_movieclip_get_size_fl(MovieClip *clip, MovieClipUser *user, float size[2]) +{ + int width, height; + BKE_movieclip_get_size(clip, user, &width, &height); + + size[0] = (float)width; + size[1] = (float)height; +} int BKE_movieclip_get_duration(MovieClip *clip) { @@ -1012,9 +1028,9 @@ int BKE_movieclip_get_duration(MovieClip *clip) return clip->len; } -void BKE_movieclip_aspect(MovieClip *clip, float *aspx, float *aspy) +void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy) { - *aspx = *aspy = 1.0; + *aspx = 1.0; /* x is always 1 */ *aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect; @@ -1310,6 +1326,11 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip) } } + { + bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT); + treetype->foreach_nodetree(bmain, (void *)clip, &BKE_node_tree_unlink_id_cb); + } + clip->id.us = 0; } diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 1c06d95a70b..591524e5156 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -666,7 +666,9 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) mdisp->totdisp = totdisp; mdisp->level = lvl; - multires_grid_paint_mask_downsample(&gpm[g], lvl); + if (gpm) { + multires_grid_paint_mask_downsample(&gpm[g], lvl); + } } } } @@ -893,15 +895,16 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl CCGKey highGridKey, lowGridKey; CCGSubSurf *ss; int i, numGrids, highGridSize; + int has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); /* create subsurf DM from original mesh at high level */ cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); ss = ((CCGDerivedMesh *)highdm)->ss; /* create multires DM from original mesh at low level */ - lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, TRUE); + lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, has_mask); cddm->release(cddm); /* copy subsurf grids and replace them with low displaced grids */ @@ -1164,17 +1167,18 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm) CCGKey highGridKey, lowGridKey; CCGSubSurf *ss; int i, j, numGrids, highGridSize, lowGridSize; + int has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); /* create subsurf DM from original mesh at high level */ if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform); else cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); ss = ((CCGDerivedMesh *)highdm)->ss; /* create multires DM from original mesh and displacements */ - lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple, TRUE); + lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple, has_mask); cddm->release(cddm); /* gather grid data */ @@ -1226,12 +1230,13 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm) } else { DerivedMesh *cddm, *subdm; + int has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform); else cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE); + subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); cddm->release(cddm); multiresModifier_disp_run(dm, me, NULL, CALC_DISPLACEMENTS, subdm->getGridData(subdm), mmd->totlvl); @@ -2107,7 +2112,7 @@ void multires_load_old(Object *ob, Mesh *me) * reference subsurfed dm with this option, before calling multiresModifier_disp_run(), * which implicitly expects both subsurfs from its first dm and oldGridData parameters to * be of the same "format"! */ - dm = multires_make_derived_from_derived(orig, mmd, ob, MULTIRES_ALLOC_PAINT_MASK); + dm = multires_make_derived_from_derived(orig, mmd, ob, 0); multires_load_old_dm(dm, me, mmd->totlvl + 1); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d62b03b5060..9590160c8f3 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -764,7 +764,7 @@ void BKE_nlastrips_clear_metas(ListBase *strips, short onlySel, short onlyTemp) } /* Add the given NLA-Strip to the given Meta-Strip, assuming that the - * strip isn't attached to anyy list of strips + * strip isn't attached to any list of strips */ short BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip) { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 62e80645a35..8cede4f51a5 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -58,8 +58,6 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_node.h" -#include "BKE_utildefines.h" -#include "BKE_utildefines.h" #include "RNA_access.h" @@ -671,7 +669,7 @@ bNodeTree *ntreeAddTree(const char *name, int type, int nodetype) * copying for internal use (threads for eg), where you wont want it to modify the * scene data. */ -static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_extern) +static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern) { bNodeTree *newtree; bNode *node /*, *nnode */ /* UNUSED */, *last; @@ -702,6 +700,11 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e last = ntree->nodes.last; for (node = ntree->nodes.first; node; node = node->next) { + /* ntreeUserDecrefID inline */ + if (do_id_user) { + id_us_plus(node->id); + } + if (do_make_extern) { id_lib_extern(node->id); } @@ -751,22 +754,56 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e return newtree; } +bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user) +{ + return ntreeCopyTree_internal(ntree, do_id_user, TRUE); +} bNodeTree *ntreeCopyTree(bNodeTree *ntree) { - return ntreeCopyTree_internal(ntree, TRUE); + return ntreeCopyTree_ex(ntree, TRUE); } /* use when duplicating scenes */ -void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to) +void ntreeSwitchID_ex(bNodeTree *ntree, ID *id_from, ID *id_to, const short do_id_user) { bNode *node; + + if (id_from == id_to) { + /* should never happen but may as well skip if it does */ + return; + } + /* for scene duplication only */ for (node = ntree->nodes.first; node; node = node->next) { if (node->id == id_from) { + if (do_id_user) { + id_us_min(id_from); + id_us_plus(id_to); + } + node->id = id_to; } } } +void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to) +{ + ntreeSwitchID_ex(ntree, id_from, id_to, TRUE); +} + +void ntreeUserIncrefID(bNodeTree *ntree) +{ + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + id_us_plus(node->id); + } +} +void ntreeUserDecrefID(bNodeTree *ntree) +{ + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + id_us_min(node->id); + } +} /* *************** preview *********** */ /* if node->preview, then we assume the rect to exist */ @@ -913,6 +950,7 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent) } } +/** \note caller needs to manage node->id user */ void nodeFreeNode(bNodeTree *ntree, bNode *node) { bNodeSocket *sock, *nextsock; @@ -956,7 +994,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) } /* do not free ntree itself here, BKE_libblock_free calls this function too */ -void ntreeFreeTree(bNodeTree *ntree) +void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) { bNode *node, *next; bNodeSocket *sock; @@ -990,6 +1028,21 @@ void ntreeFreeTree(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = next) { next = node->next; + + /* ntreeUserIncrefID inline */ + + /* XXX, this is correct, however when freeing the entire database + * this ends up accessing freed data which isn't properly unlinking + * its self from scene nodes, SO - for now prefer invalid usercounts + * on free rather then bad memory access - Campbell */ +#if 0 + if (do_id_user) { + id_us_min(node->id); + } +#else + (void)do_id_user; +#endif + nodeFreeNode(ntree, node); } @@ -1000,6 +1053,11 @@ void ntreeFreeTree(bNodeTree *ntree) node_socket_free_default_value(sock->type, sock->default_value); BLI_freelistN(&ntree->outputs); } +/* same as ntreeFreeTree_ex but always manage users */ +void ntreeFreeTree(bNodeTree *ntree) +{ + ntreeFreeTree_ex(ntree, TRUE); +} void ntreeFreeCache(bNodeTree *ntree) { @@ -1188,7 +1246,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) } /* node copy func */ - ltree = ntreeCopyTree_internal(ntree, FALSE); + ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE); if (adt) { AnimData *ladt = BKE_animdata_from_id(<ree->id); @@ -1248,7 +1306,7 @@ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) if (ntreetype->local_merge) ntreetype->local_merge(localtree, ntree); - ntreeFreeTree(localtree); + ntreeFreeTree_ex(localtree, FALSE); MEM_freeN(localtree); } @@ -1433,13 +1491,13 @@ void nodeSocketSetType(bNodeSocket *sock, int type) * otherwise we may reference missing data. * * Currently its only used for ID's, but nodes may one day - * referene other pointers which need validation. + * reference other pointers which need validation. */ typedef struct bNodeClipboardExtraInfo { - struct bNodeClipboardExtraInfo *next, *prev; + struct bNodeClipboardExtraInfo *next, *prev; ID *id; - char id_name[MAX_ID_NAME]; - char library_name[FILE_MAX]; + char id_name[MAX_ID_NAME]; + char library_name[FILE_MAX]; } bNodeClipboardExtraInfo; #endif /* USE_NODE_CB_VALIDATE */ @@ -1448,7 +1506,7 @@ typedef struct bNodeClipboard { ListBase nodes; #ifdef USE_NODE_CB_VALIDATE - ListBase nodes_extra_info; + ListBase nodes_extra_info; #endif ListBase links; @@ -1480,7 +1538,7 @@ void BKE_node_clipboard_clear(void) node_clipboard.nodes.first = node_clipboard.nodes.last = NULL; #ifdef USE_NODE_CB_VALIDATE - BLI_freelistN(&node_clipboard.nodes_extra_info); + BLI_freelistN(&node_clipboard.nodes_extra_info); #endif } @@ -1531,28 +1589,28 @@ int BKE_node_clipboard_validate(void) void BKE_node_clipboard_add_node(bNode *node) { #ifdef USE_NODE_CB_VALIDATE - /* add extra info */ - bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), STRINGIFY(bNodeClipboardExtraInfo)); + /* add extra info */ + bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), STRINGIFY(bNodeClipboardExtraInfo)); node_info->id = node->id; - if (node->id) { - BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name)); - if (node->id->lib) { - BLI_strncpy(node_info->library_name, node->id->lib->filepath, sizeof(node_info->library_name)); - } - else { - node_info->library_name[0] = '\0'; - } - } - else { - node_info->id_name[0] = '\0'; - node_info->library_name[0] = '\0'; - } - BLI_addtail(&node_clipboard.nodes_extra_info, node_info); + if (node->id) { + BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name)); + if (node->id->lib) { + BLI_strncpy(node_info->library_name, node->id->lib->filepath, sizeof(node_info->library_name)); + } + else { + node_info->library_name[0] = '\0'; + } + } + else { + node_info->id_name[0] = '\0'; + node_info->library_name[0] = '\0'; + } + BLI_addtail(&node_clipboard.nodes_extra_info, node_info); /* end extra info */ #endif /* USE_NODE_CB_VALIDATE */ - /* add node */ + /* add node */ BLI_addtail(&node_clipboard.nodes, node); } @@ -2088,6 +2146,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_vecblur(ttype); register_node_type_cmp_dilateerode(ttype); register_node_type_cmp_inpaint(ttype); + register_node_type_cmp_despeckle(ttype); register_node_type_cmp_defocus(ttype); register_node_type_cmp_valtorgb(ttype); @@ -2213,6 +2272,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_tex_gradient(ttype); register_node_type_sh_tex_magic(ttype); register_node_type_sh_tex_checker(ttype); + register_node_type_sh_tex_brick(ttype); } static void registerTextureNodes(bNodeTreeType *ttype) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0fd3804f63a..f72372742d0 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -305,17 +305,27 @@ void BKE_object_free(Object *ob) ID *id = ob->data; id->us--; if (id->us == 0) { - if (ob->type == OB_MESH) BKE_mesh_unlink(ob->data); - else if (ob->type == OB_CURVE) BKE_curve_unlink(ob->data); - else if (ob->type == OB_MBALL) BKE_mball_unlink(ob->data); + switch (ob->type) { + case OB_MESH: + BKE_mesh_unlink((Mesh *)id); + break; + case OB_CURVE: + BKE_curve_unlink((Curve *)id); + break; + case OB_MBALL: + BKE_mball_unlink((MetaBall *)id); + break; + } } ob->data = NULL; } - - for (a = 0; a < ob->totcol; a++) { - if (ob->mat[a]) ob->mat[a]->id.us--; + + if (ob->mat) { + for (a = 0; a < ob->totcol; a++) { + if (ob->mat[a]) ob->mat[a]->id.us--; + } + MEM_freeN(ob->mat); } - if (ob->mat) MEM_freeN(ob->mat); if (ob->matbits) MEM_freeN(ob->matbits); ob->mat = NULL; ob->matbits = NULL; @@ -330,7 +340,7 @@ void BKE_object_free(Object *ob) BKE_pose_free(ob->pose); if (ob->mpath) animviz_free_motionpath(ob->mpath); - free_properties(&ob->prop); + BKE_bproperty_free_list(&ob->prop); BKE_object_free_modifiers(ob); free_sensors(&ob->sensors); @@ -879,23 +889,44 @@ Object *BKE_object_add(struct Scene *scene, int type) return ob; } -SoftBody *copy_softbody(SoftBody *sb) +SoftBody *copy_softbody(SoftBody *sb, int copy_caches) { SoftBody *sbn; if (sb == NULL) return(NULL); sbn = MEM_dupallocN(sb); - sbn->totspring = sbn->totpoint = 0; - sbn->bpoint = NULL; - sbn->bspring = NULL; + + if (copy_caches == FALSE) { + sbn->totspring = sbn->totpoint = 0; + sbn->bpoint = NULL; + sbn->bspring = NULL; + } + else { + sbn->totspring = sb->totspring; + sbn->totpoint = sb->totpoint; + + if (sbn->bpoint) { + int i; + + sbn->bpoint = MEM_dupallocN(sbn->bpoint); + + for (i = 0; i < sbn->totpoint; i++) { + if (sbn->bpoint[i].springs) + sbn->bpoint[i].springs = MEM_dupallocN(sbn->bpoint[i].springs); + } + } + + if (sb->bspring) + sbn->bspring = MEM_dupallocN(sb->bspring); + } sbn->keys = NULL; sbn->totkey = sbn->totpointkey = 0; sbn->scratch = NULL; - sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches); + sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, copy_caches); if (sb->effector_weights) sbn->effector_weights = MEM_dupallocN(sb->effector_weights); @@ -968,7 +999,7 @@ static ParticleSystem *copy_particlesystem(ParticleSystem *psys) psysn->childcachebufs.first = psysn->childcachebufs.last = NULL; psysn->renderdata = NULL; - psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches); + psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, FALSE); /* XXX - from reading existing code this seems correct but intended usage of * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */ @@ -1029,7 +1060,7 @@ void BKE_object_copy_particlesystems(Object *obn, Object *ob) void BKE_object_copy_softbody(Object *obn, Object *ob) { if (ob->soft) - obn->soft = copy_softbody(ob->soft); + obn->soft = copy_softbody(ob->soft, FALSE); } static void copy_object_pose(Object *obn, Object *ob) @@ -1069,12 +1100,12 @@ static void copy_object_pose(Object *obn, Object *ob) } } -static int object_pose_context(Object *ob) +int BKE_object_pose_context_check(Object *ob) { - if ( (ob) && - (ob->type == OB_ARMATURE) && - (ob->pose) && - (ob->mode & OB_MODE_POSE)) + if ((ob) && + (ob->type == OB_ARMATURE) && + (ob->pose) && + (ob->mode & OB_MODE_POSE)) { return 1; } @@ -1088,12 +1119,12 @@ Object *BKE_object_pose_armature_get(Object *ob) if (ob == NULL) return NULL; - if (object_pose_context(ob)) + if (BKE_object_pose_context_check(ob)) return ob; ob = modifiers_isDeformedByArmature(ob); - if (object_pose_context(ob)) + if (BKE_object_pose_context_check(ob)) return ob; return NULL; @@ -1110,7 +1141,7 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src) copy_v3_v3(ob_tar->size, ob_src->size); } -Object *BKE_object_copy(Object *ob) +static Object *object_copy_do(Object *ob, int copy_caches) { Object *obn; ModifierData *md; @@ -1137,7 +1168,7 @@ Object *BKE_object_copy(Object *ob) } obn->prop.first = obn->prop.last = NULL; - copy_properties(&obn->prop, &ob->prop); + BKE_bproperty_copy_list(&obn->prop, &ob->prop); copy_sensors(&obn->sensors, &ob->sensors); copy_controllers(&obn->controllers, &ob->controllers); @@ -1171,7 +1202,7 @@ Object *BKE_object_copy(Object *ob) if (obn->pd->rng) obn->pd->rng = MEM_dupallocN(ob->pd->rng); } - obn->soft = copy_softbody(ob->soft); + obn->soft = copy_softbody(ob->soft, copy_caches); obn->bsoft = copy_bulletsoftbody(ob->bsoft); BKE_object_copy_particlesystems(obn, ob); @@ -1187,6 +1218,18 @@ Object *BKE_object_copy(Object *ob) return obn; } +/* copy objects, will re-initialize cached simulation data */ +Object *BKE_object_copy(Object *ob) +{ + return object_copy_do(ob, FALSE); +} + +/* copy objects, will duplicate cached simulation data */ +Object *BKE_object_copy_with_caches(Object *ob) +{ + return object_copy_do(ob, TRUE); +} + static void extern_local_object(Object *ob) { ParticleSystem *psys; @@ -1514,7 +1557,7 @@ void BKE_object_mat3_to_rot(Object *ob, float mat[][3], short use_compat) /* end drot correction */ if (use_compat) mat3_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, tmat); - else mat3_to_eulO(ob->rot, ob->rotmode, tmat); + else mat3_to_eulO(ob->rot, ob->rotmode, tmat); } } } @@ -1756,9 +1799,8 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4]) static void give_parvert(Object *par, int nr, float vec[3]) { BMEditMesh *em; - int a, count; - - vec[0] = vec[1] = vec[2] = 0.0f; + + zero_v3(vec); if (par->type == OB_MESH) { Mesh *me = par->data; @@ -1785,18 +1827,28 @@ static void give_parvert(Object *par, int nr, float vec[3]) dm = (em) ? em->derivedFinal : par->derivedFinal; if (dm) { - MVert *mvert = dm->getVertArray(dm); - int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX); - int i, vindex, numVerts = dm->getNumVerts(dm); - - /* get the average of all verts with (original index == nr) */ - count = 0; - for (i = 0; i < numVerts; i++) { - vindex = (index) ? index[i] : i; - - if (vindex == nr) { - add_v3_v3(vec, mvert[i].co); - count++; + int count = 0; + int numVerts = dm->getNumVerts(dm); + + if (nr < numVerts) { + MVert *mvert = dm->getVertArray(dm); + int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX); + int i; + + /* get the average of all verts with (original index == nr) */ + if (index) { + for (i = 0; i < numVerts; i++) { + if (index[i] == nr) { + add_v3_v3(vec, mvert[i].co); + count++; + } + } + } + else { + if (nr < numVerts) { + add_v3_v3(vec, mvert[nr].co); + count++; + } } } @@ -1818,71 +1870,31 @@ static void give_parvert(Object *par, int nr, float vec[3]) } } else if (ELEM(par->type, OB_CURVE, OB_SURF)) { - Nurb *nu; - Curve *cu; - BPoint *bp; - BezTriple *bezt; - int found = 0; - ListBase *nurbs; - - cu = par->data; - nurbs = BKE_curve_nurbs_get(cu); - nu = nurbs->first; - - count = 0; - while (nu && !found) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (count == nr) { - found = 1; - copy_v3_v3(vec, bezt->vec[1]); - break; - } - count++; - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - if (count == nr) { - found = 1; - memcpy(vec, bp->vec, sizeof(float) * 3); - break; - } - count++; - bp++; - } - } - nu = nu->next; - } + Curve *cu = par->data; + ListBase *nurb = BKE_curve_nurbs_get(cu);; + BKE_nurbList_index_get_co(nurb, nr, vec); } else if (par->type == OB_LATTICE) { - Lattice *latt = par->data; - BPoint *bp; - DispList *dl = BKE_displist_find(&par->disp, DL_VERTS); - float *co = dl ? dl->verts : NULL; - + Lattice *latt = par->data; + DispList *dl = BKE_displist_find(&par->disp, DL_VERTS); + float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL; + int tot; + if (latt->editlatt) latt = latt->editlatt->latt; - - a = latt->pntsu * latt->pntsv * latt->pntsw; - count = 0; - bp = latt->def; - while (a--) { - if (count == nr) { - if (co) - memcpy(vec, co, 3 * sizeof(float)); - else - memcpy(vec, bp->vec, 3 * sizeof(float)); - break; + + tot = latt->pntsu * latt->pntsv * latt->pntsw; + + /* ensure dl is correct size */ + BLI_assert(dl == NULL || dl->nr == tot); + + if (nr < tot) { + if (co) { + copy_v3_v3(vec, co[nr]); + } + else { + copy_v3_v3(vec, latt->def[nr].vec); } - count++; - if (co) co += 3; - else bp++; } } } @@ -2249,7 +2261,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const short u Curve *cu = ob->data; /* Use the object bounding box so that modifier output - gets taken into account */ + * gets taken into account */ if (ob->bb) bb = *(ob->bb); else { @@ -2350,7 +2362,7 @@ int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_ma ListBase *lb; DupliObject *dob; - lb = object_duplilist(scene, ob); + lb = object_duplilist(scene, ob, FALSE); for (dob = lb->first; dob; dob = dob->next) { if ((use_hidden == FALSE) && (dob->no_draw != 0)) { /* pass */ @@ -2427,7 +2439,7 @@ void BKE_scene_foreach_display_point( ListBase *lb; DupliObject *dob; - lb = object_duplilist(scene, ob); + lb = object_duplilist(scene, ob, FALSE); for (dob = lb->first; dob; dob = dob->next) { if (dob->no_draw == 0) { BKE_object_foreach_display_point(dob->ob, dob->mat, func_cb, user_data); @@ -2700,7 +2712,7 @@ void BKE_object_handle_update(Scene *scene, Object *ob) if (pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID) == 0) { scene->physics_settings.quick_cache_step = scene->physics_settings.quick_cache_step ? - MIN2(scene->physics_settings.quick_cache_step, pid->cache->step) : + mini(scene->physics_settings.quick_cache_step, pid->cache->step) : pid->cache->step; } } @@ -2889,22 +2901,22 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int int newkey = 0; if (key == NULL) { - key = me->key = add_key((ID *)me); + key = me->key = BKE_key_add((ID *)me); key->type = KEY_RELATIVE; newkey = 1; } if (newkey || from_mix == FALSE) { /* create from mesh */ - kb = add_keyblock_ctime(key, name, FALSE); - mesh_to_key(me, kb); + kb = BKE_keyblock_add_ctime(key, name, FALSE); + BKE_key_convert_from_mesh(me, kb); } else { /* copy from current values */ float *data = do_ob_key(scene, ob); /* create new block with prepared data */ - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); kb->data = data; kb->totelem = me->totvert; } @@ -2920,20 +2932,20 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int int newkey = 0; if (key == NULL) { - key = lt->key = add_key((ID *)lt); + key = lt->key = BKE_key_add((ID *)lt); key->type = KEY_RELATIVE; newkey = 1; } if (newkey || from_mix == FALSE) { - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); if (!newkey) { KeyBlock *basekb = (KeyBlock *)key->block.first; kb->data = MEM_dupallocN(basekb->data); kb->totelem = basekb->totelem; } else { - latt_to_key(lt, kb); + BKE_key_convert_from_lattice(lt, kb); } } else { @@ -2941,7 +2953,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int float *data = do_ob_key(scene, ob); /* create new block with prepared data */ - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); kb->totelem = lt->pntsu * lt->pntsv * lt->pntsw; kb->data = data; } @@ -2958,21 +2970,21 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int int newkey = 0; if (key == NULL) { - key = cu->key = add_key((ID *)cu); + key = cu->key = BKE_key_add((ID *)cu); key->type = KEY_RELATIVE; newkey = 1; } if (newkey || from_mix == FALSE) { /* create from curve */ - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); if (!newkey) { KeyBlock *basekb = (KeyBlock *)key->block.first; kb->data = MEM_dupallocN(basekb->data); kb->totelem = basekb->totelem; } else { - curve_to_key(cu, kb, lb); + BKE_key_convert_from_curve(cu, kb, lb); } } else { @@ -2980,7 +2992,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int float *data = do_ob_key(scene, ob); /* create new block with prepared data */ - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); kb->totelem = BKE_nurbList_verts_count(lb); kb->data = data; } @@ -3010,7 +3022,7 @@ int BKE_object_is_modified(Scene *scene, Object *ob) { int flag = 0; - if (ob_get_key(ob)) { + if (BKE_key_from_object(ob)) { flag |= eModifierMode_Render; } else { @@ -3278,7 +3290,7 @@ void BKE_object_groups_clear(Scene *scene, Base *base, Object *object) { Group *group = NULL; - BLI_assert(base->object == object); + BLI_assert((base == NULL) || (base->object == object)); if (scene && base == NULL) { base = BKE_scene_base_find(scene, object); diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c new file mode 100644 index 00000000000..7f9578250f2 --- /dev/null +++ b/source/blender/blenkernel/intern/object_deform.c @@ -0,0 +1,156 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/object_deform.c + * \ingroup bke + */ + +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + +#include "BKE_action.h" +#include "BKE_object_deform.h" /* own include */ +#include "BKE_object.h" +#include "BKE_modifier.h" + +#include "DNA_armature_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" + +/* --- functions for getting vgroup aligned maps --- */ + +/** + * gets the status of "flag" for each bDeformGroup + * in ob->defbase and returns an array containing them + */ +char *BKE_objdef_lock_flags_get(Object *ob, const int defbase_tot) +{ + char is_locked = FALSE; + int i; + //int defbase_tot = BLI_countlist(&ob->defbase); + char *lock_flags = MEM_mallocN(defbase_tot * sizeof(char), "defflags"); + bDeformGroup *defgroup; + + for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { + lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0); + is_locked |= lock_flags[i]; + } + if (is_locked) { + return lock_flags; + } + + MEM_freeN(lock_flags); + return NULL; +} + +char *BKE_objdef_validmap_get(Object *ob, const int defbase_tot) +{ + bDeformGroup *dg; + ModifierData *md; + char *vgroup_validmap; + GHash *gh; + int i, step1 = 1; + //int defbase_tot = BLI_countlist(&ob->defbase); + + if (ob->defbase.first == NULL) { + return NULL; + } + + gh = BLI_ghash_str_new("BKE_objdef_validmap_get gh"); + + /* add all names to a hash table */ + for (dg = ob->defbase.first; dg; dg = dg->next) { + BLI_ghash_insert(gh, dg->name, NULL); + } + + BLI_assert(BLI_ghash_size(gh) == defbase_tot); + + /* now loop through the armature modifiers and identify deform bones */ + for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob) : md->next) { + if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual))) + continue; + + if (md->type == eModifierType_Armature) { + ArmatureModifierData *amd = (ArmatureModifierData *) md; + + if (amd->object && amd->object->pose) { + bPose *pose = amd->object->pose; + bPoseChannel *chan; + + for (chan = pose->chanbase.first; chan; chan = chan->next) { + if (chan->bone->flag & BONE_NO_DEFORM) + continue; + + if (BLI_ghash_remove(gh, chan->name, NULL, NULL)) { + BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1)); + } + } + } + } + } + + vgroup_validmap = MEM_mallocN(defbase_tot, "wpaint valid map"); + + /* add all names to a hash table */ + for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { + vgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL); + } + + BLI_assert(i == BLI_ghash_size(gh)); + + BLI_ghash_free(gh, NULL, NULL); + + return vgroup_validmap; +} + +/* Returns total selected vgroups, + * wpi.defbase_sel is assumed malloc'd, all values are set */ +char *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot) +{ + char *dg_selection = MEM_mallocN(defbase_tot * sizeof(char), __func__); + bDeformGroup *defgroup; + unsigned int i; + Object *armob = BKE_object_pose_armature_get(ob); + (*r_dg_flags_sel_tot) = 0; + + if (armob) { + bPose *pose = armob->pose; + for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { + bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name); + if (pchan && (pchan->bone->flag & BONE_SELECTED)) { + dg_selection[i] = TRUE; + (*r_dg_flags_sel_tot) += 1; + } + else { + dg_selection[i] = FALSE; + } + } + } + else { + memset(dg_selection, FALSE, sizeof(char) * defbase_tot); + } + + return dg_selection; +} diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 66b0cff691e..4f3921936e8 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -37,8 +37,6 @@ #include "BKE_image.h" #include "BKE_ocean.h" -#include "BKE_utildefines.h" - #include "BKE_global.h" // XXX TESTING #include "BLI_math_base.h" @@ -1119,19 +1117,20 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame) /* if image is already loaded in mem, return */ if (och->ibufs_disp[f] != NULL) return; + /* use default color spaces since we know for sure cache files were saved with default settings too */ cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE); - och->ibufs_disp[f] = IMB_loadiffname(string, 0); + och->ibufs_disp[f] = IMB_loadiffname(string, 0, NULL); //if (och->ibufs_disp[f] == NULL) printf("error loading %s\n", string); //else printf("loaded cache %s\n", string); cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM); - och->ibufs_foam[f] = IMB_loadiffname(string, 0); + och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL); //if (och->ibufs_foam[f] == NULL) printf("error loading %s\n", string); //else printf("loaded cache %s\n", string); cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL); - och->ibufs_norm[f] = IMB_loadiffname(string, 0); + och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL); //if (och->ibufs_norm[f] == NULL) printf("error loading %s\n", string); //else printf("loaded cache %s\n", string); } @@ -1174,8 +1173,6 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); - ibuf_disp->profile = ibuf_foam->profile = ibuf_normal->profile = IB_PROFILE_LINEAR_RGB; - BKE_simulate_ocean(o, och->time[i], och->wave_scale, och->chop_amount); /* add new foam */ diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 9787a5025f7..03342d0f6d1 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -57,7 +57,6 @@ #include "BKE_packedFile.h" #include "BKE_report.h" #include "BKE_sound.h" -#include "BKE_utildefines.h" #ifdef _WIN32 #define open _open diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 3267253e744..5a302cba2ab 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -190,7 +190,7 @@ void BKE_paint_free(Paint *paint) } /* called when copying scene settings, so even if 'src' and 'tar' are the same - * still do a id_us_plus(), rather then if we were copying betweem 2 existing + * still do a id_us_plus(), rather then if we were copying between 2 existing * scenes where a matching value should decrease the existing user count as * with paint_brush_set() */ void BKE_paint_copy(Paint *src, Paint *tar) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 26952db8fba..e8af794eaea 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -116,7 +116,7 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur) } return tot; } -/* we allocate path cache memory in chunks instead of a big continguous +/* we allocate path cache memory in chunks instead of a big contiguous * chunk, windows' memory allocater fails to find big blocks of memory often */ #define PATH_CACHE_BUF_SIZE 1024 @@ -3776,7 +3776,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; - ptex->length = 1.0f - part->randlength *PSYS_FRAND(child_index + 26); + ptex->length = 1.0f - part->randlength * PSYS_FRAND(child_index + 26); ptex->length *= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f; for (m = 0; m < MAX_MTEX; m++, mtexp++) { @@ -3968,7 +3968,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float UNUSED size *= part->childsize; if (part->childrandsize != 0.0f) - size *= 1.0f - part->childrandsize *PSYS_FRAND(cpa - psys->child + 26); + size *= 1.0f - part->childrandsize * PSYS_FRAND(cpa - psys->child + 26); return size; } @@ -4539,8 +4539,8 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] /* can happen with bad pointcache or physics calculation * since this becomes geometry, nan's and inf's crash raytrace code. * better not allow this. */ - if (!finite(bb->vec[0]) || !finite(bb->vec[1]) || !finite(bb->vec[2]) || - !finite(bb->vel[0]) || !finite(bb->vel[1]) || !finite(bb->vel[2]) ) + if ((!finite(bb->vec[0])) || (!finite(bb->vec[1])) || (!finite(bb->vec[2])) || + (!finite(bb->vel[0])) || (!finite(bb->vel[1])) || (!finite(bb->vel[2])) ) { zero_v3(bb->vec); zero_v3(bb->vel); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index bae8efa758e..154c8cca75d 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -797,8 +797,10 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch } else { ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel); - psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); - ctx->jitoff[i]++; + if (!isnan(ctx->jitoff[i])) { + psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); + ctx->jitoff[i]++; + } } break; case PART_DISTR_RAND: @@ -3775,8 +3777,8 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) /* Calculate the speed of the particle relative to the local scale of the * simulation. This should be called once per particle during a simulation * step, after the velocity has been updated. element_size defines the scale of - * the simulation, and is typically the distance to neighbourning particles. */ -void update_courant_num(ParticleSimulationData *sim, ParticleData *pa, + * the simulation, and is typically the distance to neighboring particles. */ +static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa, float dtime, SPHData *sphdata) { float relative_vel[3]; @@ -3788,8 +3790,7 @@ void update_courant_num(ParticleSimulationData *sim, ParticleData *pa, sim->courant_num = speed * dtime / sphdata->element_size; } /* Update time step size to suit current conditions. */ -float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, - float t_frac) +static float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, float t_frac) { if (sim->courant_num == 0.0f) psys->dt_frac = 1.0f; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index e990f461d4c..8c0d19ba1fd 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -69,7 +69,6 @@ #include "BKE_scene.h" #include "BKE_smoke.h" #include "BKE_softbody.h" -#include "BKE_utildefines.h" #include "BIK_api.h" @@ -1030,7 +1029,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) { ListBase *lb_dupli_ob; - if ((lb_dupli_ob=object_duplilist(scene, ob))) { + /* don't update the dupli groups, we only wan't their pid's */ + if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE, FALSE))) { DupliObject *dob; for (dob= lb_dupli_ob->first; dob; dob= dob->next) { if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */ @@ -1067,8 +1067,9 @@ static int ptcache_path(PTCacheID *pid, char *filename) if (pid->cache->flag & PTCACHE_EXTERNAL) { strcpy(filename, pid->cache->path); - if (strncmp(filename, "//", 2)==0) + if (BLI_path_is_rel(filename)) { BLI_path_abs(filename, blendfilename); + } return BLI_add_slash(filename); /* new strlen() */ } @@ -2662,32 +2663,59 @@ void BKE_ptcache_free_list(ListBase *ptcaches) } } -static PointCache *ptcache_copy(PointCache *cache) +static PointCache *ptcache_copy(PointCache *cache, int copy_data) { PointCache *ncache; ncache= MEM_dupallocN(cache); - /* hmm, should these be copied over instead? */ ncache->mem_cache.first = NULL; ncache->mem_cache.last = NULL; - ncache->cached_frames = NULL; - ncache->edit = NULL; - ncache->flag= 0; - ncache->simframe= 0; + if (copy_data == FALSE) { + ncache->mem_cache.first = NULL; + ncache->mem_cache.last = NULL; + ncache->cached_frames = NULL; + + ncache->flag= 0; + ncache->simframe= 0; + } + else { + PTCacheMem *pm; + + for (pm = cache->mem_cache.first; pm; pm = pm->next) { + PTCacheMem *pmn = MEM_dupallocN(pm); + int i; + + for (i = 0; i < BPHYS_TOT_DATA; i++) { + if (pmn->data[i]) + pmn->data[i] = MEM_dupallocN(pm->data[i]); + } + + BKE_ptcache_mem_pointers_init(pm); + + BLI_addtail(&ncache->mem_cache, pmn); + } + + if (ncache->cached_frames) + ncache->cached_frames = MEM_dupallocN(cache->cached_frames); + } + + /* hmm, should these be copied over instead? */ + ncache->edit = NULL; return ncache; } + /* returns first point cache */ -PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old) +PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old, int copy_data) { PointCache *cache = ptcaches_old->first; ptcaches_new->first = ptcaches_new->last = NULL; for (; cache; cache=cache->next) - BLI_addtail(ptcaches_new, ptcache_copy(cache)); + BLI_addtail(ptcaches_new, ptcache_copy(cache, copy_data)); return ptcaches_new->first; } diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c index 46ddce4b51b..8da4f11fed3 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -27,9 +27,12 @@ /** \file blender/blenkernel/intern/property.c * \ingroup bke + * + * This module deals with bProperty only, + * they are used on blender objects in the game engine + * (where they get converted into C++ classes - CValue and subclasses) */ - #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -45,7 +48,7 @@ #include "BKE_property.h" -void free_property(bProperty *prop) +void BKE_bproperty_free(bProperty *prop) { if (prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin); @@ -53,17 +56,17 @@ void free_property(bProperty *prop) } -void free_properties(ListBase *lb) +void BKE_bproperty_free_list(ListBase *lb) { bProperty *prop; while ( (prop = lb->first) ) { BLI_remlink(lb, prop); - free_property(prop); + BKE_bproperty_free(prop); } } -bProperty *copy_property(bProperty *prop) +bProperty *BKE_bproperty_copy(bProperty *prop) { bProperty *propn; @@ -76,13 +79,13 @@ bProperty *copy_property(bProperty *prop) return propn; } -void copy_properties(ListBase *lbn, ListBase *lbo) +void BKE_bproperty_copy_list(ListBase *lbn, ListBase *lbo) { bProperty *prop, *propn; - free_properties(lbn); /* in case we are copying to an object with props */ + BKE_bproperty_free_list(lbn); /* in case we are copying to an object with props */ prop = lbo->first; while (prop) { - propn = copy_property(prop); + propn = BKE_bproperty_copy(prop); BLI_addtail(lbn, propn); prop = prop->next; } @@ -90,7 +93,7 @@ void copy_properties(ListBase *lbn, ListBase *lbo) } -void init_property(bProperty *prop) +void BKE_bproperty_init(bProperty *prop) { /* also use when property changes type */ @@ -113,22 +116,22 @@ void init_property(bProperty *prop) } -bProperty *new_property(int type) +bProperty *BKE_bproperty_new(int type) { bProperty *prop; prop = MEM_callocN(sizeof(bProperty), "property"); prop->type = type; - init_property(prop); + BKE_bproperty_init(prop); strcpy(prop->name, "prop"); return prop; } -/* used by unique_property() only */ -static bProperty *get_property__internal(bProperty *first, bProperty *self, const char *name) +/* used by BKE_bproperty_unique() only */ +static bProperty *bproperty_get(bProperty *first, bProperty *self, const char *name) { bProperty *p; for (p = first; p; p = p->next) { @@ -137,7 +140,7 @@ static bProperty *get_property__internal(bProperty *first, bProperty *self, cons } return NULL; } -void unique_property(bProperty *first, bProperty *prop, int force) +void BKE_bproperty_unique(bProperty *first, bProperty *prop, int force) { bProperty *p; @@ -151,13 +154,13 @@ void unique_property(bProperty *first, bProperty *prop, int force) if (force) { /* change other names to make them unique */ - while ((p = get_property__internal(first, prop, prop->name))) { - unique_property(first, p, 0); + while ((p = bproperty_get(first, prop, prop->name))) { + BKE_bproperty_unique(first, p, 0); } } else { /* change our own name until its unique */ - if (get_property__internal(first, prop, prop->name)) { + if (bproperty_get(first, prop, prop->name)) { /* there is a collision */ char new_name[sizeof(prop->name)]; char base_name[sizeof(prop->name)]; @@ -175,33 +178,34 @@ void unique_property(bProperty *first, bProperty *prop, int force) BLI_snprintf(num, sizeof(num), "%d", i++); BLI_strncpy(new_name, base_name, sizeof(prop->name) - strlen(num)); strcat(new_name, num); - } while (get_property__internal(first, prop, new_name)); + } while (bproperty_get(first, prop, new_name)); BLI_strncpy(prop->name, new_name, sizeof(prop->name)); } } } -bProperty *get_ob_property(Object *ob, const char *name) +bProperty *BKE_bproperty_object_get(Object *ob, const char *name) { return BLI_findstring(&ob->prop, name, offsetof(bProperty, name)); } -void set_ob_property(Object *ob, bProperty *propc) +void BKE_bproperty_object_set(Object *ob, bProperty *propc) { bProperty *prop; - prop = get_ob_property(ob, propc->name); + prop = BKE_bproperty_object_get(ob, propc->name); if (prop) { - free_property(prop); + BKE_bproperty_free(prop); BLI_remlink(&ob->prop, prop); } - BLI_addtail(&ob->prop, copy_property(propc)); + BLI_addtail(&ob->prop, BKE_bproperty_copy(propc)); } /* negative: prop is smaller * positive: prop is larger */ -int compare_property(bProperty *prop, const char *str) +#if 0 /* UNUSED */ +int BKE_bproperty_cmp(bProperty *prop, const char *str) { // extern int Gdfra; /* sector.c */ float fvalue, ftest; @@ -237,8 +241,9 @@ int compare_property(bProperty *prop, const char *str) return 0; } +#endif -void set_property(bProperty *prop, const char *str) +void BKE_bproperty_set(bProperty *prop, const char *str) { // extern int Gdfra; /* sector.c */ @@ -262,7 +267,7 @@ void set_property(bProperty *prop, const char *str) } -void add_property(bProperty *prop, const char *str) +void BKE_bproperty_add(bProperty *prop, const char *str) { // extern int Gdfra; /* sector.c */ @@ -282,7 +287,7 @@ void add_property(bProperty *prop, const char *str) } /* reads value of property, sets it in chars in str */ -void set_property_valstr(bProperty *prop, char *str) +void BKE_bproperty_set_valstr(bProperty *prop, char *str) { // extern int Gdfra; /* sector.c */ @@ -303,11 +308,13 @@ void set_property_valstr(bProperty *prop, char *str) } } +#if 0 /* UNUSED */ void cp_property(bProperty *prop1, bProperty *prop2) { char str[128]; - set_property_valstr(prop2, str); + BKE_bproperty_set_valstr(prop2, str); - set_property(prop1, str); + BKE_bproperty_set(prop1, str); } +#endif diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index c440d21f56d..6c1fbbfa9a0 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -44,7 +44,6 @@ #include "DNA_object_types.h" #include "BLI_blenlib.h" -#include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_library.h" @@ -211,7 +210,7 @@ void unlink_controllers(ListBase *lb) bController *cont; for (cont= lb->first; cont; cont= cont->next) - unlink_controller(cont); + unlink_controller(cont); } void free_controller(bController *cont) @@ -537,7 +536,7 @@ void clear_sca_new_poins(void) ob= G.main->object.first; while (ob) { clear_sca_new_poins_ob(ob); - ob= ob->id.next; + ob= ob->id.next; } } @@ -625,7 +624,7 @@ void set_sca_new_poins(void) ob= G.main->object.first; while (ob) { set_sca_new_poins_ob(ob); - ob= ob->id.next; + ob= ob->id.next; } } @@ -697,7 +696,7 @@ void sca_remove_ob_poin(Object *obt, Object *ob) if (sta->target == ob) sta->target = NULL; } act= act->next; - } + } } /* ******************** INTERFACE ******************* */ @@ -876,3 +875,20 @@ void unlink_logicbricks(void **poin, void ***ppoin, short *tot) return; } } + +const char *sca_state_name_get(Object *ob, short bit) +{ + bController *cont; + unsigned int mask; + + mask = (1<<bit); + cont = ob->controllers.first; + while (cont) { + if (cont->state_mask & mask) { + return cont->name; + } + cont = cont->next; + } + return NULL; +} + diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d476e90498c..f8777f87369 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -57,6 +57,7 @@ #include "BKE_anim.h" #include "BKE_animsys.h" +#include "BKE_colortools.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_group.h" @@ -76,6 +77,8 @@ #include "RE_engine.h" +#include "IMB_colormanagement.h" + //XXX #include "BIF_previewrender.h" //XXX #include "BIF_editseq.h" @@ -153,7 +156,8 @@ Scene *BKE_scene_copy(Scene *sce, int type) BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); if (sce->nodetree) { - scen->nodetree = ntreeCopyTree(sce->nodetree); /* copies actions */ + /* ID's are managed on both copy and switch */ + scen->nodetree = ntreeCopyTree(sce->nodetree); ntreeSwitchID(scen->nodetree, &sce->id, &scen->id); } @@ -166,6 +170,11 @@ Scene *BKE_scene_copy(Scene *sce, int type) obase = obase->next; base = base->next; } + + /* copy color management settings */ + BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings); + BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings); + BKE_color_managed_view_settings_copy(&scen->r.im_format.view_settings, &sce->r.im_format.view_settings); } /* tool settings */ @@ -331,6 +340,8 @@ void BKE_scene_free(Scene *sce) MEM_freeN(sce->fps_info); sound_destroy_scene(sce); + + BKE_color_managed_view_settings_free(&sce->view_settings); } Scene *BKE_scene_add(const char *name) @@ -371,7 +382,14 @@ Scene *BKE_scene_add(const char *name) sce->r.frs_sec_base = 1; sce->r.edgeint = 10; sce->r.ocres = 128; + + /* OCIO_TODO: for forwards compatibility only, so if no tonecurve are used, + * images would look in the same way as in current blender + * + * perhaps at some point should be completely deprecated? + */ sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT; + sce->r.gauss = 1.0; /* deprecated but keep for upwards compat */ @@ -545,6 +563,9 @@ Scene *BKE_scene_add(const char *name) sound_create_scene(sce); + BKE_color_managed_display_settings_init(&sce->display_settings); + BKE_color_managed_view_settings_init(&sce->view_settings); + return sce; } @@ -723,7 +744,7 @@ int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob) * this enters eternal loop because of * makeDispListMBall getting called inside of group_duplilist */ if ((*base)->object->dup_group == NULL) { - duplilist = object_duplilist((*scene), (*base)->object); + duplilist = object_duplilist((*scene), (*base)->object, FALSE); dupob = duplilist->first; @@ -1239,3 +1260,26 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene) base = base->next; } } + +void BKE_scene_disable_color_management(Scene *scene) +{ + ColorManagedDisplaySettings *display_settings = &scene->display_settings; + ColorManagedViewSettings *view_settings = &scene->view_settings; + const char *view; + const char *none_display_name; + + none_display_name = IMB_colormanagement_display_get_none_name(); + + BLI_strncpy(display_settings->display_device, none_display_name, sizeof(display_settings->display_device)); + + view = IMB_colormanagement_view_get_default_name(display_settings->display_device); + + if (view) { + BLI_strncpy(view_settings->view_transform, view, sizeof(view_settings->view_transform)); + } +} + +int BKE_scene_check_color_management_enabled(const Scene *scene) +{ + return strcmp(scene->display_settings.display_device, "None") != 0; +} diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 87906337ca2..33519483843 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -49,14 +49,14 @@ #include "BKE_main.h" #include "BKE_sequencer.h" #include "BKE_texture.h" -#include "BKE_utildefines.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "RNA_access.h" -static void slize_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, +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) { @@ -72,7 +72,7 @@ static void slize_get_byte_buffers(const SeqRenderData *context, const ImBuf *ib *rect3 = (unsigned char*) ibuf3->rect + offset; } -static void slize_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, +static void slice_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, const ImBuf *ibuf3, const ImBuf *out, int start_line, float **rect1, float **rect2, float **rect3, float **rect_out) { @@ -120,13 +120,13 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * } if (ibuf1 && !ibuf1->rect_float && out->rect_float) { - IMB_float_from_rect_simple(ibuf1); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf1, TRUE); } if (ibuf2 && !ibuf2->rect_float && out->rect_float) { - IMB_float_from_rect_simple(ibuf2); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf2, TRUE); } if (ibuf3 && !ibuf3->rect_float && out->rect_float) { - IMB_float_from_rect_simple(ibuf3); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf3, TRUE); } if (ibuf1 && !ibuf1->rect && !out->rect_float) { @@ -138,7 +138,7 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * if (ibuf3 && !ibuf3->rect && !out->rect_float) { IMB_rect_from_float(ibuf3); } - + return out; } @@ -286,14 +286,14 @@ static void do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), fl if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_alphaover_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); } @@ -448,14 +448,14 @@ static void do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), f if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_alphaunder_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); } @@ -558,14 +558,14 @@ static void do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_cross_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); } @@ -609,9 +609,9 @@ static void makeGammaTables(float gamma) /* The end of the table should match 1.0 carefully. In order to avoid * rounding errors, we just set this explicitly. The last segment may - * have a different length than the other segments, but our - * interpolation is insensitive to that - */ + * have a different length than the other segments, but our + * interpolation is insensitive to that + */ color_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0; gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; @@ -807,14 +807,14 @@ static void do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), f if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_gammacross_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_gammacross_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } @@ -913,14 +913,14 @@ static void do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_add_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_add_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } @@ -1017,14 +1017,14 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_sub_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out); } @@ -1214,14 +1214,14 @@ static void do_mul_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_mul_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_mul_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out); } @@ -2748,7 +2748,7 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo if (out->rect_float) { float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_drop_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out); do_alphaover_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out); @@ -2756,7 +2756,7 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo else { unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; - slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); + slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out); do_drop_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out); do_alphaover_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out); diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 26c2fe03688..b0dcad64722 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -43,7 +43,6 @@ #include "BKE_colortools.h" #include "BKE_sequencer.h" -#include "BKE_utildefines.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -141,7 +140,7 @@ static void modifier_apply_threaded(ImBuf *ibuf, ImBuf *mask, modifier_apply_thr /* **** Color Balance Modifier **** */ -void colorBalance_init_data(SequenceModifierData *smd) +static void colorBalance_init_data(SequenceModifierData *smd) { ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd; int c; @@ -155,14 +154,11 @@ void colorBalance_init_data(SequenceModifierData *smd) } } -ImBuf *colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +static void colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd; - ImBuf *ibuf_new = IMB_dupImBuf(ibuf); - BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf_new, cbmd->color_multiply, FALSE, mask); - - return ibuf_new; + BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf, cbmd->color_multiply, FALSE, mask); } static SequenceModifierTypeInfo seqModifier_ColorBalance = { @@ -177,21 +173,21 @@ static SequenceModifierTypeInfo seqModifier_ColorBalance = { /* **** Curves Modifier **** */ -void curves_init_data(SequenceModifierData *smd) +static void curves_init_data(SequenceModifierData *smd) { CurvesModifierData *cmd = (CurvesModifierData *) smd; curvemapping_set_defaults(&cmd->curve_mapping, 4, 0.0f, 0.0f, 1.0f, 1.0f); } -void curves_free_data(SequenceModifierData *smd) +static void curves_free_data(SequenceModifierData *smd) { CurvesModifierData *cmd = (CurvesModifierData *) smd; curvemapping_free_data(&cmd->curve_mapping); } -void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd) +static void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd) { CurvesModifierData *cmd = (CurvesModifierData *) smd; CurvesModifierData *cmd_target = (CurvesModifierData *) target; @@ -199,8 +195,8 @@ void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd) curvemapping_copy_data(&cmd_target->curve_mapping, &cmd->curve_mapping); } -void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, - unsigned char *mask_rect, float *mask_rect_float, void *data_v) +static void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, + unsigned char *mask_rect, float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *) data_v; int x, y; @@ -253,10 +249,9 @@ void curves_apply_threaded(int width, int height, unsigned char *rect, float *re } } -ImBuf *curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +static void curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { CurvesModifierData *cmd = (CurvesModifierData *) smd; - ImBuf *ibuf_new = IMB_dupImBuf(ibuf); float black[3] = {0.0f, 0.0f, 0.0f}; float white[3] = {1.0f, 1.0f, 1.0f}; @@ -266,11 +261,9 @@ ImBuf *curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) curvemapping_premultiply(&cmd->curve_mapping, 0); curvemapping_set_black_white(&cmd->curve_mapping, black, white); - modifier_apply_threaded(ibuf_new, mask, curves_apply_threaded, &cmd->curve_mapping); + modifier_apply_threaded(ibuf, mask, curves_apply_threaded, &cmd->curve_mapping); curvemapping_premultiply(&cmd->curve_mapping, 1); - - return ibuf_new; } static SequenceModifierTypeInfo seqModifier_Curves = { @@ -285,7 +278,7 @@ static SequenceModifierTypeInfo seqModifier_Curves = { /* **** Hue Correct Modifier **** */ -void hue_correct_init_data(SequenceModifierData *smd) +static void hue_correct_init_data(SequenceModifierData *smd) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; int c; @@ -303,14 +296,14 @@ void hue_correct_init_data(SequenceModifierData *smd) hcmd->curve_mapping.cur = 1; } -void hue_correct_free_data(SequenceModifierData *smd) +static void hue_correct_free_data(SequenceModifierData *smd) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; curvemapping_free_data(&hcmd->curve_mapping); } -void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *smd) +static void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *smd) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; HueCorrectModifierData *hcmd_target = (HueCorrectModifierData *) target; @@ -318,7 +311,7 @@ void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *s curvemapping_copy_data(&hcmd_target->curve_mapping, &hcmd->curve_mapping); } -void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, +static void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, unsigned char *mask_rect, float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *) data_v; @@ -372,16 +365,13 @@ void hue_correct_apply_threaded(int width, int height, unsigned char *rect, floa } } -ImBuf *hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +static void hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; - ImBuf *ibuf_new = IMB_dupImBuf(ibuf); curvemapping_initialize(&hcmd->curve_mapping); - modifier_apply_threaded(ibuf_new, mask, hue_correct_apply_threaded, &hcmd->curve_mapping); - - return ibuf_new; + modifier_apply_threaded(ibuf, mask, hue_correct_apply_threaded, &hcmd->curve_mapping); } static SequenceModifierTypeInfo seqModifier_HueCorrect = { @@ -394,6 +384,103 @@ static SequenceModifierTypeInfo seqModifier_HueCorrect = { hue_correct_apply /* apply */ }; +/* **** Bright/Contrast Modifier **** */ + +typedef struct BrightContrastThreadData { + float bright; + float contrast; +} BrightContrastThreadData; + +static void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, + unsigned char *mask_rect, float *mask_rect_float, void *data_v) +{ + BrightContrastThreadData *data = (BrightContrastThreadData *) data_v; + int x, y; + + float i; + int c; + float a, b, v; + float brightness = data->bright / 100.0f; + float contrast = data->contrast; + float delta = contrast / 200.0f; + + a = 1.0f - delta * 2.0f; + /* + * The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ + if (contrast > 0) { + a = 1.0f / a; + b = a * (brightness - delta); + } + else { + delta *= -1; + b = a * (brightness + delta); + } + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + int pixel_index = (y * width + x) * 4; + + if (rect) { + unsigned char *pixel = rect + pixel_index; + + for (c = 0; c < 3; c++) { + i = pixel[c]; + v = a * i + b; + + if (mask_rect) { + unsigned char *m = mask_rect + pixel_index; + float t = (float) m[c] / 255.0f; + + pixel[c] = pixel[c] * (1.0f - t) + v * t; + } + else + pixel[c] = v; + } + } + else if (rect_float) { + float *pixel = rect_float + pixel_index; + + for (c = 0; c < 3; c++) { + i = pixel[c]; + v = a * i + b; + + if (mask_rect_float) { + float *m = mask_rect_float + pixel_index; + + pixel[c] = pixel[c] * (1.0f - m[c]) + v * m[c]; + } + else + pixel[c] = v; + } + } + } + } +} + +static void brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +{ + BrightContrastModifierData *bcmd = (BrightContrastModifierData *) smd; + BrightContrastThreadData data; + + data.bright = bcmd->bright; + data.contrast = bcmd->contrast; + + modifier_apply_threaded(ibuf, mask, brightcontrast_apply_threaded, &data); +} + +static SequenceModifierTypeInfo seqModifier_BrightContrast = { + "Bright/Contrast", /* name */ + "BrightContrastModifierData", /* struct_name */ + sizeof(BrightContrastModifierData), /* struct_size */ + NULL, /* init_data */ + NULL, /* free_data */ + NULL, /* copy_data */ + brightcontrast_apply /* apply */ +}; + /*********************** Modifier functions *************************/ static void sequence_modifier_type_info_init(void) @@ -403,6 +490,7 @@ static void sequence_modifier_type_info_init(void) INIT_TYPE(ColorBalance); INIT_TYPE(Curves); INIT_TYPE(HueCorrect); + INIT_TYPE(BrightContrast); #undef INIT_TYPE } @@ -493,9 +581,13 @@ ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, I SequenceModifierData *smd; ImBuf *processed_ibuf = ibuf; + if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) { + processed_ibuf = IMB_dupImBuf(ibuf); + BKE_sequencer_imbuf_from_sequencer_space(context.scene, processed_ibuf); + } + for (smd = seq->modifiers.first; smd; smd = smd->next) { SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); - ImBuf *ibuf_new; /* could happen if modifier is being removed or not exists in current version of blender */ if (!smti) @@ -511,18 +603,17 @@ ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, I if (processed_ibuf == ibuf) processed_ibuf = IMB_dupImBuf(ibuf); - ibuf_new = smti->apply(smd, processed_ibuf, mask); - - if (ibuf_new != processed_ibuf) { - IMB_freeImBuf(processed_ibuf); - processed_ibuf = ibuf_new; - } + smti->apply(smd, processed_ibuf, mask); if (mask) IMB_freeImBuf(mask); } } + if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) { + BKE_sequencer_imbuf_to_sequencer_space(context.scene, processed_ibuf, FALSE); + } + return processed_ibuf; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 3699f802c91..90c3347a1df 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -62,7 +62,6 @@ #include "BKE_fcurve.h" #include "BKE_scene.h" #include "BKE_mask.h" -#include "BKE_utildefines.h" #include "RNA_access.h" @@ -72,6 +71,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "BKE_context.h" #include "BKE_sound.h" @@ -166,14 +166,12 @@ static void seq_free_strip(Strip *strip) if (strip->transform) { MEM_freeN(strip->transform); } - if (strip->color_balance) { - MEM_freeN(strip->color_balance); - } MEM_freeN(strip); } -void BKE_sequence_free(Scene *scene, Sequence *seq) +/* only give option to skip cache locally (static func) */ +static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const int do_cache) { if (seq->strip) seq_free_strip(seq->strip); @@ -207,21 +205,39 @@ void BKE_sequence_free(Scene *scene, Sequence *seq) /* free modifiers */ BKE_sequence_modifier_clear(seq); - BKE_sequencer_cache_cleanup_sequence(seq); - BKE_sequencer_preprocessed_cache_cleanup_sequence(seq); + /* free cached data used by this strip, + * also invalidate cache for all dependent sequences + * + * be _very_ careful here, invalidating cache loops over the scene sequences and + * assumes the listbase is valid for all strips, this may not be the case if lists are being freed. + * this is optional BKE_sequence_invalidate_cache + */ + if (do_cache) { + if (scene) { + BKE_sequence_invalidate_cache(scene, seq); + } + } MEM_freeN(seq); } +void BKE_sequence_free(Scene *scene, Sequence *seq) +{ + BKE_sequence_free_ex(scene, seq, TRUE); +} + +/* cache must be freed before calling this function + * since it leaves the seqbase in an invalid state */ static void seq_free_sequence_recurse(Scene *scene, Sequence *seq) { - Sequence *iseq; + Sequence *iseq, *iseq_next; - for (iseq = seq->seqbase.first; iseq; iseq = iseq->next) { + for (iseq = seq->seqbase.first; iseq; iseq = iseq_next) { + iseq_next = iseq->next; seq_free_sequence_recurse(scene, iseq); } - BKE_sequence_free(scene, seq); + BKE_sequence_free_ex(scene, seq, FALSE); } @@ -242,7 +258,7 @@ static void seq_free_clipboard_recursive(Sequence *seq_parent) seq_free_clipboard_recursive(seq); } - BKE_sequence_free(NULL, seq_parent); + BKE_sequence_free_ex(NULL, seq_parent, FALSE); } void BKE_sequencer_free_clipboard(void) @@ -271,28 +287,103 @@ Editing *BKE_sequencer_editing_ensure(Scene *scene) void BKE_sequencer_editing_free(Scene *scene) { Editing *ed = scene->ed; - MetaStack *ms; Sequence *seq; if (ed == NULL) return; + /* this may not be the active scene!, could be smarter about this */ + BKE_sequencer_cache_cleanup(); + SEQ_BEGIN (ed, seq) { - BKE_sequence_free(scene, seq); + /* handle cache freeing above */ + BKE_sequence_free_ex(scene, seq, FALSE); } SEQ_END - while ((ms = ed->metastack.first)) { - BLI_remlink(&ed->metastack, ms); - MEM_freeN(ms); - } + BLI_freelistN(&ed->metastack); MEM_freeN(ed); scene->ed = NULL; } +/*********************** Sequencer color space functions *************************/ + +static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) +{ + IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name); +} + +void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_float) +{ + const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + const char *to_colorspace = scene->sequencer_colorspace_settings.name; + int predivide = ibuf->flags & IB_cm_predivide; + + if (!ibuf->rect_float) { + if (make_float && ibuf->rect) { + /* when converting byte buffer to float in sequencer we need to make float + * buffer be in sequencer's working space, which is currently only doable + * from linear space. + * + */ + + /* + * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's + */ + + IMB_float_from_rect(ibuf); + } + else { + /* if there's only byte buffer in image it's already in compositor's working space, + * nothing to do here + */ + + return; + } + } + + if (from_colorspace && from_colorspace[0] != '\0') { + if (ibuf->rect) + imb_freerectImBuf(ibuf); + + IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, predivide); + } +} + +void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) +{ + const char *from_colorspace = scene->sequencer_colorspace_settings.name; + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + + if (!ibuf->rect_float) + return; + + if (to_colorspace && to_colorspace[0] != '\0') { + int predivide = ibuf->flags & IB_cm_predivide; + + IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, predivide); + } +} + +void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4]) +{ + const char *from_colorspace = scene->sequencer_colorspace_settings.name; + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + + if (to_colorspace && to_colorspace[0] != '\0') { + IMB_colormanagement_transform_v4(pixel, from_colorspace, to_colorspace); + } + else { + /* if no color management enables fallback to legacy conversion */ + srgb_to_linearrgb_v4(pixel, pixel); + } +} + /*********************** sequencer pipeline functions *************************/ SeqRenderData BKE_sequencer_new_render_data(Main *bmain, Scene *scene, int rectx, int recty, int preview_render_size) @@ -370,7 +461,7 @@ static void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_point seq_build_array(&ed->seqbase, &array, 0); } -void BKE_seqence_iterator_begin(Editing *ed, SeqIterator *iter, int use_pointer) +void BKE_sequence_iterator_begin(Editing *ed, SeqIterator *iter, int use_pointer) { memset(iter, 0, sizeof(*iter)); seq_array(ed, &iter->array, &iter->tot, use_pointer); @@ -382,7 +473,7 @@ void BKE_seqence_iterator_begin(Editing *ed, SeqIterator *iter, int use_pointer) } } -void BKE_seqence_iterator_next(SeqIterator *iter) +void BKE_sequence_iterator_next(SeqIterator *iter) { if (++iter->cur < iter->tot) iter->seq = iter->array[iter->cur]; @@ -390,7 +481,7 @@ void BKE_seqence_iterator_next(SeqIterator *iter) iter->valid = 0; } -void BKE_seqence_iterator_end(SeqIterator *iter) +void BKE_sequence_iterator_end(SeqIterator *iter) { if (iter->array) MEM_freeN(iter->array); @@ -582,7 +673,9 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, int lock_range) BLI_path_abs(str, G.main->name); if (seq->anim) IMB_free_anim(seq->anim); - seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex); + + /* OCIO_TODO: support configurable input space for strips */ + seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, NULL); if (!seq->anim) { return; @@ -750,7 +843,7 @@ static int seqbase_unique_name_recursive_cb(Sequence *seq, void *arg_pt) return 1; } -void BKE_seqence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) +void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) { SeqUniqueInfo sui; char *dot; @@ -1079,7 +1172,8 @@ static void seq_open_anim_file(Sequence *seq) seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(name, G.main->name); - seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex); + /* OCIO_TODO: support configurable input space for strips */ + seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, NULL); if (seq->anim == NULL) { return; @@ -1185,8 +1279,9 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra) if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) { return NULL; } - - seq->strip->proxy->anim = openanim(name, IB_rect, 0); + + /* proxies are generated in default color space */ + seq->strip->proxy->anim = openanim(name, IB_rect, 0, NULL); } if (seq->strip->proxy->anim == NULL) { return NULL; @@ -1204,7 +1299,13 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra) } if (BLI_exists(name)) { - return IMB_loadiffname(name, IB_rect); + /* OCIO_TODO: support configurable spaces for strips */ + ImBuf *ibuf = IMB_loadiffname(name, IB_rect, NULL); + + if (ibuf) + sequencer_imbuf_assign_spaces(context.scene, ibuf); + + return ibuf; } else { return NULL; @@ -1242,7 +1343,8 @@ static void seq_proxy_build_frame(SeqRenderData context, Sequence *seq, int cfra ibuf->planes = 24; BLI_make_existing_file(name); - + + /* OCIO_TODO: support per-strip color space settings */ ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); if (ok == 0) { perror(name); @@ -1669,26 +1771,6 @@ void BKE_sequencer_color_balance_apply(StripColorBalance *cb, ImBuf *ibuf, float imb_freerectImBuf(ibuf); } -static void sequence_color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra) -{ - StripColorBalance *cb = seq->strip->color_balance; - ImBuf *mask_input = NULL; - short make_float = seq->flag & SEQ_MAKE_FLOAT; - - if (seq->mask_sequence) { - if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) { - int make_float = ibuf->rect_float != NULL; - - mask_input = BKE_sequencer_render_mask_input(context, SEQUENCE_MASK_INPUT_STRIP, seq->mask_sequence, NULL, cfra, make_float); - } - } - - BKE_sequencer_color_balance_apply(cb, ibuf, mul, make_float, mask_input); - - if (mask_input) - IMB_freeImBuf(mask_input); -} - /* * input preprocessing for SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP and SEQ_TYPE_SCENE * @@ -1711,9 +1793,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen { float mul; - if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | - SEQ_FLIPY | SEQ_USE_COLOR_BALANCE | SEQ_MAKE_PREMUL)) - { + if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) { return TRUE; } @@ -1755,8 +1835,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, StripCrop c = {0}; StripTransform t = {0}; int sx, sy, dx, dy; - double xscale = 1.0; - double yscale = 1.0; if (is_proxy_image) { double f = seq_rendersize_to_scale_factor(context.preview_render_size); @@ -1773,14 +1851,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, t = *seq->strip->transform; } - xscale = context.scene->r.xsch ? ((double) context.rectx / (double) context.scene->r.xsch) : 1.0; - yscale = context.scene->r.ysch ? ((double) context.recty / (double) context.scene->r.ysch) : 1.0; - - c.left *= xscale; c.right *= xscale; - c.top *= yscale; c.bottom *= yscale; - - t.xofs *= xscale; t.yofs *= yscale; - sx = ibuf->x - c.left - c.right; sy = ibuf->y - c.top - c.bottom; dx = sx; @@ -1832,14 +1902,10 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, mul *= seq->blend_opacity / 100.0f; } - if (seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) { - sequence_color_balance(context, seq, ibuf, mul, cfra); - mul = 1.0; - } - if (seq->flag & SEQ_MAKE_FLOAT) { - if (!ibuf->rect_float) - IMB_float_from_rect_simple(ibuf); + if (!ibuf->rect_float) { + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, TRUE); + } if (ibuf->rect) { imb_freerectImBuf(ibuf); @@ -1905,6 +1971,8 @@ static void copy_to_ibuf_still(SeqRenderData context, Sequence *seq, float nr, I * changing the cached image... */ ibuf = IMB_dupImBuf(ibuf); + sequencer_imbuf_assign_spaces(context.scene, ibuf); + if (nr == 0) { BKE_sequencer_cache_put(context, seq, seq->start, SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf); } @@ -2108,7 +2176,7 @@ static ImBuf *seq_render_movieclip_strip(SeqRenderData context, Sequence *seq, f memset(&user, 0, sizeof(MovieClipUser)); - BKE_movieclip_user_set_frame(&user, nr + seq->anim_startofs); + BKE_movieclip_user_set_frame(&user, nr + seq->anim_startofs + seq->clip->start_frame); user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; @@ -2169,7 +2237,7 @@ static ImBuf *seq_render_mask(SeqRenderData context, Mask *mask, float nr, short BKE_maskrasterize_handle_init(mr_handle, mask_temp, context.rectx, context.recty, TRUE, TRUE, TRUE); - BKE_mask_free(mask_temp); + BKE_mask_free_nolib(mask_temp); MEM_freeN(mask_temp); BKE_maskrasterize_buffer(mr_handle, context.rectx, context.recty, maskbuf); @@ -2319,7 +2387,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float /* opengl offscreen render */ BKE_scene_update_for_newframe(context.bmain, scene, scene->lay); ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty, - IB_rect, context.scene->r.seq_prev_type, TRUE, err_out); + IB_rect, context.scene->r.seq_prev_type, TRUE, FALSE, err_out); if (ibuf == NULL) { fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out); } @@ -2350,11 +2418,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float } /* float buffers in the sequencer are not linear */ - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - else - ibuf->profile = IB_PROFILE_NONE; - IMB_convert_profile(ibuf, IB_PROFILE_SRGB); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); } else if (rres.rect32) { ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect); @@ -2454,14 +2518,14 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo BLI_path_abs(name, G.main->name); } - if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) { + /* OCIO_TODO: support configurable space for image strips */ + if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, NULL))) { /* we don't need both (speed reasons)! */ if (ibuf->rect_float && ibuf->rect) imb_freerectImBuf(ibuf); /* all sequencer color is done in SRGB space, linear gives odd crossfades */ - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) - IMB_convert_profile(ibuf, IB_PROFILE_NONE); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); copy_to_ibuf_still(context, seq, nr, ibuf); @@ -2510,15 +2574,18 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo { ibuf = seq_render_movieclip_strip(context, seq, nr); - if (ibuf && use_preprocess) { + if (ibuf) { + /* duplicate frame so movie cache wouldn't be confused by sequencer's stuff */ ImBuf *i = IMB_dupImBuf(ibuf); - IMB_freeImBuf(ibuf); - ibuf = i; + + if (ibuf->rect_float) + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); + + copy_to_ibuf_still(context, seq, nr, ibuf); } - copy_to_ibuf_still(context, seq, nr, ibuf); break; } @@ -2532,6 +2599,9 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo } } + if (ibuf) + sequencer_imbuf_assign_spaces(context.scene, ibuf); + return ibuf; } @@ -2565,15 +2635,18 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) is_proxy_image = (ibuf != NULL); } - ibuf = do_render_strip_uncached(context, seq, cfra); + if (ibuf == NULL) + ibuf = do_render_strip_uncached(context, seq, cfra); if (ibuf) BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); } } - if (ibuf == NULL) + if (ibuf == NULL) { ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); + sequencer_imbuf_assign_spaces(context.scene, ibuf); + } if (ibuf->x != context.rectx || ibuf->y != context.recty) use_preprocess = TRUE; @@ -2652,12 +2725,12 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, if (count == 1) { out = seq_render_strip(context, seq_arr[0], cfra); + BKE_sequencer_cache_put(context, seq_arr[0], cfra, SEQ_STRIPELEM_IBUF_COMP, out); return out; } - for (i = count - 1; i >= 0; i--) { int early_out; Sequence *seq = seq_arr[i]; @@ -2935,6 +3008,9 @@ static void free_anim_seq(Sequence *seq) /* check whether sequence cur depends on seq */ int BKE_sequence_check_depend(Sequence *seq, Sequence *cur) { + if (cur->seq1 == seq || cur->seq2 == seq || cur->seq3 == seq) + return TRUE; + /* sequences are not intersecting in time, assume no dependency exists between them */ if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp) return FALSE; @@ -2956,20 +3032,11 @@ int BKE_sequence_check_depend(Sequence *seq, Sequence *cur) return TRUE; } -static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidate_preprocess) +static void sequence_do_invalidate_dependent(Sequence *seq, ListBase *seqbase) { - Editing *ed = scene->ed; Sequence *cur; - /* invalidate cache for current sequence */ - BKE_sequencer_cache_cleanup_sequence(seq); - - if (invalidate_preprocess) - BKE_sequencer_preprocessed_cache_cleanup_sequence(seq); - - /* invalidate cache for all dependent sequences */ - SEQ_BEGIN (ed, cur) - { + for (cur = seqbase->first; cur; cur = cur->next) { if (cur == seq) continue; @@ -2977,60 +3044,71 @@ static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidat BKE_sequencer_cache_cleanup_sequence(cur); BKE_sequencer_preprocessed_cache_cleanup_sequence(cur); } + + if (cur->seqbase.first) + sequence_do_invalidate_dependent(seq, &cur->seqbase); } - SEQ_END +} + +static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidate_self, int invalidate_preprocess) +{ + Editing *ed = scene->ed; + + /* invalidate cache for current sequence */ + if (invalidate_self) + BKE_sequencer_cache_cleanup_sequence(seq); + + /* if invalidation is invoked from sequence free routine, effectdata would be NULL here */ + if (seq->effectdata && seq->type == SEQ_TYPE_SPEED) + BKE_sequence_effect_speed_rebuild_map(scene, seq, TRUE); + + if (invalidate_preprocess) + BKE_sequencer_preprocessed_cache_cleanup_sequence(seq); + + /* invalidate cache for all dependent sequences */ + + /* NOTE: can not use SEQ_BEGIN/SEQ_END here because that macro will change sequence's depth, + * which makes transformation routines work incorrect + */ + sequence_do_invalidate_dependent(seq, &ed->seqbase); } void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq) { - sequence_invalidate_cache(scene, seq, TRUE); + sequence_invalidate_cache(scene, seq, TRUE, TRUE); +} + +void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq) +{ + sequence_invalidate_cache(scene, seq, FALSE, TRUE); } void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq) { - sequence_invalidate_cache(scene, seq, FALSE); + sequence_invalidate_cache(scene, seq, TRUE, FALSE); } -void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, int check_mem_usage, int keep_file_handles) +void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, int for_render) { Sequence *seq; - if (check_mem_usage) { - /* Let the cache limitor take care of this (schlaile) */ - /* While render let's keep all memory available for render - * (ton) - * At least if free memory is tight... - * This can make a big difference in encoding speed - * (it is around 4 times(!) faster, if we do not waste time - * on freeing _all_ buffers every time on long timelines...) - * (schlaile) - */ - - uintptr_t mem_in_use; - uintptr_t mmap_in_use; - uintptr_t max; - - mem_in_use = MEM_get_memory_in_use(); - mmap_in_use = MEM_get_mapped_memory_in_use(); - max = MEM_CacheLimiter_get_maximum(); - - if (max == 0 || mem_in_use + mmap_in_use <= max) { - return; - } - } - BKE_sequencer_cache_cleanup(); - + for (seq = seqbase->first; seq; seq = seq->next) { + if (for_render && CFRA >= seq->startdisp && CFRA <= seq->enddisp) { + continue; + } + if (seq->strip) { - if (seq->type == SEQ_TYPE_MOVIE && !keep_file_handles) + if (seq->type == SEQ_TYPE_MOVIE) { free_anim_seq(seq); + } if (seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, 1); } } if (seq->type == SEQ_TYPE_META) { - BKE_sequencer_free_imbuf(scene, &seq->seqbase, FALSE, keep_file_handles); + BKE_sequencer_free_imbuf(scene, &seq->seqbase, for_render); } if (seq->type == SEQ_TYPE_SCENE) { /* FIXME: recurs downwards, @@ -3626,8 +3704,8 @@ int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) SWAP(float, seq_a->blend_opacity, seq_b->blend_opacity); - SWAP(void *, seq_a->prev, seq_b->prev); - SWAP(void *, seq_a->next, seq_b->next); + SWAP(Sequence *, seq_a->prev, seq_b->prev); + SWAP(Sequence *, seq_a->next, seq_b->next); SWAP(int, seq_a->start, seq_b->start); SWAP(int, seq_a->startofs, seq_b->startofs); SWAP(int, seq_a->endofs, seq_b->endofs); @@ -3805,7 +3883,7 @@ static void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) { if (seq) { BLI_strncpy(seq->name + 2, seq_load->name, sizeof(seq->name) - 2); - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); if (seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) { seq_load->start_frame += (seq->enddisp - seq->startdisp); @@ -3892,10 +3970,10 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad sound = sound_new_file(bmain, seq_load->path); /* handles relative paths */ if (sound == NULL || sound->playback_handle == NULL) { - /* +#if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - */ +#endif return NULL; } @@ -3904,10 +3982,10 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad if (info.specs.channels == AUD_CHANNELS_INVALID) { sound_delete(bmain, sound); - /* +#if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - */ +#endif return NULL; } @@ -3916,7 +3994,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad seq->type = SEQ_TYPE_SOUND_RAM; seq->sound = sound; BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2); - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* basic defaults */ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); @@ -3963,7 +4041,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad BLI_strncpy(path, seq_load->path, sizeof(path)); BLI_path_abs(path, G.main->name); - an = openanim(path, IB_rect, 0); + /* OCIO_TODO: support configurable input space for strips */ + an = openanim(path, IB_rect, 0, NULL); if (an == NULL) return NULL; @@ -3975,7 +4054,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad seq->anim = an; seq->anim_preseek = IMB_anim_get_preseek(an); BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2); - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* basic defaults */ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); @@ -4032,10 +4111,6 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seqn->strip->proxy->anim = NULL; } - if (seq->strip->color_balance) { - seqn->strip->color_balance = MEM_dupallocN(seq->strip->color_balance); - } - if (seqn->modifiers.first) { seqn->modifiers.first = seqn->modifiers.last = NULL; @@ -4091,7 +4166,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup } if (dupe_flag & SEQ_DUPE_UNIQUE_NAME) - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seqn); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqn); if (dupe_flag & SEQ_DUPE_ANIM) BKE_sequencer_dupe_animdata(scene, seq->name + 2, seqn->name + 2); @@ -4146,7 +4221,7 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase * /* called on draw, needs to be fast, * we could cache and use a flag if we want to make checks for file paths resolving for eg. */ -int BKE_seqence_is_valid_check(Sequence *seq) +int BKE_sequence_is_valid_check(Sequence *seq) { switch (seq->type) { case SEQ_TYPE_MASK: diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index f9399946570..9a8bcaabe0c 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -313,7 +313,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) auxMesh = object_get_derived_final(calc->smd->auxTarget); if (!auxMesh) return; - space_transform_setup(&local2aux, calc->ob, calc->smd->auxTarget); + SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); } //After sucessufuly build the trees, start projection vertexs @@ -500,7 +500,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); + 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 f194c5e9d05..1909e65d0ab 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -80,10 +80,10 @@ /* UNUSED so far, may be enabled later */ /* #define USE_SMOKE_COLLISION_DM */ -#ifdef WITH_SMOKE - #include "smoke_API.h" +#ifdef WITH_SMOKE + #ifdef _WIN32 #include <time.h> #include <stdio.h> @@ -148,7 +148,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) /* Stubs to use when smoke is disabled */ struct WTURBULENCE *smoke_turbulence_init(int *UNUSED(res), int UNUSED(amplify), int UNUSED(noisetype)) { return NULL; } -struct FLUID_3D *smoke_init(int *UNUSED(res), float *UNUSED(p0)) { return NULL; } +// struct FLUID_3D *smoke_init(int *UNUSED(res), float *UNUSED(p0)) { return NULL; } void smoke_free(struct FLUID_3D *UNUSED(fluid)) {} float *smoke_get_density(struct FLUID_3D *UNUSED(fluid)) { return NULL; } void smoke_turbulence_free(struct WTURBULENCE *UNUSED(wt)) {} diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 008dc332710..f47c931e309 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -143,13 +143,15 @@ typedef struct SB_thread_context { } SB_thread_context; #define NLF_BUILD 1 -#define NLF_SOLVE 2 +#if 0 +# define NLF_SOLVE 2 +#endif #define MID_PRESERVE 1 #define SOFTGOALSNAP 0.999f /* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp - * removes *unnecessary* stiffnes from ODE system + * removes *unnecessary* stiffness from ODE system */ #define HEUNWARNLIMIT 1 /* 500 would be fine i think for detecting severe *stiff* stuff */ @@ -2291,7 +2293,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo /* done goal stuff */ /* gravitation */ - if (sb && scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { float gravity[3]; copy_v3_v3(gravity, scene->physics_settings.gravity); mul_v3_fl(gravity, sb_grav_force_scale(ob)*_final_mass(ob, bp)*sb->effector_weights->global_gravity); /* individual mass of node here */ @@ -3923,7 +3925,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) sst=PIL_check_seconds_timer(); /* Integration back in time is possible in theory, but pretty useless here. - * So we refuse to do so. Since we do not know anything about 'outside' canges + * So we refuse to do so. Since we do not know anything about 'outside' changes * especially colliders we refuse to go more than 10 frames. */ if (dtime < 0 || dtime > 10.5f) return; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 14360297ec0..385d1bb6fc5 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -50,7 +50,6 @@ # include "AUD_C-API.h" #endif -#include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_sound.h" @@ -774,37 +773,36 @@ void sound_force_device(int UNUSED(device)) {} void sound_init_once(void) {} void sound_init(struct Main *UNUSED(bmain)) {} void sound_exit(void) {} -void sound_cache(struct bSound* UNUSED(sound)) { } -void sound_delete_cache(struct bSound* UNUSED(sound)) {} -void sound_load(struct Main *UNUSED(bmain), struct bSound* UNUSED(sound)) {} +void sound_cache(struct bSound *UNUSED(sound)) { } +void sound_delete_cache(struct bSound *UNUSED(sound)) {} +void sound_load(struct Main *UNUSED(bmain), struct bSound *UNUSED(sound)) {} void sound_create_scene(struct Scene *UNUSED(scene)) {} void sound_destroy_scene(struct Scene *UNUSED(scene)) {} void sound_mute_scene(struct Scene *UNUSED(scene), int UNUSED(muted)) {} -void* sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } -void* sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence)) { return NULL; } -void* sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } -void* sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence* UNUSED(sequence)) { return NULL; } -void sound_remove_scene_sound(struct Scene *UNUSED(scene), void* UNUSED(handle)) {} -void sound_mute_scene_sound(void* UNUSED(handle), char UNUSED(mute)) {} -void sound_move_scene_sound(struct Scene *UNUSED(scene), void* UNUSED(handle), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) {} +void *sound_scene_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } +void *sound_scene_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; } +void *sound_add_scene_sound(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) { return NULL; } +void *sound_add_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) { return NULL; } +void sound_remove_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle)) {} +void sound_mute_scene_sound(void *UNUSED(handle), char UNUSED(mute)) {} +void sound_move_scene_sound(struct Scene *UNUSED(scene), void *UNUSED(handle), int UNUSED(startframe), int UNUSED(endframe), int UNUSED(frameskip)) {} void sound_move_scene_sound_defaults(struct Scene *UNUSED(scene), struct Sequence *UNUSED(sequence)) {} void sound_play_scene(struct Scene *UNUSED(scene)) {} void sound_stop_scene(struct Scene *UNUSED(scene)) {} void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {} float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; } int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; } -int sound_read_sound_buffer(struct bSound* UNUSED(sound), float* UNUSED(buffer), int UNUSED(length), float UNUSED(start), float UNUSED(end)) { return 0; } -void sound_read_waveform(struct bSound* sound) { (void)sound; } +void sound_read_waveform(struct bSound *sound) { (void)sound; } void sound_init_main(struct Main *bmain) { (void)bmain; } void sound_set_cfra(int cfra) { (void)cfra; } -void sound_update_sequencer(struct Main* main, struct bSound* sound) { (void)main; (void)sound; } -void sound_update_scene(struct Scene* scene) { (void)scene; } -void sound_update_scene_sound(void* handle, struct bSound* sound) { (void)handle; (void)sound; } +void sound_update_sequencer(struct Main *main, struct bSound *sound) { (void)main; (void)sound; } +void sound_update_scene(struct Scene *scene) { (void)scene; } +void sound_update_scene_sound(void *handle, struct bSound *sound) { (void)handle; (void)sound; } void sound_update_scene_listener(struct Scene *scene) { (void)scene; } void sound_update_fps(struct Scene *scene) { (void)scene; } -void sound_set_scene_sound_volume(void* handle, float volume, char animated) { (void)handle; (void)volume; (void)animated; } -void sound_set_scene_sound_pan(void* handle, float pan, char animated) { (void)handle; (void)pan; (void)animated; } +void sound_set_scene_sound_volume(void *handle, float volume, char animated) { (void)handle; (void)volume; (void)animated; } +void sound_set_scene_sound_pan(void *handle, float pan, char animated) { (void)handle; (void)pan; (void)animated; } void sound_set_scene_volume(struct Scene *scene, float volume) { (void)scene; (void)volume; } -void sound_set_scene_sound_pitch(void* handle, float pitch, char animated) { (void)handle; (void)pitch; (void)animated; } -float sound_get_length(struct bSound* sound) { (void)sound; return 0; } +void sound_set_scene_sound_pitch(void *handle, float pitch, char animated) { (void)handle; (void)pitch; (void)animated; } +float sound_get_length(struct bSound *sound) { (void)sound; return 0; } #endif // WITH_AUDASPACE diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 99486f47629..e1a7bb792f8 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -513,10 +513,14 @@ static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen) w2 = (1.0f - fx + fac2 * fx * -fac) * (fy); w4 = (fx) * (1.0f - fy + -fac2 * fy * fac); - fac2 = 1.0f - (w1 + w2 + w4); - fac2 = fac2 / (float)(faceLen - 3); - for (j = 0; j < faceLen; j++) - w[j] = fac2; + /* these values aren't used for tri's and cause divide by zero */ + if (faceLen > 3) { + fac2 = 1.0f - (w1 + w2 + w4); + fac2 = fac2 / (float)(faceLen - 3); + for (j = 0; j < faceLen; j++) { + w[j] = fac2; + } + } w[i] = w1; w[(i - 1 + faceLen) % faceLen] = w2; @@ -1468,9 +1472,9 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) } static void ccgDM_foreachMappedVert( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), - void *userData) + DerivedMesh *dm, + void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), + void *userData) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGVertIterator *vi; @@ -1490,9 +1494,9 @@ static void ccgDM_foreachMappedVert( } static void ccgDM_foreachMappedEdge( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), - void *userData) + DerivedMesh *dm, + void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), + void *userData) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; @@ -2588,9 +2592,9 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, } static void ccgDM_foreachMappedFaceCenter( - DerivedMesh *dm, - void (*func)(void *userData, int index, const float co[3], const float no[3]), - void *userData) + DerivedMesh *dm, + void (*func)(void *userData, int index, const float co[3], const float no[3]), + void *userData) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 7de5f97588b..05d0705107d 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -48,6 +48,7 @@ #include "DNA_constraint_types.h" #include "DNA_controller_types.h" +#include "DNA_actuator_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -528,6 +529,7 @@ void BKE_text_unlink(Main *bmain, Text *text) SpaceLink *sl; Object *ob; bController *cont; + bActuator *act; bConstraint *con; short update; @@ -541,6 +543,15 @@ void BKE_text_unlink(Main *bmain, Text *text) if (pc->text == text) pc->text = NULL; } } + /* game actuators */ + for (act = ob->actuators.first; act; act = act->next) { + if (act->type == ACT_2DFILTER) { + bTwoDFilterActuator *tfa; + + tfa = act->data; + if (tfa->text == text) tfa->text = NULL; + } + } /* pyconstraints */ update = 0; @@ -1684,7 +1695,8 @@ void txt_print_undo(Text *text) printf("%c%c%c", text->undo_buf[i], text->undo_buf[i + 1], text->undo_buf[i + 2]); i += 3; break; - case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4: { + case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4: + { unsigned int uc; char c[BLI_UTF8_MAX + 1]; size_t c_len; @@ -1918,6 +1930,7 @@ static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, s break; case 4: /* 32-bit unicode symbol */ unicode = txt_undo_read_uint32(undo_buf, undo_pos); + break; default: /* should never happen */ BLI_assert(0); @@ -1969,6 +1982,7 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s break; case 4: /* 32-bit unicode symbol */ unicode = txt_undo_read_uint32(undo_buf, undo_pos); + break; default: /* should never happen */ BLI_assert(0); @@ -3030,30 +3044,6 @@ void txt_uncomment(Text *text) } } - -void txt_move_lines_up(struct Text *text) -{ - TextLine *prev_line; - - if (!text || !text->curl || !text->sell) return; - - txt_order_cursors(text); - - prev_line = text->curl->prev; - - if (!prev_line) return; - - BLI_remlink(&text->lines, prev_line); - BLI_insertlinkafter(&text->lines, text->sell, prev_line); - - txt_make_dirty(text); - txt_clean_text(text); - - if (!undoing) { - txt_undo_add_op(text, UNDO_MOVE_LINES_UP); - } -} - void txt_move_lines(struct Text *text, const int direction) { TextLine *line_other; @@ -3093,7 +3083,6 @@ int 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) return 0; 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 2f54fe6cebd..9dd83181521 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -56,7 +56,6 @@ #include "IMB_imbuf.h" -#include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_ocean.h" @@ -339,7 +338,7 @@ void colorband_table_RGBA(ColorBand *coba, float **array, int *size) do_colorband(coba, (float)a / (float)CM_TABLE, &(*array)[a * 4]); } -int vergcband(const void *a1, const void *a2) +static int vergcband(const void *a1, const void *a2) { const CBData *x1 = a1, *x2 = a2; @@ -1074,19 +1073,21 @@ void set_current_material_texture(Material *ma, Tex *newtex) { Tex *tex = NULL; bNode *node; - - if (ma && ma->use_nodes && ma->nodetree) { - node = nodeGetActiveID(ma->nodetree, ID_TE); - if (node) { - tex = (Tex *)node->id; - id_us_min(&tex->id); + if ((ma->use_nodes && ma->nodetree) && + (node = nodeGetActiveID(ma->nodetree, ID_TE))) + { + tex = (Tex *)node->id; + id_us_min(&tex->id); + if (newtex) { node->id = &newtex->id; id_us_plus(&newtex->id); - ma = NULL; + } + else { + node->id = NULL; } } - if (ma) { + else { int act = (int)ma->texact; tex = (ma->mtex[act]) ? ma->mtex[act]->tex : NULL; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 78e7dab045f..c9d7ec3964f 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -335,7 +335,7 @@ static void search_pixel_to_marker_unified(int frame_width, int frame_height, } /* Each marker has 5 coordinates associated with it that get warped with - * tracking: the four corners ("pattern_corners"), and the cernter ("pos"). + * tracking: the four corners ("pattern_corners"), and the center ("pos"). * This function puts those 5 points into the appropriate frame for tracking * (the "search" coordinate frame). */ @@ -411,6 +411,8 @@ void BKE_tracking_clipboard_free(void) track = next_track; } + + tracking_clipboard.tracks.first = tracking_clipboard.tracks.last = NULL; } void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object) @@ -453,7 +455,7 @@ void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingO /*********************** Tracks *************************/ -static void tracking_marker_insert_disabled(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, +static void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker, int before, int overwrite) { MovieTrackingMarker marker_new; @@ -854,7 +856,7 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height } /* TODO: add an option to control whether AA is enabled or not */ - PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE); + PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height); MEM_freeN(mask_points); } @@ -1041,14 +1043,6 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) } } } - else if (event == CLAMP_SEARCH_DIM) { - float dim[2]; - sub_v2_v2v2(dim, pat_max, pat_min); - for (a = 0; a < 2; a++) { - marker->search_min[a] = pat_min[a]; - marker->search_max[a] = pat_max[a]; - } - } } MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr) @@ -1625,7 +1619,6 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea float *mask = NULL; pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); - pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; if (!search_ibuf->rect_float) { IMB_float_from_rect(search_ibuf); @@ -1720,7 +1713,6 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); - searchibuf->profile = ibuf->profile; IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); @@ -2029,7 +2021,7 @@ static void track_context_free(void *customdata) { TrackContext *track_context = (TrackContext *)customdata; -#if WITH_LIBMV +#ifdef WITH_LIBMV if (track_context->search_area) MEM_freeN(track_context->search_area); @@ -2223,8 +2215,8 @@ static ImBuf *tracking_context_get_frame_ibuf(MovieTrackingContext *context, int return ibuf; } -MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingContext *context, MovieTrackingTrack *track, - MovieTrackingMarker *marker) +static MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingContext *context, MovieTrackingTrack *track, + MovieTrackingMarker *marker) { int a = marker - track->markers; MovieTrackingMarker *marker_keyed = marker; @@ -2289,9 +2281,9 @@ static ImBuf *tracking_context_get_reference_ibuf(MovieTrackingContext *context, return ibuf; } -static void track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context, - MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra, - int frame_width, int frame_height) +static int track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context, + MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra, + int frame_width, int frame_height) { MovieTrackingMarker *marker_keyed = NULL; ImBuf *reference_ibuf = NULL; @@ -2299,6 +2291,10 @@ static void track_context_update_reference(MovieTrackingContext *context, TrackC /* calculate patch for keyframed position */ reference_ibuf = tracking_context_get_reference_ibuf(context, track, marker, curfra, &marker_keyed); + + if (!reference_ibuf) + return FALSE; + track_context->marker = *marker_keyed; if (track_context->search_area) { @@ -2317,6 +2313,8 @@ static void track_context_update_reference(MovieTrackingContext *context, TrackC } IMB_freeImBuf(reference_ibuf); + + return TRUE; } static void tracking_configure_tracker(TrackContext *track_context, MovieTrackingTrack *track, @@ -2402,7 +2400,7 @@ static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrack * if so -- create disabled marker before currently tracking "segment" */ - tracking_marker_insert_disabled(track, &new_marker, !context->backwards, FALSE); + tracking_marker_insert_disabled(track, old_marker, !context->backwards, FALSE); } /* insert currently tracked marker */ @@ -2481,8 +2479,12 @@ int BKE_tracking_context_step(MovieTrackingContext *context) float *patch_new; if (need_readjust) { - track_context_update_reference(context, track_context, track, marker, - curfra, frame_width, frame_height); + if (track_context_update_reference(context, track_context, track, marker, + curfra, frame_width, frame_height) == FALSE) + { + /* happens when reference frame fails to be loaded */ + continue; + } } /* for now track to the same search area dimension as marker has got for current frame @@ -2776,7 +2778,7 @@ static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, L int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size) { -#if WITH_LIBMV +#ifdef WITH_LIBMV ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) { @@ -3315,7 +3317,6 @@ static ImBuf *stabilization_allocate_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int } else { cacheibuf = IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->planes, flags); - cacheibuf->profile = srcibuf->profile; } return cacheibuf; diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index da5e7ff3db7..46836b1f8d1 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -350,7 +350,7 @@ static int unit_as_string(char *str, int len_max, double value, int prec, bUnitC /* Add unit prefix and strip zeros */ /* replace trailing zero's with spaces - * so the number is less complicated but allignment in a button wont + * so the number is less complicated but alignment in a button wont * jump about while dragging */ i = len - 1; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index dd71e43182e..434bfe19c1f 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -51,14 +51,14 @@ #include "BKE_node.h" #include "BKE_world.h" -void BKE_world_free(World *wrld) +void BKE_world_free_ex(World *wrld, int do_id_user) { MTex *mtex; int a; for (a = 0; a < MAX_MTEX; a++) { mtex = wrld->mtex[a]; - if (mtex && mtex->tex) mtex->tex->id.us--; + if (do_id_user && mtex && mtex->tex) mtex->tex->id.us--; if (mtex) MEM_freeN(mtex); } BKE_previewimg_free(&wrld->preview); @@ -67,7 +67,7 @@ void BKE_world_free(World *wrld) /* is no lib link block, but world extension */ if (wrld->nodetree) { - ntreeFreeTree(wrld->nodetree); + ntreeFreeTree_ex(wrld->nodetree, do_id_user); MEM_freeN(wrld->nodetree); } @@ -75,6 +75,10 @@ void BKE_world_free(World *wrld) wrld->id.icon_id = 0; } +void BKE_world_free(World *wrld) +{ + BKE_world_free_ex(wrld, TRUE); +} World *add_world(const char *name) { diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index f22fd74baf4..ff1fdebb728 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -69,8 +69,6 @@ #include "ffmpeg_compat.h" -extern void do_init_ffmpeg(void); - static int ffmpeg_type = 0; static int ffmpeg_codec = CODEC_ID_MPEG4; static int ffmpeg_audio_codec = CODEC_ID_NONE; @@ -101,6 +99,8 @@ static AUD_Device *audio_mixdown_device = 0; #define FFMPEG_AUTOSPLIT_SIZE 2000000000 +#define PRINT if (G.debug & G_DEBUG_FFMPEG) printf + /* Delete a picture buffer */ static void delete_picture(AVFrame *f) @@ -125,9 +125,7 @@ static int write_audio_frame(void) AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples); audio_time += (double) audio_input_samples / (double) c->sample_rate; - pkt.size = avcodec_encode_audio(c, audio_output_buffer, - audio_outbuf_size, - (short *)audio_input_buffer); + pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer); if (pkt.size < 0) { // XXX error("Error writing audio packet"); @@ -137,9 +135,8 @@ static int write_audio_frame(void) pkt.data = audio_output_buffer; if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) { - pkt.pts = av_rescale_q(c->coded_frame->pts, - c->time_base, audio_stream->time_base); - fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts); + pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base); + PRINT("Audio Frame PTS: %d\n", (int) pkt.pts); } pkt.stream_index = audio_stream->index; @@ -180,59 +177,71 @@ static AVFrame *alloc_picture(int pix_fmt, int width, int height) static const char **get_file_extensions(int format) { switch (format) { - case FFMPEG_DV: { + case FFMPEG_DV: + { static const char *rv[] = { ".dv", NULL }; return rv; } - case FFMPEG_MPEG1: { + case FFMPEG_MPEG1: + { static const char *rv[] = { ".mpg", ".mpeg", NULL }; return rv; } - case FFMPEG_MPEG2: { - static const char *rv[] = { ".dvd", ".vob", ".mpg", ".mpeg", - NULL }; + case FFMPEG_MPEG2: + { + static const char *rv[] = { ".dvd", ".vob", ".mpg", ".mpeg", NULL }; return rv; } - case FFMPEG_MPEG4: { + case FFMPEG_MPEG4: + { static const char *rv[] = { ".mp4", ".mpg", ".mpeg", NULL }; return rv; } - case FFMPEG_AVI: { + case FFMPEG_AVI: + { static const char *rv[] = { ".avi", NULL }; return rv; } - case FFMPEG_MOV: { + case FFMPEG_MOV: + { static const char *rv[] = { ".mov", NULL }; return rv; } - case FFMPEG_H264: { + case FFMPEG_H264: + { /* FIXME: avi for now... */ static const char *rv[] = { ".avi", NULL }; return rv; } - case FFMPEG_XVID: { + case FFMPEG_XVID: + { /* FIXME: avi for now... */ static const char *rv[] = { ".avi", NULL }; return rv; } - case FFMPEG_FLV: { + case FFMPEG_FLV: + { static const char *rv[] = { ".flv", NULL }; return rv; } - case FFMPEG_MKV: { + case FFMPEG_MKV: + { static const char *rv[] = { ".mkv", NULL }; return rv; } - case FFMPEG_OGG: { + case FFMPEG_OGG: + { static const char *rv[] = { ".ogg", ".ogv", NULL }; return rv; } - case FFMPEG_MP3: { + case FFMPEG_MP3: + { static const char *rv[] = { ".mp3", NULL }; return rv; } - case FFMPEG_WAV: { + case FFMPEG_WAV: + { static const char *rv[] = { ".wav", NULL }; return rv; } @@ -254,21 +263,18 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0); } - outsize = avcodec_encode_video(c, video_buffer, video_buffersize, - frame); + outsize = avcodec_encode_video(c, video_buffer, video_buffersize, frame); if (outsize > 0) { AVPacket packet; av_init_packet(&packet); if (c->coded_frame->pts != AV_NOPTS_VALUE) { - packet.pts = av_rescale_q(c->coded_frame->pts, - c->time_base, - video_stream->time_base); - fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); + packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base); + PRINT("Video Frame PTS: %d\n", (int)packet.pts); } else { - fprintf(stderr, "Video Frame PTS: not set\n"); + PRINT("Video Frame PTS: not set\n"); } if (c->coded_frame->key_frame) packet.flags |= AV_PKT_FLAG_KEY; @@ -364,7 +370,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) char *param; const AVOption *rv = NULL; - fprintf(stderr, "FFMPEG expert option: %s: ", prop->name); + PRINT("FFMPEG expert option: %s: ", prop->name); BLI_strncpy(name, prop->name, sizeof(name)); @@ -376,15 +382,15 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) switch (prop->type) { case IDP_STRING: - fprintf(stderr, "%s.\n", IDP_String(prop)); + PRINT("%s.\n", IDP_String(prop)); av_set_string3(c, prop->name, IDP_String(prop), 1, &rv); break; case IDP_FLOAT: - fprintf(stderr, "%g.\n", IDP_Float(prop)); + PRINT("%g.\n", IDP_Float(prop)); rv = av_set_double(c, prop->name, IDP_Float(prop)); break; case IDP_INT: - fprintf(stderr, "%d.\n", IDP_Int(prop)); + PRINT("%d.\n", IDP_Int(prop)); if (param) { if (IDP_Int(prop)) { @@ -401,8 +407,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) } if (!rv) { - fprintf(stderr, "ffmpeg-option not supported: %s! Skipping.\n", - prop->name); + PRINT("ffmpeg-option not supported: %s! Skipping.\n", prop->name); } } @@ -446,11 +451,14 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char /* prepare a video stream for the output file */ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of, - int rectx, int recty) + int rectx, int recty, char *error, int error_size) { AVStream *st; AVCodecContext *c; AVCodec *codec; + + error[0] = '\0'; + st = av_new_stream(of, 0); if (!st) return NULL; @@ -460,7 +468,6 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->codec_id = codec_id; c->codec_type = AVMEDIA_TYPE_VIDEO; - /* Get some values from the current render settings */ c->width = rectx; @@ -492,7 +499,8 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->me_method = ME_EPZS; codec = avcodec_find_encoder(c->codec_id); - if (!codec) return NULL; + if (!codec) + return NULL; /* Be sure to use the correct pixel format(e.g. RGB, YUV) */ @@ -547,27 +555,25 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex // || !strcmp(of->oformat->name, "3gp") ) { - fprintf(stderr, "Using global header\n"); + PRINT("Using global header\n"); c->flags |= CODEC_FLAG_GLOBAL_HEADER; } /* Determine whether we are encoding interlaced material or not */ if (rd->mode & R_FIELDS) { - fprintf(stderr, "Encoding interlaced video\n"); + PRINT("Encoding interlaced video\n"); c->flags |= CODEC_FLAG_INTERLACED_DCT; c->flags |= CODEC_FLAG_INTERLACED_ME; } /* xasp & yasp got float lately... */ - st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q( - ((double) rd->xasp / (double) rd->yasp), 255); + st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double) rd->xasp / (double) rd->yasp), 255); set_ffmpeg_properties(rd, c, "video"); if (avcodec_open(c, codec) < 0) { - // - //XXX error("Couldn't initialize codec"); + BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; } @@ -584,16 +590,11 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex else video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height); - video_buffer = (uint8_t *)MEM_mallocN(video_buffersize * sizeof(uint8_t), - "FFMPEG video buffer"); + video_buffer = (uint8_t *)MEM_mallocN(video_buffersize * sizeof(uint8_t), "FFMPEG video buffer"); current_frame = alloc_picture(c->pix_fmt, c->width, c->height); - img_convert_ctx = sws_getContext(c->width, c->height, - PIX_FMT_BGR32, - c->width, c->height, - c->pix_fmt, - SWS_BICUBIC, + img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL); return st; } @@ -645,11 +646,9 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4; } - audio_output_buffer = (uint8_t *)av_malloc( - audio_outbuf_size); + audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); - audio_input_buffer = (uint8_t *)av_malloc( - audio_input_samples * c->channels * sizeof(int16_t)); + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); audio_time = 0.0f; @@ -672,7 +671,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report AVFormatContext *of; AVOutputFormat *fmt; AVDictionary *opts = NULL; - char name[256]; + char name[256], error[1024]; const char **exts; ffmpeg_type = rd->ffcodecdata.type; @@ -681,14 +680,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate; ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate; ffmpeg_gop_size = rd->ffcodecdata.gop_size; - ffmpeg_autosplit = rd->ffcodecdata.flags - & FFMPEG_AUTOSPLIT_OUTPUT; + ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT; - do_init_ffmpeg(); - /* Determine the correct filename */ BKE_ffmpeg_filepath_get(name, rd); - fprintf(stderr, "Starting output to %s(ffmpeg)...\n" + PRINT("Starting output to %s(ffmpeg)...\n" " Using type=%d, codec=%d, audio_codec=%d,\n" " video_bitrate=%d, audio_bitrate=%d,\n" " gop_size=%d, autosplit=%d\n" @@ -793,10 +789,14 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } if (fmt->video_codec != CODEC_ID_NONE) { - video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty); - printf("alloc video stream %p\n", video_stream); + video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty, error, sizeof(error)); + PRINT("alloc video stream %p\n", video_stream); if (!video_stream) { - BKE_report(reports, RPT_ERROR, "Error initializing video stream."); + if (error[0]) + BKE_report(reports, RPT_ERROR, error); + else + BKE_report(reports, RPT_ERROR, "Error initializing video stream."); + av_dict_free(&opts); return 0; } @@ -839,7 +839,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report * inter-frames (H.264 B-frames, for example), it can output the frames * in a different order from the one it was given. * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write - * them in the order 1, 4, 2, 3 - first the two frames used for predition, + * them in the order 1, 4, 2, 3 - first the two frames used for prediction, * and then the bidirectionally-predicted frames. What this means in practice * is that the encoder may not immediately produce one output frame for each * input frame. These delayed frames must be flushed before we close the @@ -847,7 +847,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report * parameter. * </p> */ -void flush_ffmpeg(void) +static void flush_ffmpeg(void) { int outsize = 0; int ret = 0; @@ -867,13 +867,11 @@ void flush_ffmpeg(void) break; } if (c->coded_frame->pts != AV_NOPTS_VALUE) { - packet.pts = av_rescale_q(c->coded_frame->pts, - c->time_base, - video_stream->time_base); - fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); + packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base); + PRINT("Video Frame PTS: %d\n", (int) packet.pts); } else { - fprintf(stderr, "Video Frame PTS: not set\n"); + PRINT("Video Frame PTS: not set\n"); } if (c->coded_frame->key_frame) { packet.flags |= AV_PKT_FLAG_KEY; @@ -916,9 +914,7 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd) } while (*fe) { - if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), - *fe) == 0) - { + if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), *fe) == 0) { break; } fe++; @@ -962,6 +958,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, } void BKE_ffmpeg_end(void); +static void end_ffmpeg_impl(int is_autosplit); #ifdef WITH_AUDASPACE static void write_audio_frames(double to_pts) @@ -983,9 +980,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i AVFrame *avframe; int success = 1; - fprintf(stderr, "Writing frame %i, " - "render width=%d, render height=%d\n", frame, - rectx, recty); + PRINT("Writing frame %i, render width=%d, render height=%d\n", frame, rectx, recty); // why is this done before writing the video frame and again at end_ffmpeg? // write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base)); @@ -996,7 +991,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i if (ffmpeg_autosplit) { if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) { - BKE_ffmpeg_end(); + end_ffmpeg_impl(TRUE); ffmpeg_autosplit_count++; success &= start_ffmpeg_impl(rd, rectx, recty, reports); } @@ -1009,11 +1004,11 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i return success; } -void BKE_ffmpeg_end(void) +static void end_ffmpeg_impl(int is_autosplit) { unsigned int i; - fprintf(stderr, "Closing ffmpeg...\n"); + PRINT("Closing ffmpeg...\n"); #if 0 if (audio_stream) { /* SEE UPPER */ @@ -1022,14 +1017,16 @@ void BKE_ffmpeg_end(void) #endif #ifdef WITH_AUDASPACE - if (audio_mixdown_device) { - AUD_closeReadDevice(audio_mixdown_device); - audio_mixdown_device = 0; + if (is_autosplit == FALSE) { + if (audio_mixdown_device) { + AUD_closeReadDevice(audio_mixdown_device); + audio_mixdown_device = 0; + } } #endif if (video_stream && video_stream->codec) { - fprintf(stderr, "Flushing delayed frames...\n"); + PRINT("Flushing delayed frames...\n"); flush_ffmpeg(); } @@ -1041,7 +1038,7 @@ void BKE_ffmpeg_end(void) if (video_stream && video_stream->codec) { avcodec_close(video_stream->codec); - printf("zero video stream %p\n", video_stream); + PRINT("zero video stream %p\n", video_stream); video_stream = 0; } @@ -1087,6 +1084,11 @@ void BKE_ffmpeg_end(void) } } +void BKE_ffmpeg_end(void) +{ + end_ffmpeg_impl(FALSE); +} + /* properties */ void BKE_ffmpeg_property_del(RenderData *rd, void *type, void *prop_) @@ -1142,8 +1144,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in BLI_strncpy(name, o->name, sizeof(name)); } - fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n", - type, parent_index, opt_index, name); + PRINT("ffmpeg_property_add: %s %d %d %s\n", type, parent_index, opt_index, name); prop = IDP_GetPropertyFromGroup(group, name); if (prop) { @@ -1181,8 +1182,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in /* not all versions of ffmpeg include that, so here we go ... */ -static const AVOption *my_av_find_opt(void *v, const char *name, - const char *unit, int mask, int flags) +static const AVOption *my_av_find_opt(void *v, const char *name, const char *unit, int mask, int flags) { AVClass *c = *(AVClass **)v; const AVOption *o = c->option; @@ -1235,14 +1235,11 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char if (param && o->type != FF_OPT_TYPE_CONST && o->unit) { p = my_av_find_opt(&c, param, o->unit, 0, 0); if (p) { - prop = BKE_ffmpeg_property_add(rd, - (char *) type, p - c.av_class->option, - o - c.av_class->option); + prop = BKE_ffmpeg_property_add(rd, (char *) type, p - c.av_class->option, o - c.av_class->option); } } else { - prop = BKE_ffmpeg_property_add(rd, - (char *) type, o - c.av_class->option, 0); + prop = BKE_ffmpeg_property_add(rd, (char *) type, o - c.av_class->option, 0); } @@ -1316,12 +1313,10 @@ static void ffmpeg_set_expert_options(RenderData *rd) if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) BKE_ffmpeg_property_add_string(rd, "video", "cqp:0"); } -#if 0 /* disabled for after release */ else if (codec_id == CODEC_ID_DNXHD) { if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) - ffmpeg_property_add_string(rd, "video", "mbd:rd"); + BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd"); } -#endif } void BKE_ffmpeg_preset_set(RenderData *rd, int preset) |