diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2012-02-02 03:22:55 +0400 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2012-02-02 03:22:55 +0400 |
commit | 28f1fdd39bbb11b1081594e2f41bebef77a31518 (patch) | |
tree | 3475d4f0b15d7ba8e59150fec25adc582ae62afb /source/blender/blenkernel/intern | |
parent | 6b39a476cbe83febfe67daa31be6fade83194c7a (diff) | |
parent | d882f05b824f4111ef5c319c89a2f85b1773c579 (diff) |
svn merge ^/trunk/blender -r43091:43824(HEAD)
Conflicted file manually update:
===============================
readfile.c
Note 1:
=======
The Double Edge Mask is not in tile since it's not a simple convert.
The author of this node is aware of it and should have it working there eventually.
(I'm going to add it in COM_Converter.cpp in a next commit)
Note 2:
=======
In COM_compositor.cpp we are passing only "Compositing" instead of what we have in trunk "Compositing 1 Gamma"
If we decide to go with trunk then we need to incorporate the 43283 and 43287 commits.
Something like:
COM_compositor.cpp:51
- editingtree->stats_draw(editingtree->sdh, (char*)"Compositing");
+ char str[128];
+ BLI_snprintf(str, sizeof(str), "Compositing %d %s", curnode, node->name)
+ editingtree->stats_draw(editingtree->sdh, str);
Diffstat (limited to 'source/blender/blenkernel/intern')
51 files changed, 2359 insertions, 1774 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d0ef517e2ae..27aeeb95903 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -722,24 +722,23 @@ void vDM_ColorBand_store(ColorBand *coba) * note that we could save some memory and allocate RGB only but then we'd need to * re-arrange the colors when copying to the face since MCol has odd ordering, * so leave this as is - campbell */ -static unsigned char *calc_weightpaint_vert_array(Object *ob, int const draw_flag, ColorBand *coba) +static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const draw_flag, ColorBand *coba) { - Mesh *me = ob->data; - unsigned char *wtcol_v = MEM_mallocN (sizeof(unsigned char) * me->totvert * 4, "weightmap_v"); + MDeformVert *dv = DM_get_vert_data_layer(dm, CD_MDEFORMVERT); + int numVerts = dm->getNumVerts(dm); + unsigned char *wtcol_v = MEM_mallocN (sizeof(unsigned char) * numVerts * 4, "weightmap_v"); - if (me->dvert) { + if (dv) { unsigned char *wc = wtcol_v; - MDeformVert *dv= me->dvert; unsigned int i; - /* varisbles for multipaint */ + /* 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); - /* const int unselected = defbase_tot - selected; */ /* UNUSED */ - for (i = me->totvert; i != 0; i--, wc += 4, dv++) { + 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); } @@ -748,34 +747,94 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, int const draw_fla else { int col_i; weightpaint_color((unsigned char *)&col_i, coba, 0.0f); - fill_vn_i((int *)wtcol_v, me->totvert, col_i); + fill_vn_i((int *)wtcol_v, numVerts, col_i); } return wtcol_v; } -static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) +/* return an array of vertex weight colors from given weights, caller must free. + * + * note that we could save some memory and allocate RGB only but then we'd need to + * re-arrange the colors when copying to the face since MCol has odd ordering, + * so leave this as is - campbell */ +static unsigned char *calc_colors_from_weights_array(const int num, float *weights) { - ColorBand *coba= stored_cb; /* warning, not a local var */ + unsigned char *wtcol_v = MEM_mallocN(sizeof(unsigned char) * num * 4, "weightmap_v"); + unsigned char *wc = wtcol_v; + int i; - Mesh *me = ob->data; - unsigned char *wtcol_v = calc_weightpaint_vert_array(ob, draw_flag, coba); - unsigned char *wtcol_f = MEM_mallocN (sizeof(unsigned char) * me->totface*4*4, "weightmap_f"); + for (i = 0; i < num; i++, wc += 4, weights++) + weightpaint_color((unsigned char *) wc, NULL, *weights); - MFace *mf = me->mface; + return wtcol_v; +} + +void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, + float *weights, int num, const int *indices) +{ + ColorBand *coba= stored_cb; /* warning, not a local var */ + + MFace *mf = dm->getFaceArray(dm); + int numFaces = dm->getNumFaces(dm); + int numVerts = dm->getNumVerts(dm); + unsigned char *wtcol_v; + unsigned char *wtcol_f = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); int i; - for (i=0; i<me->totface; i++, mf++) { - unsigned int fidx= mf->v4 ? 3:2; - do { - copy_v4_v4_char((char *)&wtcol_f[(4 * i + fidx) * 4], - (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); - } while (fidx--); - } + /* If no CD_WEIGHT_MCOL existed yet, add a new one! */ + if (!wtcol_f) + wtcol_f = CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numFaces); + + if (wtcol_f) { + unsigned char *wtcol_f_step = wtcol_f; + + /* Weights are given by caller. */ + if (weights) { + float *w = weights; + /* If indices is not NULL, it means we do not have weights for all vertices, + * so we must create them (and set them to zero)... */ + if(indices) { + w = MEM_callocN(sizeof(float)*numVerts, "Temp weight array DM_update_weight_mcol"); + i = num; + while(i--) + w[indices[i]] = weights[i]; + } + + /* Convert float weights to colors. */ + wtcol_v = calc_colors_from_weights_array(numVerts, w); + + if(indices) + MEM_freeN(w); + } - MEM_freeN(wtcol_v); + /* No weights given, take them from active vgroup(s). */ + else + wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba); + + /* Now copy colors in all face verts. */ + for (i = 0; i < numFaces; i++, mf++, wtcol_f_step += (4 * 4)) { +#if 0 + unsigned int fidx= mf->v4 ? 3:2; - CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol_f, dm->numFaceData); +#else /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */ + unsigned int fidx; + if (mf->v4) { + fidx = 3; + } + else { + fidx = 2; + *(int *)(&wtcol_f_step[3 * 4]) = 0; + } +#endif + + do { + copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4], + (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); + } while (fidx--); + } + MEM_freeN(wtcol_v); + } } /* new value for useDeform -1 (hack for the gameengine): @@ -789,7 +848,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos int needMapping, CustomDataMask dataMask, int index, int useCache) { Mesh *me = ob->data; - ModifierData *firstmd, *md; + ModifierData *firstmd, *md, *previewmd = NULL; LinkNode *datamasks, *curr; CustomDataMask mask, nextmask, append_mask = 0; float (*deformedVerts)[3] = NULL; @@ -802,8 +861,17 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos int has_multires = mmd != NULL, multires_applied = 0; int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt; - int draw_flag= ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) | - (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0)); + const int draw_flag= ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) | + (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0)); + /* Generic preview only in object mode! */ + const int do_mod_mcol = (ob->mode == OB_MODE_OBJECT); +#if 0 /* XXX Will re-enable this when we have global mod stack options. */ + const int do_final_wmcol = (scene->toolsettings->weights_preview == WP_WPREVIEW_FINAL) && do_wmcol; +#endif + const int do_final_wmcol = FALSE; + int do_init_wmcol = ((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT) && !do_final_wmcol); + /* XXX Same as above... For now, only weights preview in WPaint mode. */ + const int do_mod_wmcol = do_init_wmcol; if(mmd && !mmd->sculptlvl) has_multires = 0; @@ -828,6 +896,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode); curr = datamasks; + if(do_mod_wmcol || do_mod_mcol) { + /* Find the last active modifier generating a preview, or NULL if none. */ + /* XXX Currently, DPaint modifier just ignores this. + * Needs a stupid hack... + * The whole "modifier preview" thing has to be (re?)designed, anyway! */ + previewmd = modifiers_getLastPreview(scene, md, required_mode); + } + if(deform_r) *deform_r = NULL; *final_r = NULL; @@ -983,8 +1059,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos CDDM_calc_normals(dm); } - if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) - add_weight_mcol_dm(ob, dm, draw_flag); + if(do_init_wmcol) + DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); /* Constructive modifiers need to have an origindex * otherwise they wont have anywhere to copy the data from. @@ -1071,8 +1147,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } /* in case of dynamic paint, make sure preview mask remains for following modifiers */ + /* XXX Temp and hackish solution! */ if (md->type == eModifierType_DynamicPaint) append_mask |= CD_MASK_WEIGHT_MCOL; + /* In case of active preview modifier, make sure preview mask remains for following modifiers. */ + else if ((md == previewmd) && (do_mod_wmcol)) { + DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); + append_mask |= CD_MASK_WEIGHT_MCOL; + } } isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform); @@ -1100,10 +1182,19 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos CDDM_apply_vert_coords(finaldm, deformedVerts); CDDM_calc_normals(finaldm); - if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) - add_weight_mcol_dm(ob, finaldm, draw_flag); +#if 0 /* For later nice mod preview! */ + /* In case we need modified weights in CD_WEIGHT_MCOL, we have to re-compute it. */ + if(do_final_wmcol) + DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); +#endif } else if(dm) { finaldm = dm; + +#if 0 /* For later nice mod preview! */ + /* In case we need modified weights in CD_WEIGHT_MCOL, we have to re-compute it. */ + if(do_final_wmcol) + DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); +#endif } else { finaldm = CDDM_from_mesh(me, ob); @@ -1112,8 +1203,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos CDDM_calc_normals(finaldm); } - if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) - add_weight_mcol_dm(ob, finaldm, draw_flag); + /* In this case, we should never have weight-modifying modifiers in stack... */ + if(do_init_wmcol) + DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); } /* add an orco layer if needed */ @@ -2299,3 +2391,79 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm) #endif /* WITH_GAMEENGINE */ /* --- NAVMESH (end) --- */ + + +/* derivedmesh info printing function, + * to help track down differences DM output */ + +#ifndef NDEBUG +#include "BLI_dynstr.h" + +static void dm_debug_info_layers(DynStr *dynstr, DerivedMesh *dm, void *(*getElemDataArray)(DerivedMesh *, int)) +{ + int type; + + for (type = 0; type < CD_NUMTYPES; type++) { + /* note: doesnt account for multiple layers */ + void *pt = getElemDataArray(dm, type); + if (pt) { + const char *name = CustomData_layertype_name(type); + const int size = CustomData_sizeof(type); + const char *structname; + int structnum; + CustomData_file_write_info(type, &structname, &structnum); + BLI_dynstr_appendf(dynstr, + " dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n", + name, structname, type, (void *)pt, size, (int)(MEM_allocN_len(pt) / size)); + } + } +} + +char *DM_debug_info(DerivedMesh *dm) +{ + DynStr *dynstr= BLI_dynstr_new(); + char *ret; + const char *tstr; + + BLI_dynstr_appendf(dynstr, "{\n"); + BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)dm); + switch (dm->type) { + case DM_TYPE_CDDM: tstr = "DM_TYPE_CDDM"; break; + case DM_TYPE_EDITMESH: tstr = "DM_TYPE_EDITMESH"; break; + case DM_TYPE_CCGDM: tstr = "DM_TYPE_CCGDM"; break; + default: tstr = "UNKNOWN"; break; + } + BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr); + BLI_dynstr_appendf(dynstr, " 'numVertData': %d,\n", dm->numVertData); + BLI_dynstr_appendf(dynstr, " 'numEdgeData': %d,\n", dm->numEdgeData); + BLI_dynstr_appendf(dynstr, " 'numFaceData': %d,\n", dm->numFaceData); + BLI_dynstr_appendf(dynstr, " 'deformedOnly': %d,\n", dm->deformedOnly); + + BLI_dynstr_appendf(dynstr, " 'vertexLayers': (\n"); + dm_debug_info_layers(dynstr, dm, dm->getVertDataArray); + BLI_dynstr_appendf(dynstr, " ),\n"); + + BLI_dynstr_appendf(dynstr, " 'edgeLayers': (\n"); + dm_debug_info_layers(dynstr, dm, dm->getEdgeDataArray); + BLI_dynstr_appendf(dynstr, " ),\n"); + + BLI_dynstr_appendf(dynstr, " 'faceLayers': (\n"); + dm_debug_info_layers(dynstr, dm, dm->getFaceDataArray); + BLI_dynstr_appendf(dynstr, " ),\n"); + + BLI_dynstr_appendf(dynstr, "}\n"); + + ret = BLI_dynstr_get_cstring(dynstr); + BLI_dynstr_free(dynstr); + return ret; +} + +void DM_debug_print(DerivedMesh *dm) +{ + char *str = DM_debug_info(dm); + printf("%s", str); + fflush(stdout); + MEM_freeN(str); +} + +#endif /* NDEBUG */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 89bad72044e..fabc35361b9 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -585,11 +585,14 @@ int interval_test(int min, int max, int p1, int cycl) } -/* calculate the deformation implied by the curve path at a given parametric position, and returns whether this operation succeeded - * - *vec needs FOUR items! - * - ctime is normalized range <0-1> +/* calculate the deformation implied by the curve path at a given parametric position, + * and returns whether this operation succeeded. + * + * note: ctime is normalized range <0-1> + * + * returns OK: 1/0 */ -int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius, float *weight) /* returns OK */ +int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius, float *weight) { Curve *cu; Nurb *nu; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index ae04b7760c2..02b9330d588 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -590,7 +590,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) /* ************ Armature Deform ******************* */ typedef struct bPoseChanDeform { - Mat4 *b_bone_mats; + Mat4 *b_bone_mats; DualQuat *dual_quat; DualQuat *b_bone_dual_quats; } bPoseChanDeform; @@ -665,7 +665,7 @@ static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float *co, Dua } /* using vec with dist to bone b1 - b2 */ -float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, float rad2, float rdist) +float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist) { float dist=0.0f; float bdelta[3]; @@ -677,18 +677,18 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl sub_v3_v3v3(pdelta, vec, b1); - a = bdelta[0]*pdelta[0] + bdelta[1]*pdelta[1] + bdelta[2]*pdelta[2]; - hsqr = ((pdelta[0]*pdelta[0]) + (pdelta[1]*pdelta[1]) + (pdelta[2]*pdelta[2])); + a = dot_v3v3(bdelta, pdelta); + hsqr = dot_v3v3(pdelta, pdelta); - if (a < 0.0F){ + if (a < 0.0f) { /* If we're past the end of the bone, do a spherical field attenuation thing */ - dist= ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ; + dist = len_squared_v3v3(b1, vec); rad= rad1; } - else if (a > l){ + else if (a > l) { /* If we're past the end of the bone, do a spherical field attenuation thing */ - dist= ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ; - rad= rad2; + dist = len_squared_v3v3(b2, vec); + rad = rad2; } else { dist= (hsqr - (a*a)); @@ -709,7 +709,7 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl if(rdist==0.0f || dist >= l) return 0.0f; else { - a= (float)sqrt(dist)-rad; + a = sqrtf(dist)-rad; return 1.0f-( a*a )/( rdist*rdist ); } } @@ -1123,66 +1123,183 @@ void armature_loc_world_to_pose(Object *ob, float *inloc, float *outloc) copy_v3_v3(outloc, nLocMat[3]); } -/* Convert Pose-Space Matrix to Bone-Space Matrix - * NOTE: this cannot be used to convert to pose-space transforms of the supplied - * pose-channel into its local space (i.e. 'visual'-keyframing) +/* Construct the matrices (rot/scale and loc) to apply the PoseChannels into the armature (object) space. + * I.e. (roughly) the "pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b)" in the + * pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) + * ...function. + * + * This allows to get the transformations of a bone in its object space, *before* constraints (and IK) + * get applied (used by pose evaluation code). + * And reverse: to find pchan transformations needed to place a bone at a given loc/rot/scale + * in object space (used by interactive transform, and snapping code). + * + * Note that, with the HINGE/NO_SCALE/NO_LOCAL_LOCATION options, the location matrix + * will differ from the rotation/scale matrix... + * + * NOTE: This cannot be used to convert to pose-space transforms of the supplied + * pose-channel into its local space (i.e. 'visual'-keyframing). + * (note: I don't understand that, so I keep it :p --mont29). */ -void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outmat[][4]) +void pchan_to_pose_mat(bPoseChannel *pchan, float rotscale_mat[][4], float loc_mat[][4]) { - float pc_trans[4][4], inv_trans[4][4]; - float pc_posemat[4][4], inv_posemat[4][4]; - float pose_mat[4][4]; - - /* paranoia: prevent crashes with no pose-channel supplied */ - if (pchan==NULL) return; - - /* default flag */ - if((pchan->bone->flag & BONE_NO_LOCAL_LOCATION)==0) { - /* get the inverse matrix of the pchan's transforms */ - switch(pchan->rotmode) { - case ROT_MODE_QUAT: - loc_quat_size_to_mat4(pc_trans, pchan->loc, pchan->quat, pchan->size); - break; - case ROT_MODE_AXISANGLE: - loc_axisangle_size_to_mat4(pc_trans, pchan->loc, pchan->rotAxis, pchan->rotAngle, pchan->size); - break; - default: /* euler */ - loc_eul_size_to_mat4(pc_trans, pchan->loc, pchan->eul, pchan->size); + Bone *bone, *parbone; + bPoseChannel *parchan; + + /* set up variables for quicker access below */ + bone= pchan->bone; + parbone= bone->parent; + parchan= pchan->parent; + + if(parchan) { + float offs_bone[4][4]; /* yoffs(b-1) + root(b) + bonemat(b). */ + + /* Bone transform itself. */ + copy_m4_m3(offs_bone, bone->bone_mat); + + /* The bone's root offset (is in the parent's coordinate system). */ + copy_v3_v3(offs_bone[3], bone->head); + + /* Get the length translation of parent (length along y axis). */ + offs_bone[3][1]+= parbone->length; + + /* Compose the rotscale matrix for this bone. */ + if((bone->flag & BONE_HINGE) && (bone->flag & BONE_NO_SCALE)) { + /* Parent rest rotation and scale. */ + mult_m4_m4m4(rotscale_mat, parbone->arm_mat, offs_bone); } + else if(bone->flag & BONE_HINGE) { + /* Parent rest rotation and pose scale. */ + float tmat[4][4], tscale[3]; - copy_m4_m4(pose_mat, pchan->pose_mat); - } - else { - /* local location, this is not default, different calculation - * note: only tested for location with pose bone snapping. - * If this is not useful in other cases the BONE_NO_LOCAL_LOCATION - * case may have to be split into its own function. */ - unit_m4(pc_trans); - copy_v3_v3(pc_trans[3], pchan->loc); + /* Extract the scale of the parent pose matrix. */ + mat4_to_size(tscale, parchan->pose_mat); + size_to_mat4(tmat, tscale); - /* use parents rotation/scale space + own absolute position */ - if(pchan->parent) copy_m4_m4(pose_mat, pchan->parent->pose_mat); - else unit_m4(pose_mat); + /* Applies the parent pose scale to the rest matrix. */ + mult_m4_m4m4(tmat, tmat, parbone->arm_mat); + + mult_m4_m4m4(rotscale_mat, tmat, offs_bone); + } + else if(bone->flag & BONE_NO_SCALE) { + /* Parent pose rotation and rest scale (i.e. no scaling). */ + float tmat[4][4]; + copy_m4_m4(tmat, parchan->pose_mat); + normalize_m4(tmat); + mult_m4_m4m4(rotscale_mat, tmat, offs_bone); + } + else + mult_m4_m4m4(rotscale_mat, parchan->pose_mat, offs_bone); - copy_v3_v3(pose_mat[3], pchan->pose_mat[3]); +# if 1 + /* Compose the loc matrix for this bone. */ + /* NOTE: That version deos not modify bone's loc when HINGE/NO_SCALE options are set. */ + + /* In this case, use the object's space *orientation*. */ + if(bone->flag & BONE_NO_LOCAL_LOCATION) { + /* XXX I'm sure that code can be simplified! */ + float bone_loc[4][4], bone_rotscale[3][3], tmat4[4][4], tmat3[3][3]; + unit_m4(bone_loc); + unit_m4(loc_mat); + unit_m4(tmat4); + + mul_v3_m4v3(bone_loc[3], parchan->pose_mat, offs_bone[3]); + + unit_m3(bone_rotscale); + copy_m3_m4(tmat3, parchan->pose_mat); + mul_m3_m3m3(bone_rotscale, tmat3, bone_rotscale); + + copy_m4_m3(tmat4, bone_rotscale); + mult_m4_m4m4(loc_mat, bone_loc, tmat4); + } + /* Those flags do not affect position, use plain parent transform space! */ + else if(bone->flag & (BONE_HINGE|BONE_NO_SCALE)) { + mult_m4_m4m4(loc_mat, parchan->pose_mat, offs_bone); + } + /* Else (i.e. default, usual case), just use the same matrix for rotation/scaling, and location. */ + else + copy_m4_m4(loc_mat, rotscale_mat); +# endif +# if 0 + /* Compose the loc matrix for this bone. */ + /* NOTE: That version modifies bone's loc when HINGE/NO_SCALE options are set. */ + + /* In these cases we need to compute location separately */ + if(bone->flag & (BONE_HINGE|BONE_NO_SCALE|BONE_NO_LOCAL_LOCATION)) { + float bone_loc[4][4], bone_rotscale[3][3], tmat4[4][4], tmat3[3][3]; + unit_m4(bone_loc); + unit_m4(loc_mat); + unit_m4(tmat4); + + mul_v3_m4v3(bone_loc[3], parchan->pose_mat, offs_bone[3]); + + /* "No local location" is not transformed by bone matrix. */ + /* This only affects orientations (rotations), as scale is always 1.0 here. */ + if(bone->flag & BONE_NO_LOCAL_LOCATION) + unit_m3(bone_rotscale); + else + /* We could also use bone->bone_mat directly, here... */ + copy_m3_m4(bone_rotscale, offs_bone); + + if(bone->flag & BONE_HINGE) { + copy_m3_m4(tmat3, parbone->arm_mat); + /* for hinge-only, we use armature *rotation*, but pose mat *scale*! */ + if(!(bone->flag & BONE_NO_SCALE)) { + float size[3], tsmat[3][3]; + mat4_to_size(size, parchan->pose_mat); + size_to_mat3(tsmat, size); + mul_m3_m3m3(tmat3, tsmat, tmat3); + } + mul_m3_m3m3(bone_rotscale, tmat3, bone_rotscale); + } + else if(bone->flag & BONE_NO_SCALE) { + /* For no-scale only, normalized parent pose mat is enough! */ + copy_m3_m4(tmat3, parchan->pose_mat); + normalize_m3(tmat3); + mul_m3_m3m3(bone_rotscale, tmat3, bone_rotscale); + } + /* NO_LOCAL_LOCATION only. */ + else { + copy_m3_m4(tmat3, parchan->pose_mat); + mul_m3_m3m3(bone_rotscale, tmat3, bone_rotscale); + } + + copy_m4_m3(tmat4, bone_rotscale); + mult_m4_m4m4(loc_mat, bone_loc, tmat4); + } + /* Else, just use the same matrix for rotation/scaling, and location. */ + else + copy_m4_m4(loc_mat, rotscale_mat); +# endif + } + /* Root bones. */ + else { + /* Rotation/scaling. */ + copy_m4_m4(rotscale_mat, pchan->bone->arm_mat); + /* Translation. */ + if(pchan->bone->flag & BONE_NO_LOCAL_LOCATION) { + /* Translation of arm_mat, without the rotation. */ + unit_m4(loc_mat); + copy_v3_v3(loc_mat[3], pchan->bone->arm_mat[3]); + } + else + copy_m4_m4(loc_mat, rotscale_mat); } +} +/* Convert Pose-Space Matrix to Bone-Space Matrix. + * NOTE: this cannot be used to convert to pose-space transforms of the supplied + * pose-channel into its local space (i.e. 'visual'-keyframing) + */ +void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outmat[][4]) +{ + float rotscale_mat[4][4], loc_mat[4][4]; - invert_m4_m4(inv_trans, pc_trans); - - /* Remove the pchan's transforms from it's pose_mat. - * This should leave behind the effects of restpose + - * parenting + constraints - */ - mult_m4_m4m4(pc_posemat, pose_mat, inv_trans); - - /* get the inverse of the leftovers so that we can remove - * that component from the supplied matrix - */ - invert_m4_m4(inv_posemat, pc_posemat); - - /* get the new matrix */ - mult_m4_m4m4(outmat, inv_posemat, inmat); + pchan_to_pose_mat(pchan, rotscale_mat, loc_mat); + invert_m4(rotscale_mat); + invert_m4(loc_mat); + + mult_m4_m4m4(outmat, rotscale_mat, inmat); + mul_v3_m4v3(outmat[3], loc_mat, inmat[3]); } /* Convert Pose-Space Location to Bone-Space Location @@ -1202,6 +1319,23 @@ void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc) copy_v3_v3(outloc, nLocMat[3]); } +void armature_mat_pose_to_bone_ex(Object *ob, bPoseChannel *pchan, float inmat[][4], float outmat[][4]) +{ + bPoseChannel work_pchan = *pchan; + + /* recalculate pose matrix with only parent transformations, + * bone loc/sca/rot is ignored, scene and frame are not used. */ + where_is_pose_bone(NULL, ob, &work_pchan, 0.0f, FALSE); + + /* find the matrix, need to remove the bone transforms first so this is + * calculated as a matrix to set rather then a difference ontop of whats + * already there. */ + unit_m4(outmat); + pchan_apply_mat4(&work_pchan, outmat, FALSE); + + armature_mat_pose_to_bone(&work_pchan, inmat, outmat); +} + /* same as object_mat3_to_rot() */ void pchan_mat3_to_rot(bPoseChannel *pchan, float mat[][3], short use_compat) { @@ -2263,98 +2397,30 @@ void where_is_pose_bone_tail(bPoseChannel *pchan) */ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, int do_extra) { - Bone *bone, *parbone; - bPoseChannel *parchan; - float vec[3]; - - /* set up variables for quicker access below */ - bone= pchan->bone; - parbone= bone->parent; - parchan= pchan->parent; - - /* this gives a chan_mat with actions (ipos) results */ - if(do_extra) pchan_calc_mat(pchan); - else unit_m4(pchan->chan_mat); + /* This gives a chan_mat with actions (ipos) results. */ + if(do_extra) + pchan_calc_mat(pchan); + else + unit_m4(pchan->chan_mat); - /* construct the posemat based on PoseChannels, that we do before applying constraints */ + /* Construct the posemat based on PoseChannels, that we do before applying constraints. */ /* pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) */ - - if(parchan) { - float offs_bone[4][4]; // yoffs(b-1) + root(b) + bonemat(b) - - /* bone transform itself */ - copy_m4_m3(offs_bone, bone->bone_mat); - - /* The bone's root offset (is in the parent's coordinate system) */ - copy_v3_v3(offs_bone[3], bone->head); - - /* Get the length translation of parent (length along y axis) */ - offs_bone[3][1]+= parbone->length; - - /* Compose the matrix for this bone */ - if((bone->flag & BONE_HINGE) && (bone->flag & BONE_NO_SCALE)) { // uses restposition rotation, but actual position - float tmat[4][4]; - /* the rotation of the parent restposition */ - copy_m4_m4(tmat, parbone->arm_mat); - mul_serie_m4(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); - } - else if(bone->flag & BONE_HINGE) { // same as above but apply parent scale - float tmat[4][4]; - - /* apply the parent matrix scale */ - float tsmat[4][4], tscale[3]; - - /* the rotation of the parent restposition */ - copy_m4_m4(tmat, parbone->arm_mat); - - /* extract the scale of the parent matrix */ - mat4_to_size(tscale, parchan->pose_mat); - size_to_mat4(tsmat, tscale); - mult_m4_m4m4(tmat, tsmat, tmat); - - mul_serie_m4(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); - } - else if(bone->flag & BONE_NO_SCALE) { - float orthmat[4][4]; - - /* do transform, with an ortho-parent matrix */ - copy_m4_m4(orthmat, parchan->pose_mat); - normalize_m4(orthmat); - mul_serie_m4(pchan->pose_mat, orthmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); - } - else - mul_serie_m4(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); - - /* in these cases we need to compute location separately */ - if(bone->flag & (BONE_HINGE|BONE_NO_SCALE|BONE_NO_LOCAL_LOCATION)) { - float bone_loc[3], chan_loc[3]; - - mul_v3_m4v3(bone_loc, parchan->pose_mat, offs_bone[3]); - copy_v3_v3(chan_loc, pchan->chan_mat[3]); - - /* no local location is not transformed by bone matrix */ - if(!(bone->flag & BONE_NO_LOCAL_LOCATION)) - mul_mat3_m4_v3(offs_bone, chan_loc); - - /* for hinge we use armature instead of pose mat */ - if(bone->flag & BONE_HINGE) mul_mat3_m4_v3(parbone->arm_mat, chan_loc); - else mul_mat3_m4_v3(parchan->pose_mat, chan_loc); - - add_v3_v3v3(pchan->pose_mat[3], bone_loc, chan_loc); - } - } - else { - mult_m4_m4m4(pchan->pose_mat, bone->arm_mat, pchan->chan_mat); - - /* optional location without arm_mat rotation */ - if(bone->flag & BONE_NO_LOCAL_LOCATION) - add_v3_v3v3(pchan->pose_mat[3], bone->arm_mat[3], pchan->chan_mat[3]); - - /* only rootbones get the cyclic offset (unless user doesn't want that) */ - if ((bone->flag & BONE_NO_CYCLICOFFSET) == 0) + { + float rotscale_mat[4][4], loc_mat[4][4]; + pchan_to_pose_mat(pchan, rotscale_mat, loc_mat); + /* Rotation and scale. */ + mult_m4_m4m4(pchan->pose_mat, rotscale_mat, pchan->chan_mat); + /* Location. */ + mul_v3_m4v3(pchan->pose_mat[3], loc_mat, pchan->chan_mat[3]); + } + + /* Only rootbones get the cyclic offset (unless user doesn't want that). */ + /* XXX That could be a problem for snapping and other "reverse transform" features... */ + if(!pchan->parent) { + if((pchan->bone->flag & BONE_NO_CYCLICOFFSET) == 0) add_v3_v3(pchan->pose_mat[3], ob->pose->cyclic_offset); } - + if(do_extra) { #if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */ @@ -2365,6 +2431,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti /* Do constraints */ if (pchan->constraints.first) { bConstraintOb *cob; + float vec[3]; /* make a copy of location of PoseChannel for later */ copy_v3_v3(vec, pchan->pose_mat[3]); @@ -2388,7 +2455,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti } } } - + /* calculate head */ copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]); /* calculate tail */ diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index ec2e6b3c078..d454bef3184 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -1503,7 +1503,7 @@ BoidState *boid_new_state(BoidSettings *boids) state->id = boids->last_state_id++; if(state->id) - sprintf(state->name, "State %i", state->id); + BLI_snprintf(state->name, sizeof(state->name), "State %i", state->id); else strcpy(state->name, "State"); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 61064bede7e..f2514c1030b 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -487,14 +487,14 @@ int brush_clone_image_delete(Brush *brush) } /* Brush Sampling */ -void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread) +void brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread) { MTex *mtex= &brush->mtex; if (mtex && mtex->tex) { float co[3], tin, tr, tg, tb, ta; int hasrgb; - const int radius= brush_size(brush); + const int radius= brush_size(scene, brush); co[0]= xy[0]/radius; co[1]= xy[1]/radius; @@ -515,19 +515,20 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread) rgba[3]= 1.0f; } } - else if (rgba) + else { rgba[0]= rgba[1]= rgba[2]= rgba[3]= 1.0f; + } } - -void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction) +/* TODO, use define for 'texfall' arg */ +void brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction) { ImBuf *ibuf; - float xy[2], dist, rgba[4], *dstf; + float xy[2], rgba[4], *dstf; int x, y, rowbytes, xoff, yoff, imbflag; - const int radius= brush_size(brush); - char *dst, crgb[3]; - const float alpha= brush_alpha(brush); + const int radius= brush_size(scene, brush); + unsigned char *dst, crgb[3]; + const float alpha= brush_alpha(scene, brush); float brush_rgb[3]; imbflag= (flt)? IB_rectfloat: IB_rect; @@ -554,67 +555,60 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf xy[1] = y + yoff; if (texfall == 0) { - dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - copy_v3_v3(dstf, brush_rgb); - dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius); + dstf[3]= alpha*brush_curve_strength_clamp(brush, len_v2(xy), radius); } else if (texfall == 1) { - brush_sample_tex(brush, xy, dstf, 0); + brush_sample_tex(scene, brush, xy, dstf, 0); } else { - dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - - brush_sample_tex(brush, xy, rgba, 0); + brush_sample_tex(scene, brush, xy, rgba, 0); mul_v3_v3v3(dstf, rgba, brush_rgb); - dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius); + dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, len_v2(xy), radius); } } } } else { - crgb[0]= FTOCHAR(brush->rgb[0]); - crgb[1]= FTOCHAR(brush->rgb[1]); - crgb[2]= FTOCHAR(brush->rgb[2]); + float alpha_f; /* final float alpha to convert to char */ + rgb_float_to_uchar(crgb, brush->rgb); for (y=0; y < ibuf->y; y++) { - dst = (char*)ibuf->rect + y*rowbytes; + dst = (unsigned char *)ibuf->rect + y*rowbytes; for (x=0; x < ibuf->x; x++, dst+=4) { xy[0] = x + xoff; xy[1] = y + yoff; if (texfall == 0) { - dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); + alpha_f = alpha * brush_curve_strength(brush, len_v2(xy), radius); - dst[0]= crgb[0]; - dst[1]= crgb[1]; - dst[2]= crgb[2]; - dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius)); + dst[0] = crgb[0]; + dst[1] = crgb[1]; + dst[2] = crgb[2]; + dst[3] = FTOCHAR(alpha_f); } else if (texfall == 1) { - brush_sample_tex(brush, xy, rgba, 0); - dst[0]= FTOCHAR(rgba[0]); - dst[1]= FTOCHAR(rgba[1]); - dst[2]= FTOCHAR(rgba[2]); - dst[3]= FTOCHAR(rgba[3]); + brush_sample_tex(scene, brush, xy, rgba, 0); + rgba_float_to_uchar(dst, rgba); } else if (texfall == 2) { - dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - - brush_sample_tex(brush, xy, rgba, 0); - dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]); - dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]); - dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]); - dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius)); - } else { - dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - - brush_sample_tex(brush, xy, rgba, 0); - dst[0]= crgb[0]; - dst[1]= crgb[1]; - dst[2]= crgb[2]; - dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius)); + brush_sample_tex(scene, brush, xy, rgba, 0); + mul_v3_v3(rgba, brush->rgb); + alpha_f = rgba[3] * alpha * brush_curve_strength_clamp(brush, len_v2(xy), radius); + + rgb_float_to_uchar(dst, rgba); + + dst[3] = FTOCHAR(alpha_f); + } + else { + brush_sample_tex(scene, brush, xy, rgba, 0); + alpha_f = rgba[3] * alpha * brush_curve_strength_clamp(brush, len_v2(xy), radius); + + dst[0] = crgb[0]; + dst[1] = crgb[1]; + dst[2] = crgb[2]; + dst[3] = FTOCHAR(alpha_f); } } } @@ -623,6 +617,125 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf *outbuf= ibuf; } +/* Unified Size and Strength */ + +// XXX: be careful about setting size and unprojected radius +// because they depend on one another +// these functions do not set the other corresponding value +// this can lead to odd behavior if size and unprojected +// radius become inconsistent. +// the biggest problem is that it isn't possible to change +// unprojected radius because a view context is not +// available. my ussual solution to this is to use the +// ratio of change of the size to change the unprojected +// radius. Not completely convinced that is correct. +// In anycase, a better solution is needed to prevent +// inconsistency. + +void brush_set_size(Scene *scene, Brush *brush, int size) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + if (ups->flag & UNIFIED_PAINT_SIZE) + ups->size= size; + else + brush->size= size; +} + +int brush_size(const Scene *scene, Brush *brush) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + return (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size; +} + +int brush_use_locked_size(const Scene *scene, Brush *brush) +{ + const short us_flag = scene->toolsettings->unified_paint_settings.flag; + + return (us_flag & UNIFIED_PAINT_SIZE) ? + (us_flag & UNIFIED_PAINT_BRUSH_LOCK_SIZE) : + (brush->flag & BRUSH_LOCK_SIZE); +} + +int brush_use_size_pressure(const Scene *scene, Brush *brush) +{ + const short us_flag = scene->toolsettings->unified_paint_settings.flag; + + return (us_flag & UNIFIED_PAINT_SIZE) ? + (us_flag & UNIFIED_PAINT_BRUSH_SIZE_PRESSURE) : + (brush->flag & BRUSH_SIZE_PRESSURE); +} + +int brush_use_alpha_pressure(const Scene *scene, Brush *brush) +{ + const short us_flag = scene->toolsettings->unified_paint_settings.flag; + + return (us_flag & UNIFIED_PAINT_ALPHA) ? + (us_flag & UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE) : + (brush->flag & BRUSH_ALPHA_PRESSURE); +} + +void brush_set_unprojected_radius(Scene *scene, Brush *brush, float unprojected_radius) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + if (ups->flag & UNIFIED_PAINT_SIZE) + ups->unprojected_radius= unprojected_radius; + else + brush->unprojected_radius= unprojected_radius; +} + +float brush_unprojected_radius(const Scene *scene, Brush *brush) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + return (ups->flag & UNIFIED_PAINT_SIZE) ? + ups->unprojected_radius : + brush->unprojected_radius; +} + +static void brush_set_alpha(Scene *scene, Brush *brush, float alpha) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + if (ups->flag & UNIFIED_PAINT_ALPHA) + ups->alpha= alpha; + else + brush->alpha= alpha; +} + +float brush_alpha(const Scene *scene, Brush *brush) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + return (ups->flag & UNIFIED_PAINT_ALPHA) ? ups->alpha : brush->alpha; +} + +/* scale unprojected radius to reflect a change in the brush's 2D size */ +void brush_scale_unprojected_radius(float *unprojected_radius, + int new_brush_size, + int old_brush_size) +{ + float scale = new_brush_size; + /* avoid division by zero */ + if(old_brush_size != 0) + scale /= (float)old_brush_size; + (*unprojected_radius) *= scale; +} + +/* scale brush size to reflect a change in the brush's unprojected radius */ +void brush_scale_size(int *brush_size, + float new_unprojected_radius, + float old_unprojected_radius) +{ + float scale = new_unprojected_radius; + /* avoid division by zero */ + if(old_unprojected_radius != 0) + scale /= new_unprojected_radius; + (*brush_size)= (int)((float)(*brush_size) * scale); +} + /* Brush Painting */ typedef struct BrushPainterCache { @@ -642,6 +755,7 @@ typedef struct BrushPainterCache { } BrushPainterCache; struct BrushPainter { + Scene *scene; Brush *brush; float lastmousepos[2]; /* mouse position of last paint call */ @@ -665,16 +779,17 @@ struct BrushPainter { BrushPainterCache cache; }; -BrushPainter *brush_painter_new(Brush *brush) +BrushPainter *brush_painter_new(Scene *scene, Brush *brush) { BrushPainter *painter= MEM_callocN(sizeof(BrushPainter), "BrushPainter"); painter->brush= brush; + painter->scene= scene; painter->firsttouch= 1; painter->cache.lastsize= -1; /* force ibuf create in refresh */ - painter->startsize = brush_size(brush); - painter->startalpha = brush_alpha(brush); + painter->startsize = brush_size(scene, brush); + painter->startalpha = brush_alpha(scene, brush); painter->startjitter = brush->jitter; painter->startspacing = brush->spacing; @@ -707,8 +822,8 @@ void brush_painter_free(BrushPainter *painter) { Brush *brush = painter->brush; - brush_set_size(brush, painter->startsize); - brush_set_alpha(brush, painter->startalpha); + brush_set_size(painter->scene, brush, painter->startsize); + brush_set_alpha(painter->scene, brush, painter->startalpha); brush->jitter = painter->startjitter; brush->spacing = painter->startspacing; @@ -720,12 +835,13 @@ void brush_painter_free(BrushPainter *painter) static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, int x, int y, int w, int h, int xt, int yt, float *pos) { + Scene *scene= painter->scene; Brush *brush= painter->brush; ImBuf *ibuf, *maskibuf, *texibuf; float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4]; - char *b, *m, *t, *ot= NULL; + unsigned char *b, *m, *t, *ot= NULL; int dotexold, origx= x, origy= y; - const int radius= brush_size(brush); + const int radius= brush_size(painter->scene, brush); xoff = -radius + 0.5f; yoff = -radius + 0.5f; @@ -763,7 +879,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i xy[0] = x + xoff; xy[1] = y + yoff; - brush_sample_tex(brush, xy, tf, 0); + brush_sample_tex(scene, brush, xy, tf, 0); } bf[0] = tf[0]*mf[0]; @@ -775,12 +891,12 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i } else { for (; y < h; y++) { - b = (char*)ibuf->rect + (y*ibuf->x + origx)*4; - t = (char*)texibuf->rect + (y*texibuf->x + origx)*4; - m = (char*)maskibuf->rect + (y*maskibuf->x + origx)*4; + b = (unsigned char *)ibuf->rect + (y*ibuf->x + origx)*4; + t = (unsigned char *)texibuf->rect + (y*texibuf->x + origx)*4; + m = (unsigned char *)maskibuf->rect + (y*maskibuf->x + origx)*4; if (dotexold) - ot = (char*)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4; + ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4; for (x=origx; x < w; x++, b+=4, m+=4, t+=4) { if (dotexold) { @@ -794,11 +910,8 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i xy[0] = x + xoff; xy[1] = y + yoff; - brush_sample_tex(brush, xy, rgba, 0); - t[0]= FTOCHAR(rgba[0]); - t[1]= FTOCHAR(rgba[1]); - t[2]= FTOCHAR(rgba[2]); - t[3]= FTOCHAR(rgba[3]); + brush_sample_tex(scene, brush, xy, rgba, 0); + rgba_float_to_uchar(t, rgba); } b[0] = t[0]*m[0]/255; @@ -812,11 +925,12 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos) { + const Scene *scene= painter->scene; Brush *brush= painter->brush; BrushPainterCache *cache= &painter->cache; ImBuf *oldtexibuf, *ibuf; int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2; - const int diameter= 2*brush_size(brush); + const int diameter= 2*brush_size(scene, brush); imbflag= (cache->flt)? IB_rectfloat: IB_rect; if (!cache->ibuf) @@ -866,13 +980,14 @@ static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float static void brush_painter_refresh_cache(BrushPainter *painter, float *pos, int use_color_correction) { + const Scene *scene= painter->scene; Brush *brush= painter->brush; BrushPainterCache *cache= &painter->cache; MTex *mtex= &brush->mtex; int size; short flt; - const int diameter= 2*brush_size(brush); - const float alpha= brush_alpha(brush); + const int diameter= 2*brush_size(scene, brush); + const float alpha= brush_alpha(scene, brush); if (diameter != cache->lastsize || alpha != cache->lastalpha || @@ -891,11 +1006,11 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos, int u size= (cache->size)? cache->size: diameter; if (brush->flag & BRUSH_FIXED_TEX) { - brush_imbuf_new(brush, flt, 3, size, &cache->maskibuf, use_color_correction); + brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction); brush_painter_fixed_tex_partial_update(painter, pos); } else - brush_imbuf_new(brush, flt, 2, size, &cache->ibuf, use_color_correction); + brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction); cache->lastsize= diameter; cache->lastalpha= alpha; @@ -917,17 +1032,17 @@ void brush_painter_break_stroke(BrushPainter *painter) static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pressure) { - if (brush_use_alpha_pressure(brush)) - brush_set_alpha(brush, MAX2(0.0f, painter->startalpha*pressure)); - if (brush_use_size_pressure(brush)) - brush_set_size(brush, MAX2(1.0f, painter->startsize*pressure)); + if (brush_use_alpha_pressure(painter->scene, brush)) + brush_set_alpha(painter->scene, brush, MAX2(0.0f, painter->startalpha*pressure)); + if (brush_use_size_pressure(painter->scene, brush)) + brush_set_size(painter->scene, brush, MAX2(1.0f, painter->startsize*pressure)); if (brush->flag & BRUSH_JITTER_PRESSURE) brush->jitter = MAX2(0.0f, painter->startjitter*pressure); if (brush->flag & BRUSH_SPACING_PRESSURE) brush->spacing = MAX2(1.0f, painter->startspacing*(1.5f-pressure)); } -void brush_jitter_pos(Brush *brush, float pos[2], float jitterpos[2]) +void brush_jitter_pos(const Scene *scene, Brush *brush, float pos[2], float jitterpos[2]) { int use_jitter= brush->jitter != 0; @@ -937,7 +1052,7 @@ void brush_jitter_pos(Brush *brush, float pos[2], float jitterpos[2]) if(use_jitter){ float rand_pos[2]; - const int radius= brush_size(brush); + const int radius= brush_size(scene, brush); const int diameter= 2*radius; // find random position within a circle of diameter 1 @@ -956,6 +1071,7 @@ void brush_jitter_pos(Brush *brush, float pos[2], float jitterpos[2]) int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user, int use_color_correction) { + Scene *scene= painter->scene; Brush *brush= painter->brush; int totpaintops= 0; @@ -1017,7 +1133,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl else { float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2]; float t, len, press; - const int radius= brush_size(brush); + const int radius= brush_size(scene, brush); /* compute brush spacing adapted to brush radius, spacing may depend on pressure, so update it */ @@ -1042,7 +1158,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush_apply_pressure(painter, brush, press); spacing= MAX2(1.0f, radius)*brush->spacing*0.01f; - brush_jitter_pos(brush, paintpos, finalpos); + brush_jitter_pos(scene, brush, paintpos, finalpos); if (painter->cache.enabled) brush_painter_refresh_cache(painter, finalpos, use_color_correction); @@ -1056,7 +1172,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl startdistance -= spacing; } } else { - brush_jitter_pos(brush, pos, finalpos); + brush_jitter_pos(scene, brush, pos, finalpos); if (painter->cache.enabled) brush_painter_refresh_cache(painter, finalpos, use_color_correction); @@ -1084,7 +1200,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl while (painter->accumtime >= (double)brush->rate) { brush_apply_pressure(painter, brush, pressure); - brush_jitter_pos(brush, pos, finalpos); + brush_jitter_pos(scene, brush, pos, finalpos); if (painter->cache.enabled) brush_painter_refresh_cache(painter, finalpos, use_color_correction); @@ -1102,8 +1218,8 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl painter->lastmousepos[1]= pos[1]; painter->lastpressure= pressure; - brush_set_alpha(brush, painter->startalpha); - brush_set_size(brush, painter->startsize); + brush_set_alpha(scene, brush, painter->startalpha); + brush_set_size(scene, brush, painter->startsize); brush->jitter = painter->startjitter; brush->spacing = painter->startspacing; @@ -1213,298 +1329,3 @@ struct ImBuf *brush_gen_radial_control_imbuf(Brush *br) return im; } - -/* Unified Size and Strength */ - -/* XXX, wouldnt it be better to only pass the active scene? - * this can return any old scene! - campbell*/ - -static void set_unified_settings(Brush *brush, short flag, int value) -{ - Scene *sce; - for (sce= G.main->scene.first; sce; sce= sce->id.next) { - if (sce->toolsettings && - ELEM4(brush, - paint_brush(&(sce->toolsettings->imapaint.paint)), - paint_brush(&(sce->toolsettings->vpaint->paint)), - paint_brush(&(sce->toolsettings->wpaint->paint)), - paint_brush(&(sce->toolsettings->sculpt->paint)))) - { - if (value) - sce->toolsettings->sculpt_paint_settings |= flag; - else - sce->toolsettings->sculpt_paint_settings &= ~flag; - } - } -} - -static short unified_settings(Brush *brush) -{ - Scene *sce; - for (sce= G.main->scene.first; sce; sce= sce->id.next) { - if (sce->toolsettings && - ELEM4(brush, - paint_brush(&(sce->toolsettings->imapaint.paint)), - paint_brush(&(sce->toolsettings->vpaint->paint)), - paint_brush(&(sce->toolsettings->wpaint->paint)), - paint_brush(&(sce->toolsettings->sculpt->paint)))) - { - return sce->toolsettings->sculpt_paint_settings; - } - } - - return 0; -} - -// XXX: be careful about setting size and unprojected radius -// because they depend on one another -// these functions do not set the other corresponding value -// this can lead to odd behavior if size and unprojected -// radius become inconsistent. -// the biggest problem is that it isn't possible to change -// unprojected radius because a view context is not -// available. my ussual solution to this is to use the -// ratio of change of the size to change the unprojected -// radius. Not completely convinced that is correct. -// In anycase, a better solution is needed to prevent -// inconsistency. - -static void set_unified_size(Brush *brush, int value) -{ - Scene *sce; - for (sce= G.main->scene.first; sce; sce= sce->id.next) { - if (sce->toolsettings && - ELEM4(brush, - paint_brush(&(sce->toolsettings->imapaint.paint)), - paint_brush(&(sce->toolsettings->vpaint->paint)), - paint_brush(&(sce->toolsettings->wpaint->paint)), - paint_brush(&(sce->toolsettings->sculpt->paint)))) - { - sce->toolsettings->sculpt_paint_unified_size= value; - } - } -} - -static int unified_size(Brush *brush) -{ - Scene *sce; - for (sce= G.main->scene.first; sce; sce= sce->id.next) { - if (sce->toolsettings && - ELEM4(brush, - paint_brush(&(sce->toolsettings->imapaint.paint)), - paint_brush(&(sce->toolsettings->vpaint->paint)), - paint_brush(&(sce->toolsettings->wpaint->paint)), - paint_brush(&(sce->toolsettings->sculpt->paint)))) - { - return sce->toolsettings->sculpt_paint_unified_size; - } - } - - return 35; // XXX magic number -} - -static void set_unified_alpha(Brush *brush, float value) -{ - Scene *sce; - for (sce= G.main->scene.first; sce; sce= sce->id.next) { - if (sce->toolsettings && - ELEM4(brush, - paint_brush(&(sce->toolsettings->imapaint.paint)), - paint_brush(&(sce->toolsettings->vpaint->paint)), - paint_brush(&(sce->toolsettings->wpaint->paint)), - paint_brush(&(sce->toolsettings->sculpt->paint)))) - { - sce->toolsettings->sculpt_paint_unified_alpha= value; - } - } -} - -static float unified_alpha(Brush *brush) -{ - Scene *sce; - for (sce= G.main->scene.first; sce; sce= sce->id.next) { - if (sce->toolsettings && - ELEM4(brush, - paint_brush(&(sce->toolsettings->imapaint.paint)), - paint_brush(&(sce->toolsettings->vpaint->paint)), - paint_brush(&(sce->toolsettings->wpaint->paint)), - paint_brush(&(sce->toolsettings->sculpt->paint)))) - { - return sce->toolsettings->sculpt_paint_unified_alpha; - } - } - - return 0.5f; // XXX magic number -} - -static void set_unified_unprojected_radius(Brush *brush, float value) -{ - Scene *sce; - for (sce= G.main->scene.first; sce; sce= sce->id.next) { - if (sce->toolsettings && - ELEM4(brush, - paint_brush(&(sce->toolsettings->imapaint.paint)), - paint_brush(&(sce->toolsettings->vpaint->paint)), - paint_brush(&(sce->toolsettings->wpaint->paint)), - paint_brush(&(sce->toolsettings->sculpt->paint)))) - { - sce->toolsettings->sculpt_paint_unified_unprojected_radius= value; - } - } -} - -static float unified_unprojected_radius(Brush *brush) -{ - Scene *sce; - for (sce= G.main->scene.first; sce; sce= sce->id.next) { - if (sce->toolsettings && - ELEM4(brush, - paint_brush(&(sce->toolsettings->imapaint.paint)), - paint_brush(&(sce->toolsettings->vpaint->paint)), - paint_brush(&(sce->toolsettings->wpaint->paint)), - paint_brush(&(sce->toolsettings->sculpt->paint)))) - { - return sce->toolsettings->sculpt_paint_unified_unprojected_radius; - } - } - - return 0.125f; // XXX magic number -} -void brush_set_size(Brush *brush, int size) -{ - const short us_flag = unified_settings(brush); - - if (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) - set_unified_size(brush, size); - else - brush->size= size; - - //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush); -} - -int brush_size(Brush *brush) -{ - const short us_flag = unified_settings(brush); - - return (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_size(brush) : brush->size; -} - -void brush_set_use_locked_size(Brush *brush, int value) -{ - const short us_flag = unified_settings(brush); - - if (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) { - set_unified_settings(brush, SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE, value); - } - else { - if (value) - brush->flag |= BRUSH_LOCK_SIZE; - else - brush->flag &= ~BRUSH_LOCK_SIZE; - } - - //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush); -} - -int brush_use_locked_size(Brush *brush) -{ - const short us_flag = unified_settings(brush); - - return (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) ? - (us_flag & SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE) : - (brush->flag & BRUSH_LOCK_SIZE); -} - -void brush_set_use_size_pressure(Brush *brush, int value) -{ - const short us_flag = unified_settings(brush); - - if (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) { - set_unified_settings(brush, SCULPT_PAINT_UNIFIED_SIZE_PRESSURE, value); - } - else { - if (value) - brush->flag |= BRUSH_SIZE_PRESSURE; - else - brush->flag &= ~BRUSH_SIZE_PRESSURE; - } - - //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush); -} - -int brush_use_size_pressure(Brush *brush) -{ - const short us_flag = unified_settings(brush); - - return (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) ? - (us_flag & SCULPT_PAINT_UNIFIED_SIZE_PRESSURE) : - (brush->flag & BRUSH_SIZE_PRESSURE); -} - -void brush_set_use_alpha_pressure(Brush *brush, int value) -{ - const short us_flag = unified_settings(brush); - - if (us_flag & SCULPT_PAINT_USE_UNIFIED_ALPHA) { - set_unified_settings(brush, SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE, value); - } - else { - if (value) - brush->flag |= BRUSH_ALPHA_PRESSURE; - else - brush->flag &= ~BRUSH_ALPHA_PRESSURE; - } - - //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush); -} - -int brush_use_alpha_pressure(Brush *brush) -{ - const short us_flag = unified_settings(brush); - - return (us_flag & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? - (us_flag & SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE) : - (brush->flag & BRUSH_ALPHA_PRESSURE); -} - -void brush_set_unprojected_radius(Brush *brush, float unprojected_radius) -{ - const short us_flag = unified_settings(brush); - - if (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) - set_unified_unprojected_radius(brush, unprojected_radius); - else - brush->unprojected_radius= unprojected_radius; - - //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush); -} - -float brush_unprojected_radius(Brush *brush) -{ - const short us_flag = unified_settings(brush); - - return (us_flag & SCULPT_PAINT_USE_UNIFIED_SIZE) ? - unified_unprojected_radius(brush) : - brush->unprojected_radius; -} - -void brush_set_alpha(Brush *brush, float alpha) -{ - const short us_flag = unified_settings(brush); - - if (us_flag & SCULPT_PAINT_USE_UNIFIED_ALPHA) - set_unified_alpha(brush, alpha); - else - brush->alpha= alpha; - - //WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush); -} - -float brush_alpha(Brush *brush) -{ - const short us_flag = unified_settings(brush); - - return (us_flag & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? - unified_alpha(brush) : - brush->alpha; -} diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4d5dce14b27..d86fc5c9aef 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -47,7 +47,6 @@ #include "BKE_modifier.h" #include "BKE_pointcache.h" - #ifdef _WIN32 void tstart ( void ) {} @@ -91,7 +90,7 @@ static CM_SOLVER_DEF solvers [] = /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ -static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); +static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]); static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); @@ -131,6 +130,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->presets = 2; /* cotton as start setting */ clmd->sim_parms->timescale = 1.0f; /* speed factor, describes how fast cloth moves */ clmd->sim_parms->reset = 0; + clmd->sim_parms->vel_damping = 1.0f; /* 1.0 = no damping, 0.0 = fully dampened */ clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->friction = 5.0; @@ -377,6 +377,8 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul } implicit_set_positions(clmd); + + clmd->clothObject->last_frame= MINFRAME-1; } return 1; @@ -427,9 +429,8 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul /************************************************ * clothModifier_do - main simulation function ************************************************/ -DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm) +void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3]) { - DerivedMesh *result; PointCache *cache; PTCacheID pid; float timescale; @@ -439,20 +440,14 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, clmd->scene= scene; /* nice to pass on later :) */ framenr= (int)scene->r.cfra; cache= clmd->point_cache; - result = CDDM_copy(dm); BKE_ptcache_id_from_cloth(&pid, ob, clmd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); clmd->sim_parms->timescale= timescale; - if(!result) { - BKE_ptcache_invalidate(cache); - return dm; - } - if(clmd->sim_parms->reset || (framenr == (startframe - clmd->sim_parms->preroll) && clmd->sim_parms->preroll != 0) - || (clmd->clothObject && result->getNumVerts(result) != clmd->clothObject->numverts)) + || (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->numverts)) { clmd->sim_parms->reset = 0; cache->flag |= PTCACHE_OUTDATED; @@ -460,7 +455,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, BKE_ptcache_validate(cache, 0); cache->last_exact= 0; cache->flag &= ~PTCACHE_REDO_NEEDED; - return result; + return; } // unused in the moment, calculated separately in implicit.c @@ -472,18 +467,20 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, /* do simulation */ if(!do_init_cloth(ob, clmd, dm, framenr)) - return result; + return; do_step_cloth(ob, clmd, dm, framenr); - cloth_to_object(ob, clmd, result); + cloth_to_object(ob, clmd, vertexCos); + + clmd->clothObject->last_frame= framenr; - return result; + return; } /* simulation is only active during a specific period */ if(framenr < startframe) { BKE_ptcache_invalidate(cache); - return result; + return; } else if(framenr > endframe) { framenr= endframe; @@ -491,14 +488,15 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, /* initialize simulation data if it didn't exist already */ if(!do_init_cloth(ob, clmd, dm, framenr)) - return result; + return; if((framenr == startframe) && (clmd->sim_parms->preroll == 0)) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); do_init_cloth(ob, clmd, dm, framenr); BKE_ptcache_validate(cache, framenr); cache->flag &= ~PTCACHE_REDO_NEEDED; - return result; + clmd->clothObject->last_frame= framenr; + return; } /* try to read from cache */ @@ -506,14 +504,16 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { implicit_set_positions(clmd); - cloth_to_object (ob, clmd, result); + cloth_to_object (ob, clmd, vertexCos); BKE_ptcache_validate(cache, framenr); if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) BKE_ptcache_write(&pid, framenr); - return result; + clmd->clothObject->last_frame= framenr; + + return; } else if(cache_result==PTCACHE_READ_OLD) { implicit_set_positions(clmd); @@ -521,9 +521,12 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, else if( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ /* if baked and nothing in cache, do nothing */ BKE_ptcache_invalidate(cache); - return result; + return; } + if(framenr!=clmd->clothObject->last_frame+1) + return; + /* if on second frame, write cache for first frame */ if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) BKE_ptcache_write(&pid, startframe); @@ -539,9 +542,8 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, else BKE_ptcache_write(&pid, framenr); - cloth_to_object (ob, clmd, result); - - return result; + cloth_to_object (ob, clmd, vertexCos); + clmd->clothObject->last_frame= framenr; } /* frees all */ @@ -696,24 +698,19 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) * cloth_to_object - copies the deformed vertices to the object. * **/ -static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm) +static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]) { unsigned int i = 0; - MVert *mvert = NULL; - unsigned int numverts; Cloth *cloth = clmd->clothObject; if (clmd->clothObject) { /* inverse matrix is not uptodate... */ invert_m4_m4(ob->imat, ob->obmat); - mvert = CDDM_get_verts(dm); - numverts = dm->getNumVerts(dm); - - for (i = 0; i < numverts; i++) + for (i = 0; i < cloth->numverts; i++) { - copy_v3_v3 (mvert[i].co, cloth->verts[i].x); - mul_m4_v3(ob->imat, mvert[i].co); /* cloth is in global coords */ + copy_v3_v3 (vertexCos[i], cloth->verts[i].x); + mul_m4_v3(ob->imat, vertexCos[i]); /* cloth is in global coords */ } } } diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 67bd6a22348..108b4e48a95 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1002,7 +1002,7 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) } /* we still need luma for histogram */ - luma = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2]; + luma = rgb_to_luma(rgb); /* check for min max */ if(ycc_mode == -1 ) { diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 878db6b3ed1..59667743520 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -41,6 +41,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_editVert.h" +#include "BLI_kdopbvh.h" #include "BLI_utildefines.h" #include "DNA_armature_types.h" @@ -64,6 +65,7 @@ #include "BKE_anim.h" /* for the curve calculation part */ #include "BKE_armature.h" #include "BKE_blender.h" +#include "BKE_bvhutils.h" #include "BKE_camera.h" #include "BKE_constraint.h" #include "BKE_displist.h" @@ -297,6 +299,12 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 copy_m4_m4(tempmat, mat); mult_m4_m4m4(mat, imat, tempmat); + + /* override with local location */ + if ((pchan->parent) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) { + armature_mat_pose_to_bone_ex(ob, pchan, pchan->pose_mat, tempmat); + copy_v3_v3(mat[3], tempmat[3]); + } } } /* pose to local with parent */ @@ -502,13 +510,17 @@ static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat normalize_v3(normal); copy_v3_v3(plane, tmat[1]); - copy_v3_v3(tmat[2], normal); - cross_v3_v3v3(tmat[0], normal, plane); - cross_v3_v3v3(tmat[1], tmat[2], tmat[0]); - - copy_m4_m3(mat, tmat); + cross_v3_v3v3(mat[0], normal, plane); + if(len_v3(mat[0]) < 1e-3) { + copy_v3_v3(plane, tmat[0]); + cross_v3_v3v3(mat[0], normal, plane); + } + + copy_v3_v3(mat[2], normal); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_m4(mat); - + /* apply the average coordinate as the new location */ mul_v3_m4v3(mat[3], ob->obmat, vec); @@ -2773,18 +2785,22 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase * /* store Z orientation before destroying obmat */ normalize_v3_v3(zz, cob->matrix[2]); - sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]); - vec[0] /= size[0]; - vec[1] /= size[1]; - vec[2] /= size[2]; + /* XXX That makes the constraint buggy with asymmetrically scaled objects, see #29940. */ +/* sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);*/ +/* vec[0] /= size[0];*/ +/* vec[1] /= size[1];*/ +/* vec[2] /= size[2];*/ - dist = normalize_v3(vec); - //dist = len_v3v3( ob->obmat[3], targetmat[3]); +/* dist = normalize_v3(vec);*/ + + dist = len_v3v3(cob->matrix[3], ct->matrix[3]); + /* Only Y constrained object axis scale should be used, to keep same length when scaling it. */ + dist /= size[1]; /* data->orglength==0 occurs on first run, and after 'R' button is clicked */ - if (data->orglength == 0) + if (data->orglength == 0) data->orglength = dist; - if (data->bulge == 0) + if (data->bulge == 0) data->bulge = 1.0; scale[1] = dist/data->orglength; @@ -3950,6 +3966,7 @@ static void followtrack_id_looper (bConstraint *con, ConstraintIDFunc func, void func(con, (ID**)&data->clip, userdata); func(con, (ID**)&data->camera, userdata); + func(con, (ID**)&data->depth_ob, userdata); } static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) @@ -3985,7 +4002,6 @@ static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { if (track->flag & TRACK_HAS_BUNDLE) { - MovieTracking *tracking= &clip->tracking; float obmat[4][4], mat[4][4]; copy_m4_m4(obmat, cob->matrix); @@ -4008,9 +4024,8 @@ static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); } } - } + } else { - MovieClipUser user; MovieTrackingMarker *marker; float vec[3], disp[3], axis[3], mat[4][4]; float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp); @@ -4035,8 +4050,7 @@ static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase CameraParams params; float pos[2], rmat[4][4]; - user.framenr= scene->r.cfra; - marker= BKE_tracking_get_marker(track, user.framenr); + marker= BKE_tracking_get_marker(track, scene->r.cfra); add_v2_v2v2(pos, marker->pos, track->offset); @@ -4078,6 +4092,34 @@ static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase copy_v3_v3(cob->matrix[3], disp); } + + if(data->depth_ob && data->depth_ob->derivedFinal) { + 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; + + 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]); + + sub_v3_v3v3(ray_nor, ray_end, ray_start); + + bvhtree_from_mesh_faces(&treeData, depth_ob->derivedFinal, 0.0f, 4, 6); + + 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); + + if(result != -1) { + mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co); + } + + free_bvhtree_from_mesh(&treeData); + } } } } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 9e9a0ca2d54..05c56fa8101 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -381,7 +381,8 @@ void CTX_wm_window_set(bContext *C, wmWindow *win) { C->wm.window= win; C->wm.screen= (win)? win->screen: NULL; - C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL; + if(C->wm.screen) + C->data.scene= C->wm.screen->scene; C->wm.area= NULL; C->wm.region= NULL; } @@ -389,7 +390,8 @@ void CTX_wm_window_set(bContext *C, wmWindow *win) void CTX_wm_screen_set(bContext *C, bScreen *screen) { C->wm.screen= screen; - C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL; + if(C->wm.screen) + C->data.scene= C->wm.screen->scene; C->wm.area= NULL; C->wm.region= NULL; } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 0f1c73c59c1..6536dfb529e 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -368,9 +368,8 @@ void tex_space_curve(Curve *cu) dl= cu->disp.first; while(dl) { - if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr; - else tot= dl->nr*dl->parts; - + tot = ELEM(dl->type, DL_INDEX3, DL_INDEX4) ? dl->nr : dl->nr * dl->parts; + if(tot) doit= 1; fp= dl->verts; while(tot--) { diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 35b2499bea5..f840774222a 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1519,7 +1519,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, data->layers[index].data = newlayerdata; if(name || (name=typeInfo->defaultname)) { - BLI_strncpy(data->layers[index].name, name, 32); + BLI_strncpy(data->layers[index].name, name, sizeof(data->layers[index].name)); CustomData_set_layer_unique_name(data, index); } else diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 6fb4164d6c6..3f3e3b80042 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -476,22 +476,22 @@ void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_ switch(name[0]) { case 'l': strcpy(replace, "r"); - strcpy(suffix, name+1); + BLI_strncpy(suffix, name+1, sizeof(suffix)); prefix[0]= 0; break; case 'r': strcpy(replace, "l"); - strcpy(suffix, name+1); + BLI_strncpy(suffix, name+1, sizeof(suffix)); prefix[0]= 0; break; case 'L': strcpy(replace, "R"); - strcpy(suffix, name+1); + BLI_strncpy(suffix, name+1, sizeof(suffix)); prefix[0]= 0; break; case 'R': strcpy(replace, "L"); - strcpy(suffix, name+1); + BLI_strncpy(suffix, name+1, sizeof(suffix)); prefix[0]= 0; break; } @@ -501,29 +501,29 @@ void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_ index = BLI_strcasestr(prefix, "right"); if (index==prefix || index==prefix+len-5) { if (index[0]=='r') - strcpy (replace, "left"); + strcpy(replace, "left"); else { if (index[1]=='I') - strcpy (replace, "LEFT"); + strcpy(replace, "LEFT"); else - strcpy (replace, "Left"); + strcpy(replace, "Left"); } *index= 0; - strcpy (suffix, index+5); + BLI_strncpy(suffix, index+5, sizeof(suffix)); } else { index = BLI_strcasestr(prefix, "left"); if (index==prefix || index==prefix+len-4) { if (index[0]=='l') - strcpy (replace, "right"); + strcpy(replace, "right"); else { if (index[1]=='E') - strcpy (replace, "RIGHT"); + strcpy(replace, "RIGHT"); else - strcpy (replace, "Right"); + strcpy(replace, "Right"); } *index= 0; - strcpy (suffix, index+4); + BLI_strncpy(suffix, index + 4, sizeof(suffix)); } } } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 3cb2f8ce738..e67056cdd9e 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -539,6 +539,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } break; case OB_CURVE: + case OB_FONT: { Curve *cu= ob->data; @@ -550,15 +551,11 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O node2 = dag_get_node(dag, cu->taperobj); dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Curve Taper"); } - } - break; - case OB_FONT: - { - Curve *cu= ob->data; - - if(cu->textoncurve) { - node2 = dag_get_node(dag, cu->textoncurve); - dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Texture On Curve"); + if(ob->type == OB_FONT) { + if(cu->textoncurve) { + node2 = dag_get_node(dag, cu->textoncurve); + dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Texture On Curve"); + } } } break; @@ -657,6 +654,11 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if((data->clip || data->flag&FOLLOWTRACK_ACTIVECLIP) && data->track[0]) depends_on_camera= 1; + + if(data->depth_ob) { + node2 = dag_get_node(dag, data->depth_ob); + dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name); + } } else if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER) depends_on_camera= 1; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index a5be056bc16..e0f76917368 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -269,9 +269,9 @@ int surfindex_displist(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, i (*b)= 1; } - if( (dl->flag & DL_CYCL_V) && a==dl->parts-1) { \ - (*p3)-= dl->nr*dl->parts; \ - (*p4)-= dl->nr*dl->parts; \ + if( (dl->flag & DL_CYCL_V) && a==dl->parts-1) { + (*p3)-= dl->nr*dl->parts; + (*p4)-= dl->nr*dl->parts; } return 1; @@ -833,6 +833,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba int editmode = (!forRender && cu->editnurb); DerivedMesh *dm= NULL, *ndm; float (*vertCos)[3] = NULL; + int useCache = !forRender; if(forRender) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; @@ -911,7 +912,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba vertCos= NULL; } - ndm = mti->applyModifier(md, ob, dm, forRender, editmode); + ndm = mti->applyModifier(md, ob, dm, forRender, useCache); if (ndm) { /* Modifier returned a new derived mesh */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 567cc5ce07f..cdfd5d3562b 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -97,13 +97,18 @@ static int neighY[8] = {0,1,1, 1, 0,-1,-1,-1}; /* brush mesh raycast status */ #define HIT_VOLUME 1 #define HIT_PROXIMITY 2 +/* dynamicPaint_findNeighbourPixel() return codes */ +#define NOT_FOUND -1 +#define ON_MESH_EDGE -2 +#define OUT_OF_TEXTURE -3 /* paint effect default movement per frame in global units */ #define EFF_MOVEMENT_PER_FRAME 0.05f /* initial wave time factor */ #define WAVE_TIME_FAC (1.0f/24.f) -#define WAVE_INIT_SIZE 5.0f +#define CANVAS_REL_SIZE 5.0f /* drying limits */ #define MIN_WETNESS 0.001f +#define MAX_WETNESS 5.0f /* dissolve macro */ #define VALUE_DISSOLVE(VALUE, TIME, SCALE, LOG) (VALUE) = (LOG) ? (VALUE) * (pow(MIN_WETNESS,1.0f/(1.2f*((float)(TIME))/(SCALE)))) : (VALUE) - 1.0f/(TIME)*(SCALE) @@ -133,10 +138,10 @@ typedef struct Vec3f { float v[3]; } Vec3f; -typedef struct BakeNeighPoint { +typedef struct BakeAdjPoint { float dir[3]; /* vector pointing towards this neighbour */ float dist; /* distance to */ -} BakeNeighPoint; +} BakeAdjPoint; /* Surface data used while processing a frame */ typedef struct PaintBakeNormal { @@ -155,7 +160,7 @@ typedef struct PaintBakeData { Bounds3D mesh_bounds; /* adjacency info */ - BakeNeighPoint *bNeighs; /* current global neighbour distances and directions, if required */ + BakeAdjPoint *bNeighs; /* current global neighbour distances and directions, if required */ double average_dist; /* space partitioning */ VolumeGrid *grid; /* space partitioning grid to optimize brush checks */ @@ -187,12 +192,6 @@ typedef struct ImgSeqFormatData { Vec3f *barycentricWeights; /* b-weights for all pixel samples */ } ImgSeqFormatData; -typedef struct EffVelPoint { - float previous_pos[3]; - float previous_vel[3]; -} EffVelPoint; - - /* adjacency data flags */ #define ADJ_ON_MESH_EDGE (1<<0) @@ -361,8 +360,8 @@ void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface) surface->depth_clamp = 1.0f; } else { - sprintf(surface->output_name, "dp_"); - strcpy(surface->output_name2,surface->output_name); + strcpy(surface->output_name, "dp_"); + strcpy(surface->output_name2, surface->output_name); surface->flags &= ~MOD_DPAINT_ANTIALIAS; surface->depth_clamp = 0.0f; } @@ -422,15 +421,31 @@ static void blendColors(float t_color[3], float t_alpha, float s_color[3], float result[3] = f_alpha; } -/* assumes source alpha > 0.0f or results NaN colors */ -static void mixColors(float *t_color, float t_alpha, float *s_color, float s_alpha) +/* Mix two alpha weighed colors by a defined ratio. output is saved at a_color */ +static float mixColors(float a_color[3], float a_weight, float b_color[3], float b_weight, float ratio) { - float factor = (s_alpha<t_alpha) ? 1.0f : t_alpha/s_alpha; + float weight_ratio, factor; + if (b_weight) { + /* if first value has no weight just use b_color */ + if (!a_weight) { + copy_v3_v3(a_color, b_color); + return b_weight*ratio; + } + weight_ratio = b_weight/(a_weight+b_weight); + } + else return a_weight*(1.0f-ratio); - /* set initial color depending on existing alpha */ - interp_v3_v3v3(t_color, s_color, t_color, factor); + /* calculate final interpolation factor */ + if (ratio<=0.5f) { + factor = weight_ratio*(ratio*2.0f); + } + else { + ratio = (ratio*2.0f - 1.0f); + factor = weight_ratio*(1.0f-ratio) + ratio; + } /* mix final color */ - interp_v3_v3v3(t_color, t_color, s_color, s_alpha); + interp_v3_v3v3(a_color, a_color, b_color, factor); + return (1.0f-factor)*a_weight + factor*b_weight; } /* set "ignore cache" flag for all caches on this object */ @@ -452,19 +467,25 @@ static void object_cacheIgnoreClear(Object *ob, int state) BLI_freelistN(&pidlist); } -static void subframe_updateObject(Scene *scene, Object *ob, int flags, float frame) +static int subframe_updateObject(Scene *scene, Object *ob, int flags, float frame) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); bConstraint *con; /* if other is dynamic paint canvas, dont update */ if (pmd && pmd->canvas) - return; + return 1; /* if object has parents, update them too */ if (flags & UPDATE_PARENTS) { - if (ob->parent) subframe_updateObject(scene, ob->parent, 0, frame); - if (ob->track) subframe_updateObject(scene, ob->track, 0, frame); + int is_canvas = 0; + if (ob->parent) is_canvas += subframe_updateObject(scene, ob->parent, 0, frame); + if (ob->track) is_canvas += subframe_updateObject(scene, ob->track, 0, frame); + + /* skip subframe if object is parented + * to vertex of a dynamic paint canvas */ + if (is_canvas && (ob->partype == PARVERT1 || ob->partype == PARVERT3)) + return 0; /* also update constraint targets */ for (con = ob->constraints.first; con; con=con->next) { @@ -501,6 +522,8 @@ static void subframe_updateObject(Scene *scene, Object *ob, int flags, float fra } else where_is_object_time(scene, ob, frame); + + return 0; } static void scene_setSubframe(Scene *scene, float subframe) @@ -617,6 +640,12 @@ static void boundInsert(Bounds3D *b, float point[3]) } } +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])); +} + static void freeGrid(PaintSurfaceData *data) { PaintBakeData *bData = data->bData; @@ -959,17 +988,21 @@ struct DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSett /* Set initial values */ surface->flags = MOD_DPAINT_ANTIALIAS | MOD_DPAINT_MULALPHA | MOD_DPAINT_DRY_LOG | MOD_DPAINT_DISSOLVE_LOG | - MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1; + MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1 | MOD_DPAINT_USE_DRYING; surface->effect = 0; surface->effect_ui = 1; surface->diss_speed = 250; surface->dry_speed = 500; + surface->color_dry_threshold = 1.0f; surface->depth_clamp = 0.0f; surface->disp_factor = 1.0f; surface->disp_type = MOD_DPAINT_DISP_DISPLACE; surface->image_fileformat = MOD_DPAINT_IMGFORMAT_PNG; + surface->influence_scale = 1.0f; + surface->radius_scale = 1.0f; + surface->init_color[0] = 1.0f; surface->init_color[1] = 1.0f; surface->init_color[2] = 1.0f; @@ -1194,7 +1227,7 @@ static int surface_usesAdjData(DynamicPaintSurface *surface) static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int force_init) { PaintSurfaceData *sData = surface->data; - PaintAdjData *ed; + PaintAdjData *ad; int *temp_data; int neigh_points = 0; @@ -1210,17 +1243,17 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for if (!neigh_points) return; /* allocate memory */ - ed = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data"); - if (!ed) return; - ed->n_index = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Index"); - ed->n_num = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Counts"); + ad = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data"); + if (!ad) return; + ad->n_index = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Index"); + ad->n_num = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Counts"); temp_data = MEM_callocN(sizeof(int)*sData->total_points, "Temp Adj Data"); - ed->n_target = MEM_callocN(sizeof(int)*neigh_points, "Surface Adj Targets"); - ed->flags = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Flags"); - ed->total_targets = neigh_points; + ad->n_target = MEM_callocN(sizeof(int)*neigh_points, "Surface Adj Targets"); + ad->flags = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Flags"); + ad->total_targets = neigh_points; /* in case of allocation error, free memory */ - if (!ed->n_index || !ed->n_num || !ed->n_target || !temp_data) { + if (!ad->n_index || !ad->n_num || !ad->n_target || !temp_data) { dynamicPaint_freeAdjData(sData); if (temp_data) MEM_freeN(temp_data); setError(surface->canvas, "Not enough free memory."); @@ -1239,14 +1272,15 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for /* count number of edges per vertex */ for (i=0; i<numOfEdges; i++) { - ed->n_num[edge[i].v1]++; - ed->n_num[edge[i].v2]++; + ad->n_num[edge[i].v1]++; + ad->n_num[edge[i].v2]++; temp_data[edge[i].v1]++; temp_data[edge[i].v2]++; } - /* to locate points on "mesh edge" */ + /* also add number of vertices to temp_data + * to locate points on "mesh edge" */ for (i=0; i<numOfFaces; i++) { temp_data[face[i].v1]++; temp_data[face[i].v2]++; @@ -1260,7 +1294,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for for (i=0; i<sData->total_points; i++) { if ((temp_data[i]%2) || temp_data[i] < 4) - ed->flags[i] |= ADJ_ON_MESH_EDGE; + ad->flags[i] |= ADJ_ON_MESH_EDGE; /* reset temp data */ temp_data[i] = 0; @@ -1269,22 +1303,22 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for /* order n_index array */ n_pos = 0; for (i=0; i<sData->total_points; i++) { - ed->n_index[i] = n_pos; - n_pos += ed->n_num[i]; + ad->n_index[i] = n_pos; + n_pos += ad->n_num[i]; } /* and now add neighbour data using that info */ for (i=0; i<numOfEdges; i++) { /* first vertex */ int index = edge[i].v1; - n_pos = ed->n_index[index]+temp_data[index]; - ed->n_target[n_pos] = edge[i].v2; + n_pos = ad->n_index[index]+temp_data[index]; + ad->n_target[n_pos] = edge[i].v2; temp_data[index]++; /* second vertex */ index = edge[i].v2; - n_pos = ed->n_index[index]+temp_data[index]; - ed->n_target[n_pos] = edge[i].v1; + n_pos = ad->n_index[index]+temp_data[index]; + ad->n_target[n_pos] = edge[i].v1; temp_data[index]++; } } @@ -1323,7 +1357,7 @@ void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) MTFace *tface; MFace *mface = dm->getFaceArray(dm); int numOfFaces = dm->getNumFaces(dm); - char uvname[40]; + char uvname[MAX_CUSTOMDATA_LAYER_NAME]; if (!tex) return; @@ -1472,10 +1506,11 @@ void dynamicPaint_clearSurface(DynamicPaintSurface *surface) int dynamicPaint_resetSurface(DynamicPaintSurface *surface) { int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface); - /* dont touch image sequence types. they get handled only on bake */ - if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1; - + /* free existing data */ if (surface->data) dynamicPaint_freeSurfaceData(surface); + + /* dont reallocate for image sequence types. they get handled only on bake */ + if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1; if (numOfPoints < 1) return 0; /* allocate memory */ @@ -1508,7 +1543,7 @@ static int dynamicPaint_checkSurfaceData(DynamicPaintSurface *surface) /* apply displacing vertex surface to the derived mesh */ -static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result, int update_normals) +static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result) { PaintSurfaceData *sData = surface->data; @@ -1531,10 +1566,6 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Deri mvert[i].co[2] -= normal[2]*val; } } - else return; - - if (update_normals) - CDDM_calc_normals(result); } /* @@ -1549,7 +1580,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData if(pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) { DynamicPaintSurface *surface = pmd->canvas->surfaces.first; - pmd->canvas->flags &= ~MOD_DPAINT_PREVIEW_READY; + int update_normals = 0; /* loop through surfaces */ for (; surface; surface=surface->next) { @@ -1589,11 +1620,11 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData if (col) { #pragma omp parallel for schedule(static) for (i=0; i<numOfFaces; i++) { - int j=0; + int j = (mface[i].v4) ? 4 : 3; Material *material = give_current_material(ob, mface[i].mat_nr+1); - for (; j<((mface[i].v4)?4:3); j++) { - int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4; + while (j--) { + int index = *((&mface[i].v1)+j); if (surface->preview_id == MOD_DPAINT_SURFACE_PREV_PAINT) { float c[3]; @@ -1620,13 +1651,12 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData } else { col[i*4+j].a = 255; - col[i*4+j].r = FTOCHAR(pPoint[index].wetness); - col[i*4+j].g = FTOCHAR(pPoint[index].wetness); + col[i*4+j].r = + col[i*4+j].g = col[i*4+j].b = FTOCHAR(pPoint[index].wetness); } } } - pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY; } } @@ -1642,9 +1672,9 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData if (col) { #pragma omp parallel for schedule(static) for (i=0; i<numOfFaces; i++) { - int j=0; - for (; j<((mface[i].v4)?4:3); j++) { - int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4; + int j = (mface[i].v4) ? 4 : 3; + while (j--) { + int index = *((&mface[i].v1)+j); index *= 4; col[i*4+j].a = FTOCHAR(fcolor[index+3]); @@ -1666,13 +1696,12 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData if (col) { #pragma omp parallel for schedule(static) for (i=0; i<numOfFaces; i++) { - int j=0; - - for (; j<((mface[i].v4)?4:3); j++) { - int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4; + int j = (mface[i].v4) ? 4 : 3; + while (j--) { + int index = *((&mface[i].v1)+j); col[i*4+j].a = 255; - col[i*4+j].r = FTOCHAR(pPoint[index].wetness); - col[i*4+j].g = FTOCHAR(pPoint[index].wetness); + col[i*4+j].r = + col[i*4+j].g = col[i*4+j].b = FTOCHAR(pPoint[index].wetness); } } @@ -1687,29 +1716,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData if (surface->flags & MOD_DPAINT_PREVIEW) { /* Save preview results to weight layer, to be * able to share same drawing methods */ - MFace *mface = result->getFaceArray(result); - int numOfFaces = result->getNumFaces(result); - int i; - MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL); - if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces); - - if (col) { - #pragma omp parallel for schedule(static) - for (i=0; i<numOfFaces; i++) { - float temp_color[3]; - int j=0; - for (; j<((mface[i].v4)?4:3); j++) { - int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4; - - weight_to_rgb(temp_color, weight[index]); - col[i*4+j].r = FTOCHAR(temp_color[2]); - col[i*4+j].g = FTOCHAR(temp_color[1]); - col[i*4+j].b = FTOCHAR(temp_color[0]); - col[i*4+j].a = 255; - } - } - pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY; - } + DM_update_weight_mcol(ob, result, 0, weight, 0, NULL); } /* apply weights into a vertex group, if doesnt exists add a new layer */ @@ -1748,14 +1755,20 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData normal_short_to_float_v3(normal, mvert[i].no); madd_v3_v3fl(mvert[i].co, normal, wPoint[i].height); } - CDDM_calc_normals(result); + update_normals = 1; } /* displace */ - dynamicPaint_applySurfaceDisplace(surface, result, 1); + if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) { + dynamicPaint_applySurfaceDisplace(surface, result); + update_normals = 1; + } } } } + + if (update_normals) + CDDM_calc_normals(result); } /* make a copy of dm to use as brush data */ if (pmd->brush) { @@ -1877,7 +1890,8 @@ struct DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scen * px,py : origin pixel x and y * n_index : lookup direction index (use neighX,neighY to get final index) */ -static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh *dm, char *uvname, int w, int h, int px, int py, int n_index) +static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh *dm, + const char *uvname, int w, int h, int px, int py, int n_index) { /* Note: Current method only uses polygon edges to detect neighbouring pixels. * -> It doesn't always lead to the optimum pixel but is accurate enough @@ -1892,8 +1906,8 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh x = px + neighX[n_index]; y = py + neighY[n_index]; - if (x<0 || x>=w) return -1; - if (y<0 || y>=h) return -1; + if (x<0 || x>=w) return OUT_OF_TEXTURE; + if (y<0 || y>=h) return OUT_OF_TEXTURE; tPoint = &tempPoints[x+w*y]; /* UV neighbour */ cPoint = &tempPoints[px+w*py]; /* Origin point */ @@ -2006,8 +2020,8 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh } } - /* If none found return -1 */ - if (target_face == -1) return -1; + /* If none found pixel is on mesh edge */ + if (target_face == -1) return ON_MESH_EDGE; /* * If target face is connected in UV space as well, just use original index @@ -2045,15 +2059,15 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh final_pixel[1] = (int)floor(pixel[1]); /* If current pixel uv is outside of texture */ - if (final_pixel[0] < 0 || final_pixel[0] >= w) return -1; - if (final_pixel[1] < 0 || final_pixel[1] >= h) return -1; + if (final_pixel[0] < 0 || final_pixel[0] >= w) return OUT_OF_TEXTURE; + if (final_pixel[1] < 0 || final_pixel[1] >= h) return OUT_OF_TEXTURE; final_index = final_pixel[0] + w * final_pixel[1]; /* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */ - if (final_index == (px+w*py)) return -1; + if (final_index == (px+w*py)) return NOT_FOUND; /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */ - if (tempPoints[final_index].face_index != target_face) return -1; + if (tempPoints[final_index].face_index != target_face) return NOT_FOUND; /* * If final point is an "edge pixel", use it's "real" neighbour instead @@ -2079,7 +2093,7 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) int ty; int w,h; int numOfFaces; - char uvname[32]; + char uvname[MAX_CUSTOMDATA_LAYER_NAME]; int active_points = 0; int error = 0; @@ -2435,11 +2449,14 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) * If not found, -1 is returned */ int n_target = dynamicPaint_findNeighbourPixel(tempPoints, dm, uvname, w, h, tx, ty, i); - if (n_target != -1) { + if (n_target >= 0) { ed->n_target[n_pos] = final_index[n_target]; ed->n_num[final_index[index]]++; n_pos++; } + else if (n_target == ON_MESH_EDGE || n_target == OUT_OF_TEXTURE) { + ed->flags[final_index[index]] |= ADJ_ON_MESH_EDGE; + } } } } @@ -2573,14 +2590,8 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char* filenam if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { PaintPoint *point = &((PaintPoint*)sData->type_data)[index]; - ibuf->rect_float[pos] = point->color[0]; - ibuf->rect_float[pos+1] = point->color[1]; - ibuf->rect_float[pos+2] = point->color[2]; - /* mix wet layer */ - if (point->e_alpha) mixColors(&ibuf->rect_float[pos], point->alpha, point->e_color, point->e_alpha); - - /* use highest alpha */ - ibuf->rect_float[pos+3] = (point->e_alpha > point->alpha) ? point->e_alpha : point->alpha; + /* blend wet and dry layers */ + blendColors(point->color, point->alpha, point->e_color, point->e_alpha, &ibuf->rect_float[pos]); /* Multiply color by alpha if enabled */ if (surface->flags & MOD_DPAINT_MULALPHA) { @@ -2911,7 +2922,13 @@ static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned float paint[3], float influence, float depth, float vel_factor, float timescale) { PaintSurfaceData *sData = surface->data; - float strength = influence * brush->alpha; + float strength; + + /* apply influence scale */ + influence *= surface->influence_scale; + depth *= surface->influence_scale; + + strength = influence * brush->alpha; CLAMP(strength, 0.0f, 1.0f); /* Sample velocity colorband if required */ @@ -2990,12 +3007,12 @@ static void dynamicPaint_updatePointData(DynamicPaintSurface *surface, unsigned } /* checks whether surface and brush bounds intersect depending on brush type */ -static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush) +static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush, float brush_radius) { if (brush->collision == MOD_DPAINT_COL_VOLUME) return boundsIntersect(b1, b2); else if (brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) - return boundsIntersectDist(b1, b2, brush->paint_distance); + return boundsIntersectDist(b1, b2, brush_radius); else return 1; } @@ -3122,6 +3139,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, { BVHTreeFromMesh treeData = {0}; float avg_brushNor[3] = {0.0f}; + float brush_radius = brush->paint_distance * surface->radius_scale; int numOfVerts; int ii; Bounds3D mesh_bb = {0}; @@ -3139,8 +3157,8 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, mul_m4_v3(brushOb->obmat, mvert[ii].co); boundInsert(&mesh_bb, mvert[ii].co); - /* for project brush calculate average normal */ - if (brush->collision & MOD_DPAINT_COL_DIST && brush->flags & MOD_DPAINT_PROX_PROJECT) { + /* for proximity project calculate average normal */ + if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) { float nor[3]; normal_short_to_float_v3(nor, mvert[ii].no); mul_mat3_m4_v3(brushOb->obmat, nor); @@ -3150,7 +3168,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, } } - if (brush->collision & MOD_DPAINT_COL_DIST && brush->flags & MOD_DPAINT_PROX_PROJECT) { + if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) { mul_v3_fl(avg_brushNor, 1.0f/(float)numOfVerts); /* instead of null vector use positive z */ if (!(MIN3(avg_brushNor[0],avg_brushNor[1],avg_brushNor[2]))) @@ -3160,7 +3178,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, } /* check bounding box collision */ - if(grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush)) + if(grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush, brush_radius)) /* Build a bvh tree from transformed vertices */ if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 8)) { @@ -3172,7 +3190,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, int id; /* check grid cell bounding box */ - if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush)) + if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush, brush_radius)) continue; /* loop through cell points and process brush */ @@ -3233,7 +3251,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, hit.index = -1; hit.dist = 9999; nearest.index = -1; - nearest.dist = brush->paint_distance * brush->paint_distance; /* find_nearest uses squared distance */ + nearest.dist = brush_radius * brush_radius; /* find_nearest uses squared distance */ /* Check volume collision */ if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST) @@ -3291,9 +3309,9 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, if (inner_proximity && !hit_found) continue; /* If pure distance proximity, find the nearest point on the mesh */ - if (brush->collision != MOD_DPAINT_COL_DIST || !(brush->flags & MOD_DPAINT_PROX_PROJECT)) { + if (!(brush->flags & MOD_DPAINT_PROX_PROJECT)) { if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) { - proxDist = sqrt(nearest.dist); + proxDist = sqrtf(nearest.dist); copy_v3_v3(hitCo, nearest.co); hQuad = (nearest.no[0] == 1.0f); face = nearest.index; @@ -3313,7 +3331,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, proj_ray[2] = 1.0f; } hit.index = -1; - hit.dist = brush->paint_distance; + hit.dist = brush_radius; /* Do a face normal directional raycast, and use that distance */ if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, proj_ray, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1) @@ -3326,8 +3344,8 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, } /* If a hit was found, calculate required values */ - if (proxDist >= 0.0f && proxDist <= brush->paint_distance) { - proximity_factor = proxDist / brush->paint_distance; + if (proxDist >= 0.0f && proxDist <= brush_radius) { + proximity_factor = proxDist / brush_radius; CLAMP(proximity_factor, 0.0f, 1.0f); if (!inner_proximity) proximity_factor = 1.0f - proximity_factor; @@ -3513,8 +3531,8 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, int invalidParticles = 0; int p = 0; - float solidradius = (brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius; - float smooth = brush->particle_smooth; + float solidradius = surface->radius_scale*((brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius); + float smooth = brush->particle_smooth*surface->radius_scale; float range = solidradius + smooth; float particle_timestep = 0.04f * part->timetweak; @@ -3534,7 +3552,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, /* Proceed only if particle is active */ if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; - else if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue; + else if(pa->flag & PARS_UNEXIST) continue; /* for debug purposes check if any NAN particle proceeds * For some reason they get past activity check, this should rule most of them out */ @@ -3743,6 +3761,7 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale) { int index; + float brush_radius = brush->paint_distance * surface->radius_scale; PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; Vec3f brushVel; @@ -3760,13 +3779,13 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po float colorband[4] = {0.0f}; float strength; - if (distance>brush->paint_distance) continue; + if (distance > brush_radius) continue; /* Smooth range or color ramp */ if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH || brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP) { - strength = 1.0f - distance / brush->paint_distance; + strength = 1.0f - distance / brush_radius; CLAMP(strength, 0.0f, 1.0f); } else strength = 1.0f; @@ -3831,8 +3850,8 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || surface->type == MOD_DPAINT_SURFACE_T_WAVE) { /* get displace depth */ - float disp_intersect = (1.0f - sqrtf((brush->paint_distance-distance) / brush->paint_distance)) * brush->paint_distance; - depth = (brush->paint_distance - disp_intersect) / bData->bNormal[index].normal_scale; + float disp_intersect = (1.0f - sqrtf((brush_radius-distance) / brush_radius)) * brush_radius; + depth = (brush_radius - disp_intersect) / bData->bNormal[index].normal_scale; if (depth<0.0f) depth = 0.0f; } dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale); @@ -3846,14 +3865,13 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po /***************************** Dynamic Paint Step / Baking ******************************/ /* -* Calculate current frame neighbouring point distances -* and direction vectors +* Calculate current frame distances and directions for adjacency data */ -static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int force_init) +static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, int force_init) { PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; - BakeNeighPoint *bNeighs; + BakeAdjPoint *bNeighs; PaintAdjData *adj_data = sData->adj_data; Vec3f *realCoord = bData->realCoord; int index; @@ -3861,7 +3879,7 @@ static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int if ((!surface_usesAdjDistance(surface) && !force_init) || !sData->adj_data) return; if (bData->bNeighs) MEM_freeN(bData->bNeighs); - bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets*sizeof(struct BakeNeighPoint),"PaintEffectBake"); + bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets*sizeof(struct BakeAdjPoint),"PaintEffectBake"); if (!bNeighs) return; #pragma omp parallel for schedule(static) @@ -3900,7 +3918,7 @@ static void dynamicPaint_prepareNeighbourData(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]) { - BakeNeighPoint *bNeighs = sData->bData->bNeighs; + BakeAdjPoint *bNeighs = sData->bData->bNeighs; int numOfNeighs = sData->adj_data->n_num[index]; int i; @@ -3935,7 +3953,7 @@ void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, floa if (closest_id[1] != -1) { float force_proj[3]; float tangent[3]; - float neigh_diff = acos(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir)); + float neigh_diff = acosf(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir)); float force_intersect; float temp; @@ -3969,7 +3987,7 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus { PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; - BakeNeighPoint *bNeighs = sData->bData->bNeighs; + BakeAdjPoint *bNeighs = sData->bData->bNeighs; int index, steps, step; float eff_scale, max_velocity = 0.0f; @@ -4007,7 +4025,6 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus if (n_index != -1 && closest_d[i]>0.0f) { float dir_dot = closest_d[i], dir_factor; float speed_scale = eff_scale*smudge_str/bNeighs[n_index].dist; - float mix; PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]]; /* just skip if angle is too extreme */ @@ -4017,13 +4034,11 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus if (dir_factor > brush->smudge_strength) dir_factor = brush->smudge_strength; /* mix new color and alpha */ - mix = dir_factor*pPoint->alpha; - if (mix) mixColors(ePoint->color, ePoint->alpha, pPoint->color, mix); + mixColors(ePoint->color, ePoint->alpha, pPoint->color, pPoint->alpha, dir_factor); ePoint->alpha = ePoint->alpha*(1.0f-dir_factor) + pPoint->alpha*dir_factor; /* smudge "wet layer" */ - mix = dir_factor*pPoint->e_alpha; - if (mix) mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, mix); + mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, pPoint->e_alpha, dir_factor); ePoint->e_alpha = ePoint->e_alpha*(1.0f-dir_factor) + pPoint->e_alpha*dir_factor; pPoint->wetness *= (1.0f-dir_factor); } @@ -4040,7 +4055,7 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s { double average_force = 0.0f; float shrink_speed=0.0f, spread_speed=0.0f; - float fastest_effect; + float fastest_effect, avg_dist; int steps; PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; @@ -4117,9 +4132,10 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s shrink_speed = surface->shrink_speed; fastest_effect = MAX3(spread_speed, shrink_speed, average_force); + avg_dist = bData->average_dist*CANVAS_REL_SIZE/getSurfaceDimension(sData); - steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/bData->average_dist*timescale); - CLAMP(steps, 1, 14); + steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/avg_dist*timescale); + CLAMP(steps, 1, 20); return steps; } @@ -4130,7 +4146,8 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force, PaintPoint *prevPoint, float timescale, float steps) { PaintSurfaceData *sData = surface->data; - BakeNeighPoint *bNeighs = sData->bData->bNeighs; + BakeAdjPoint *bNeighs = sData->bData->bNeighs; + float distance_scale = getSurfaceDimension(sData)/CANVAS_REL_SIZE; int index; timescale /= steps; @@ -4140,7 +4157,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force * Spread Effect */ if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD) { - float eff_scale = EFF_MOVEMENT_PER_FRAME*surface->spread_speed*timescale; + float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*surface->spread_speed*timescale; /* Copy current surface to the previous points array to read unmodified values */ memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint)); @@ -4150,7 +4167,6 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force { int i; int numOfNeighs = sData->adj_data->n_num[index]; - float totalAlpha = 0.0f; PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index]; /* Only reads values from the surface copy (prevPoint[]), @@ -4159,39 +4175,23 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force /* Loop through neighbouring points */ for (i=0; i<numOfNeighs; i++) { int n_index = sData->adj_data->n_index[index]+i; - float w_factor, alphaAdd = 0.0f; + float w_factor; PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]]; float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist; - float color_mix = (MIN2(ePoint->wetness, pPoint->wetness))*0.25f*surface->color_spread_speed; - - totalAlpha += ePoint->e_alpha; + float color_mix = (MIN3(ePoint->wetness, pPoint->wetness, 1.0f))*0.25f*surface->color_spread_speed; /* do color mixing */ - if (color_mix > MIN_WETNESS) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, color_mix); - - /* Check if neighbouring point has higher wetness, - * if so, add it's wetness to this point as well*/ - if (ePoint->wetness <= pPoint->wetness) continue; - w_factor = ePoint->wetness/numOfNeighs * (ePoint->wetness - pPoint->wetness) * speed_scale; - if (w_factor <= MIN_WETNESS) continue; - - if (ePoint->e_alpha > pPoint->e_alpha) { - alphaAdd = ePoint->e_alpha/numOfNeighs * (ePoint->wetness*ePoint->e_alpha - pPoint->wetness*pPoint->e_alpha) * speed_scale; - } - - /* mix new color */ - mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, w_factor); + if (color_mix) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, color_mix); - pPoint->e_alpha += alphaAdd; - pPoint->wetness += w_factor; + /* Only continue if surrounding point has higher wetness */ + if (ePoint->wetness<pPoint->wetness || ePoint->wetness<MIN_WETNESS) continue; - if (pPoint->e_alpha > 1.0f) pPoint->e_alpha = 1.0f; - } + w_factor = 1.0f/numOfNeighs * MIN2(ePoint->wetness, 1.0f) * speed_scale; + CLAMP(w_factor, 0.0f, 1.0f); - /* For antialiasing sake, don't let alpha go much higher than average alpha of neighbours */ - if (pPoint->e_alpha > (totalAlpha/numOfNeighs+0.25f)) { - pPoint->e_alpha = (totalAlpha/numOfNeighs+0.25f); - if (pPoint->e_alpha>1.0f) pPoint->e_alpha = 1.0f; + /* mix new wetness and color */ + pPoint->wetness = (1.0f-w_factor)*pPoint->wetness + w_factor*ePoint->wetness; + pPoint->e_alpha = mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, w_factor); } } } @@ -4200,7 +4200,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force * Shrink Effect */ if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK) { - float eff_scale = EFF_MOVEMENT_PER_FRAME*surface->shrink_speed*timescale; + float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*surface->shrink_speed*timescale; /* Copy current surface to the previous points array to read unmodified values */ memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint)); @@ -4250,7 +4250,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force */ if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force) { - float eff_scale = EFF_MOVEMENT_PER_FRAME*timescale/2.0f; + float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*timescale/2.0f; /* Copy current surface to the previous points array to read unmodified values */ memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint)); @@ -4263,8 +4263,9 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force float closest_d[2]; /* adjust drip speed depending on wetness */ - float w_factor = pPoint_prev->wetness*0.5f - 0.025f; + float w_factor = pPoint_prev->wetness - 0.025f; if (w_factor <= 0) continue; + CLAMP(w_factor, 0.0f, 1.0f); /* get force affect points */ surface_determineForceTargetPoints(sData, index, &force[index*4], closest_d, closest_id); @@ -4273,48 +4274,45 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force for (i=0; i<2; i++) { int n_index = closest_id[i]; if (n_index != -1 && closest_d[i]>0.0f) { - float dir_dot = closest_d[i], dir_factor; + float dir_dot = closest_d[i], dir_factor, a_factor; float speed_scale = eff_scale*force[index*4+3]/bNeighs[n_index].dist; PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]]; + float e_wet = ePoint->wetness; /* just skip if angle is too extreme */ if (dir_dot <= 0.0f) continue; - dir_factor = dir_dot * speed_scale * w_factor; - if (dir_factor > (0.5f/steps)) dir_factor = (0.5f/steps); + dir_factor = dir_dot * MIN2(speed_scale, 1.0f) * w_factor; + if (dir_factor > 0.5f) dir_factor = 0.5f; - /* mix new color */ - if (dir_factor) mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, dir_factor); - - ePoint->e_alpha += dir_factor; + /* mix new wetness*/ ePoint->wetness += dir_factor; - if (ePoint->e_alpha > 1.0f) ePoint->e_alpha = 1.0f; + CLAMP(ePoint->wetness, 0.0f, MAX_WETNESS); + + /* mix new color */ + a_factor = dir_factor / pPoint_prev->wetness; + CLAMP(a_factor, 0.0f, 1.0f); + mixColors(ePoint->e_color, ePoint->e_alpha, pPoint_prev->e_color, pPoint_prev->e_alpha, a_factor); + /* dripping is supposed to preserve alpha level */ + if (pPoint_prev->e_alpha > ePoint->e_alpha) { + ePoint->e_alpha += a_factor * pPoint_prev->e_alpha; + if (ePoint->e_alpha > pPoint_prev->e_alpha) + ePoint->e_alpha = pPoint_prev->e_alpha; + } - /* and decrease paint wetness on current point */ - pPoint->wetness -= dir_factor; + /* decrease paint wetness on current point */ + pPoint->wetness -= (ePoint->wetness - e_wet); + CLAMP(pPoint->wetness, 0.0f, MAX_WETNESS); } } } - - /* Keep values within acceptable range */ - #pragma omp parallel for schedule(static) - for (index = 0; index < sData->total_points; index++) - { - PaintPoint *cPoint = &((PaintPoint*)sData->type_data)[index]; - - if (cPoint->e_alpha > 1.0f) cPoint->e_alpha=1.0f; - if (cPoint->wetness > 2.0f) cPoint->wetness=2.0f; - - if (cPoint->e_alpha < 0.0f) cPoint->e_alpha=0.0f; - if (cPoint->wetness < 0.0f) cPoint->wetness=0.0f; - } } } void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale) { PaintSurfaceData *sData = surface->data; - BakeNeighPoint *bNeighs = sData->bData->bNeighs; + BakeAdjPoint *bNeighs = sData->bData->bNeighs; int index; int steps, ss; float dt, min_dist, damp_factor; @@ -4322,7 +4320,7 @@ void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale) double average_dist = 0.0f; Bounds3D *mb = &sData->bData->mesh_bounds; float canvas_size = MAX3((mb->max[0]-mb->min[0]), (mb->max[1]-mb->min[1]), (mb->max[2]-mb->min[2])); - float wave_scale = WAVE_INIT_SIZE/canvas_size; + float wave_scale = CANVAS_REL_SIZE/canvas_size; /* allocate memory */ PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points*sizeof(PaintWavePoint), "Temp previous points for wave simulation"); @@ -4435,48 +4433,53 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index]; /* drying */ - if (pPoint->wetness >= MIN_WETNESS) { - int i; - float dry_ratio, f_color[4]; - float p_wetness = pPoint->wetness; - VALUE_DISSOLVE(pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG)); - if (pPoint->wetness<0.0f) pPoint->wetness=0.0f; - dry_ratio = pPoint->wetness/p_wetness; + if (surface->flags & MOD_DPAINT_USE_DRYING) { + if (pPoint->wetness >= MIN_WETNESS) { + int i; + float dry_ratio, f_color[4]; + float p_wetness = pPoint->wetness; + VALUE_DISSOLVE(pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG)); + if (pPoint->wetness<0.0f) pPoint->wetness=0.0f; - /* - * Slowly "shift" paint from wet layer to dry layer as it drys: - */ - /* make sure alpha values are within proper range */ - CLAMP(pPoint->alpha, 0.0f, 1.0f); - CLAMP(pPoint->e_alpha, 0.0f, 1.0f); - - /* get current final blended color of these layers */ - blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color); - /* reduce wet layer alpha by dry factor */ - pPoint->e_alpha *= dry_ratio; - - /* now calculate new alpha for dry layer that keeps final blended color unchanged */ - pPoint->alpha = (f_color[3] - pPoint->e_alpha)/(1.0f-pPoint->e_alpha); - /* for each rgb component, calculate a new dry layer color that keeps the final blend color - * with these new alpha values. (wet layer color doesnt change)*/ - if (pPoint->alpha) { - for (i=0; i<3; i++) { - pPoint->color[i] = (f_color[i]*f_color[3] - pPoint->e_color[i]*pPoint->e_alpha)/(pPoint->alpha*(1.0f-pPoint->e_alpha)); + if (pPoint->wetness < surface->color_dry_threshold) { + dry_ratio = pPoint->wetness/p_wetness; + + /* + * Slowly "shift" paint from wet layer to dry layer as it drys: + */ + /* make sure alpha values are within proper range */ + CLAMP(pPoint->alpha, 0.0f, 1.0f); + CLAMP(pPoint->e_alpha, 0.0f, 1.0f); + + /* get current final blended color of these layers */ + blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color); + /* reduce wet layer alpha by dry factor */ + pPoint->e_alpha *= dry_ratio; + + /* now calculate new alpha for dry layer that keeps final blended color unchanged */ + pPoint->alpha = (f_color[3] - pPoint->e_alpha)/(1.0f-pPoint->e_alpha); + /* for each rgb component, calculate a new dry layer color that keeps the final blend color + * with these new alpha values. (wet layer color doesnt change)*/ + if (pPoint->alpha) { + for (i=0; i<3; i++) { + pPoint->color[i] = (f_color[i]*f_color[3] - pPoint->e_color[i]*pPoint->e_alpha)/(pPoint->alpha*(1.0f-pPoint->e_alpha)); + } + } } - } - pPoint->state = DPAINT_PAINT_WET; - } - /* in case of just dryed paint, just mix it to the dry layer and mark it empty */ - else if (pPoint->state > 0) { - float f_color[4]; - blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color); - copy_v3_v3(pPoint->color, f_color); - pPoint->alpha = f_color[3]; - /* clear wet layer */ - pPoint->wetness = 0.0f; - pPoint->e_alpha = 0.0f; - pPoint->state = DPAINT_PAINT_DRY; + pPoint->state = DPAINT_PAINT_WET; + } + /* in case of just dryed paint, just mix it to the dry layer and mark it empty */ + else if (pPoint->state > 0) { + float f_color[4]; + blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color); + copy_v3_v3(pPoint->color, f_color); + pPoint->alpha = f_color[3]; + /* clear wet layer */ + pPoint->wetness = 0.0f; + pPoint->e_alpha = 0.0f; + pPoint->state = DPAINT_PAINT_DRY; + } } if (surface->flags & MOD_DPAINT_DISSOLVE) { @@ -4742,8 +4745,8 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc /* generate surface space partitioning grid */ surfaceGenerateGrid(surface); - /* calculate current frame neighbouring point distances and global dirs */ - dynamicPaint_prepareNeighbourData(surface, 0); + /* calculate current frame adjacency point distances and global dirs */ + dynamicPaint_prepareAdjacencyData(surface, 0); /* Copy current frame vertices to check against in next frame */ copy_m4_m4(bData->prev_obmat, ob->obmat); @@ -4826,7 +4829,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su if (!sData->adj_data) dynamicPaint_initAdjacencyData(surface, 1); if (!bData->bNeighs) - dynamicPaint_prepareNeighbourData(surface, 1); + dynamicPaint_prepareAdjacencyData(surface, 1); } /* update object data on this subframe */ @@ -4924,7 +4927,7 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje /* apply previous displace on derivedmesh if incremental surface */ if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL) - dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm, 0); + dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm); /* update bake data */ dynamicPaint_generateBakeData(surface, scene, cObject); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index a5c8f5c905d..0a80e8a3d56 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -950,6 +950,7 @@ char BKE_imtype_valid_channels(const char imtype) case R_IMF_IMTYPE_MULTILAYER: case R_IMF_IMTYPE_DDS: case R_IMF_IMTYPE_JP2: + case R_IMF_IMTYPE_QUICKTIME: chan_flag |= IMA_CHAN_FLAG_ALPHA; } @@ -1110,9 +1111,9 @@ int BKE_add_image_extension(char *string, const char imtype) if(BLI_testextensie_array(string, imb_ext_image) || (G.have_quicktime && BLI_testextensie_array(string, imb_ext_image_qt))) { return BLI_replace_extension(string, FILE_MAX, extension); - } else { + } + else { return BLI_ensure_extension(string, FILE_MAX, extension); - return TRUE; } } @@ -1168,7 +1169,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d char *name = scene_find_last_marker_name(scene, CFRA); if (name) BLI_strncpy(text, name, sizeof(text)); - else strcpy(text, "<none>"); + else BLI_strncpy(text, "<none>", sizeof(text)); BLI_snprintf(stamp_data->marker, sizeof(stamp_data->marker), do_prefix ? "Marker %s":"%s", text); } else { @@ -1202,14 +1203,14 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d } if (scene->r.stamp & R_STAMP_FRAME) { - char format[32]; + char fmtstr[32]; int digits= 1; if(scene->r.efra>9) digits= 1 + (int) log10(scene->r.efra); - BLI_snprintf(format, sizeof(format), do_prefix ? "Frame %%0%di":"%%0%di", digits); - BLI_snprintf (stamp_data->frame, sizeof(stamp_data->frame), format, scene->r.cfra); + BLI_snprintf(fmtstr, sizeof(fmtstr), do_prefix ? "Frame %%0%di":"%%0%di", digits); + BLI_snprintf (stamp_data->frame, sizeof(stamp_data->frame), fmtstr, scene->r.cfra); } else { stamp_data->frame[0] = '\0'; } @@ -1224,7 +1225,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d if (camera && camera->type == OB_CAMERA) { BLI_snprintf(text, sizeof(text), "%.2f", ((Camera *)camera->data)->lens); } - else strcpy(text, "<none>"); + else BLI_strncpy(text, "<none>", sizeof(text)); BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), do_prefix ? "Lens %s":"%s", text); } else { @@ -1241,7 +1242,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d Sequence *seq= seq_foreground_frame_get(scene, scene->r.cfra); if (seq) BLI_strncpy(text, seq->name+2, sizeof(text)); - else strcpy(text, "<none>"); + else BLI_strncpy(text, "<none>", sizeof(text)); BLI_snprintf(stamp_data->strip, sizeof(stamp_data->strip), do_prefix ? "Strip %s":"%s", text); } else { @@ -1607,7 +1608,7 @@ int BKE_write_ibuf(ImBuf *ibuf, const char *name, ImageFormatData *imf) return(ok); } -/* same as BKE_write_ibuf_as but crappy workaround not to perminantly modify +/* same as BKE_write_ibuf() but crappy workaround not to perminantly modify * _some_, values in the imbuf */ int BKE_write_ibuf_as(ImBuf *ibuf, const char *name, ImageFormatData *imf, const short save_copy) diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index a93d0221cf0..c6cb8c9582a 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -33,7 +33,7 @@ #include "BLI_math_base.h" #include "BLF_api.h" -void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, float color[4]) +void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4]) { int x, y; @@ -41,22 +41,17 @@ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, if(rect_float) { for(y= 0; y<height; y++) { for(x= 0; x<width; x++) { - rect_float[0]= color[0]; - rect_float[1]= color[1]; - rect_float[2]= color[2]; - rect_float[3]= color[3]; + copy_v4_v4(rect_float, color); rect_float+= 4; } } } if(rect) { - char ccol[4]; + unsigned char ccol[4]; + + rgba_float_to_uchar(ccol, color); - ccol[0]= (char)(color[0]*255.0f); - ccol[1]= (char)(color[1]*255.0f); - ccol[2]= (char)(color[2]*255.0f); - ccol[3]= (char)(color[3]*255.0f); for(y= 0; y<height; y++) { for(x= 0; x<width; x++) { diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 00a2de369a3..757d3ddf9ac 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1852,6 +1852,9 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase while(step < tf) { + // damping velocity for artistic reasons + mul_lfvectorS(id->V, id->V, clmd->sim_parms->vel_damping, numverts); + // calculate forces cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, id->M); diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 9890a2629fc..40fe3626848 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -328,9 +328,9 @@ static char *shapekey_adrcodes_to_paths (int adrcode, int *UNUSED(array_index)) /* block will be attached to ID_KE block, and setting that we alter is the 'value' (which sets keyblock.curval) */ // XXX adrcode 0 was dummy 'speed' curve if (adrcode == 0) - sprintf(buf, "speed"); + strcpy(buf, "speed"); else - sprintf(buf, "key_blocks[%d].value", adrcode); + BLI_snprintf(buf, sizeof(buf), "key_blocks[%d].value", adrcode); return buf; } @@ -915,7 +915,7 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co /* note, strings are not escapted and they should be! */ if ((actname && actname[0]) && (constname && constname[0])) { /* Constraint in Pose-Channel */ - sprintf(buf, "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname); + BLI_snprintf(buf, sizeof(buf), "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname); } else if (actname && actname[0]) { if ((blocktype == ID_OB) && strcmp(actname, "Object")==0) { @@ -928,16 +928,16 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co } else { /* Pose-Channel */ - sprintf(buf, "pose.bones[\"%s\"]", actname); + BLI_snprintf(buf, sizeof(buf), "pose.bones[\"%s\"]", actname); } } else if (constname && constname[0]) { /* Constraint in Object */ - sprintf(buf, "constraints[\"%s\"]", constname); + BLI_snprintf(buf, sizeof(buf), "constraints[\"%s\"]", constname); } else if (seq) { /* Sequence names in Scene */ - sprintf(buf, "sequence_editor.sequences_all[\"%s\"]", seq->name+2); + BLI_snprintf(buf, sizeof(buf), "sequence_editor.sequences_all[\"%s\"]", seq->name+2); } else { buf[0]= '\0'; /* empty string */ @@ -954,7 +954,7 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co /* if there was no array index pointer provided, add it to the path */ if (array_index == NULL) { - sprintf(buf, "[\"%d\"]", dummy_index); + BLI_snprintf(buf, sizeof(buf), "[\"%d\"]", dummy_index); BLI_dynstr_append(path, buf); } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index eb7d07a6f7d..b2385a5cdb8 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -377,7 +377,7 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl) if(k1->next==NULL) k[0]=k1; k1=k1->next; } - k1= k[1]; + /* k1= k[1]; */ /* UNUSED */ t[0]= k[0]->pos; t[1]+= dpos; t[2]= k[2]->pos + dpos; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 4c30789db73..5e4d8d24d24 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -462,32 +462,25 @@ void end_latt_deform(Object *ob) so we store in latmat transform from path coord inside object */ typedef struct { - float dmin[3], dmax[3], dscale, dloc[3]; + float dmin[3], dmax[3]; float curvespace[4][4], objectspace[4][4], objectspace3[3][3]; int no_rot_axis; } CurveDeform; -static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd, int dloc) +static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd) { invert_m4_m4(ob->imat, ob->obmat); mult_m4_m4m4(cd->objectspace, ob->imat, par->obmat); invert_m4_m4(cd->curvespace, cd->objectspace); copy_m3_m4(cd->objectspace3, cd->objectspace); - - // offset vector for 'no smear' - if(dloc) { - invert_m4_m4(par->imat, par->obmat); - mul_v3_m4v3(cd->dloc, par->imat, ob->obmat[3]); - } - else { - cd->dloc[0]=cd->dloc[1]=cd->dloc[2]= 0.0f; - } - cd->no_rot_axis= 0; } -/* this makes sure we can extend for non-cyclic. *vec needs 4 items! */ -static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius) /* returns OK */ +/* this makes sure we can extend for non-cyclic. + * + * returns OK: 1/0 + */ +static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius) { Curve *cu= ob->data; BevList *bl; @@ -532,20 +525,18 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, return 0; } - /* for each point, rotate & translate to curve */ - /* use path, since it has constant distances */ - /* co: local coord, result local too */ - /* returns quaternion for rotation, using cd->no_rot_axis */ - /* axis is using another define!!! */ -static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, CurveDeform *cd, float *quatp) +/* for each point, rotate & translate to curve */ +/* use path, since it has constant distances */ +/* co: local coord, result local too */ +/* returns quaternion for rotation, using cd->no_rot_axis */ +/* axis is using another define!!! */ +static int calc_curve_deform(Scene *scene, Object *par, float co[3], + const short axis, CurveDeform *cd, float quat_r[4]) { Curve *cu= par->data; float fac, loc[4], dir[3], new_quat[4], radius; - short /*upflag, */ index; - - index= axis-1; - if(index>2) - index -= 3; /* negative */ + short index; + const int is_neg_axis = (axis > 2); /* to be sure, mostly after file load */ if(cu->path==NULL) { @@ -554,52 +545,24 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C } /* options */ - if(ELEM3(axis, OB_NEGX+1, OB_NEGY+1, OB_NEGZ+1)) { /* OB_NEG# 0-5, MOD_CURVE_POS# 1-6 */ + if (is_neg_axis) { + index = axis - 3; if(cu->flag & CU_STRETCH) fac= (-co[index]-cd->dmax[index])/(cd->dmax[index] - cd->dmin[index]); else - fac= (cd->dloc[index])/(cu->path->totdist) - (co[index]-cd->dmax[index])/(cu->path->totdist); + fac= - (co[index]-cd->dmax[index])/(cu->path->totdist); } else { + index = axis; if(cu->flag & CU_STRETCH) fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]); else - fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist); + fac= + (co[index]-cd->dmin[index])/(cu->path->totdist); } -#if 0 // XXX old animation system - /* we want the ipo to work on the default 100 frame range, because there's no - actual time involved in path position */ - // huh? by WHY!!!!???? - Aligorith - if(cu->ipo) { - fac*= 100.0f; - if(calc_ipo_spec(cu->ipo, CU_SPEED, &fac)==0) - fac/= 100.0; - } -#endif // XXX old animation system - if( where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) { /* returns OK */ float quat[4], cent[3]; -#if 0 // XXX - 2.4x Z-Up, Now use bevel tilt. - if(cd->no_rot_axis) /* set by caller */ - dir[cd->no_rot_axis-1]= 0.0f; - - /* -1 for compatibility with old track defines */ - vec_to_quat( quat,dir, axis-1, upflag); - - /* the tilt */ - if(loc[3]!=0.0) { - normalize_v3(dir); - q[0]= (float)cos(0.5*loc[3]); - fac= (float)sin(0.5*loc[3]); - q[1]= -fac*dir[0]; - q[2]= -fac*dir[1]; - q[3]= -fac*dir[2]; - mul_qt_qtqt(quat, q, quat); - } -#endif - if(cd->no_rot_axis) { /* set by caller */ /* this is not exactly the same as 2.4x, since the axis is having rotation removed rather than @@ -634,9 +597,9 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C /* zero the axis which is not used, * the big block of text above now applies to these 3 lines */ - quat_apply_track(quat, axis-1, (axis==1 || axis==3) ? 1:0); /* up flag is a dummy, set so no rotation is done */ - vec_apply_track(cent, axis-1); - cent[axis < 4 ? axis-1 : axis-4]= 0.0f; + quat_apply_track(quat, axis, (axis == 0 || axis == 2) ? 1:0); /* up flag is a dummy, set so no rotation is done */ + vec_apply_track(cent, axis); + cent[index]= 0.0f; /* scale if enabled */ @@ -650,8 +613,8 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C /* translation */ add_v3_v3v3(co, cent, loc); - if(quatp) - copy_qt_qt(quatp, quat); + if(quat_r) + copy_qt_qt(quat_r, quat); return 1; } @@ -666,6 +629,7 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, int a, flag; CurveDeform cd; int use_vgroups; + const int is_neg_axis = (defaxis > 2); if(cuOb->type != OB_CURVE) return; @@ -674,10 +638,10 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, flag = cu->flag; cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist - init_curve_deform(cuOb, target, &cd, (cu->flag & CU_STRETCH)==0); + init_curve_deform(cuOb, target, &cd); /* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */ - if(defaxis < 3) { + if(is_neg_axis == FALSE) { cd.dmin[0]= cd.dmin[1]= cd.dmin[2]= 0.0f; cd.dmax[0]= cd.dmax[1]= cd.dmax[2]= 1.0f; } @@ -711,10 +675,6 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, if(cu->flag & CU_DEFORM_BOUNDS_OFF) { - /* dummy bounds */ - cd.dmin[0]= cd.dmin[1]= cd.dmin[2]= 0.0f; - cd.dmax[0]= cd.dmax[1]= cd.dmax[2]= 1.0f; - dvert = me->dvert; for(a = 0; a < numVerts; a++, dvert++) { if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); @@ -749,6 +709,7 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, weight= defvert_find_weight(dvert, index); if(weight > 0.0f) { + /* already in 'cd.curvespace', prev for loop */ copy_v3_v3(vec, vertexCos[a]); calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); @@ -776,6 +737,7 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, } for(a = 0; a < numVerts; a++) { + /* already in 'cd.curvespace', prev for loop */ calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL); mul_m4_v3(cd.objectspace, vertexCos[a]); } @@ -787,7 +749,8 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, /* input vec and orco = local coord in armature space */ /* orco is original not-animated or deformed reference point */ /* result written in vec and mat */ -void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, float *orco, float *vec, float mat[][3], int no_rot_axis) +void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, + float orco[3], float vec[3], float mat[][3], int no_rot_axis) { CurveDeform cd; float quat[4]; @@ -797,7 +760,7 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, float *orco return; } - init_curve_deform(cuOb, target, &cd, 0); /* 0 no dloc */ + init_curve_deform(cuOb, target, &cd); cd.no_rot_axis= no_rot_axis; /* option to only rotate for XY, for example */ copy_v3_v3(cd.dmin, orco); @@ -805,7 +768,7 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, float *orco mul_m4_v3(cd.curvespace, vec); - if(calc_curve_deform(scene, cuOb, vec, target->trackflag+1, &cd, quat)) { + if(calc_curve_deform(scene, cuOb, vec, target->trackflag, &cd, quat)) { float qmat[3][3]; quat_to_mat3( qmat,quat); @@ -885,7 +848,7 @@ int object_deform_mball(Object *ob, ListBase *dispbase) static BPoint *latt_bp(Lattice *lt, int u, int v, int w) { - return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv; + return <->def[LT_INDEX(lt, u, v, w)]; } void outside_lattice(Lattice *lt) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index cb1c7dbec5c..795cf75820f 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -991,7 +991,7 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor ID *id; for (i=0, id= lb->first; id; id= id->next, i++) { - char buf[32]; + char numstr[32]; if (nr && id==link) *nr= i+1; @@ -1002,12 +1002,12 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor if ( ((Image *)id)->source==IMA_SRC_VIEWER ) continue; - get_flags_for_id(id, buf); + get_flags_for_id(id, numstr); - BLI_dynstr_append(pupds, buf); + BLI_dynstr_append(pupds, numstr); BLI_dynstr_append(pupds, id->name+2); - BLI_snprintf(buf, sizeof(buf), "%%x%d", i+1); - BLI_dynstr_append(pupds, buf); + BLI_snprintf(numstr, sizeof(numstr), "%%x%d", i+1); + BLI_dynstr_append(pupds, numstr); /* icon */ switch(GS(id->name)) @@ -1017,8 +1017,8 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor case ID_IM: /* fall through */ case ID_WO: /* fall through */ case ID_LA: /* fall through */ - BLI_snprintf(buf, sizeof(buf), "%%i%d", BKE_icon_getid(id) ); - BLI_dynstr_append(pupds, buf); + BLI_snprintf(numstr, sizeof(numstr), "%%i%d", BKE_icon_getid(id) ); + BLI_dynstr_append(pupds, numstr); break; default: break; @@ -1136,10 +1136,12 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) { ID *idtest; int nr= 0, nrtest, a, left_len; - char left[32], leftest[32], in_use[32]; + char in_use[64]; /* use as a boolean array, unrelated to name length */ + + char left[MAX_ID_NAME + 8], leftest[MAX_ID_NAME + 8]; /* make sure input name is terminated properly */ - /* if( strlen(name) > 21 ) name[21]= 0; */ + /* if( strlen(name) > MAX_ID_NAME-3 ) name[MAX_ID_NAME-3]= 0; */ /* removed since this is only ever called from one place - campbell */ while (1) { @@ -1151,20 +1153,20 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) if( idtest == NULL ) return 0; /* we have a dup; need to make a new name */ - /* quick check so we can reuse one of first 32 ids if vacant */ + /* quick check so we can reuse one of first 64 ids if vacant */ memset(in_use, 0, sizeof(in_use)); /* get name portion, number portion ("name.number") */ left_len= BLI_split_name_num(left, &nr, name, '.'); /* if new name will be too long, truncate it */ - if(nr > 999 && left_len > 16) { - left[16]= 0; - left_len= 16; + if(nr > 999 && left_len > (MAX_ID_NAME - 8)) { + left[MAX_ID_NAME - 8]= 0; + left_len= MAX_ID_NAME - 8; } - else if(left_len > 17) { - left[17]= 0; - left_len= 17; + else if(left_len > (MAX_ID_NAME - 7)) { + left[MAX_ID_NAME - 7]= 0; + left_len= MAX_ID_NAME - 7; } for(idtest= lb->first; idtest; idtest= idtest->next) { @@ -1206,11 +1208,11 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) /* otherwise just continue and use a number suffix */ } - if(nr > 999 && left_len > 16) { + if(nr > 999 && left_len > (MAX_ID_NAME - 8)) { /* this would overflow name buffer */ - left[16] = 0; - /* left_len = 16; */ /* for now this isnt used again */ - memcpy(name, left, sizeof(char) * 17); + left[MAX_ID_NAME - 8] = 0; + /* left_len = MAX_ID_NAME - 8; */ /* for now this isnt used again */ + memcpy(name, left, sizeof(char) * (MAX_ID_NAME - 7)); continue; } /* this format specifier is from hell... */ @@ -1245,7 +1247,7 @@ int new_id(ListBase *lb, ID *id, const char *tname) strncpy(name, tname, sizeof(name)-1); - /* if result > 21, strncpy don't put the final '\0' to name. + /* if result > MAX_ID_NAME-3, strncpy don't put the final '\0' to name. * easier to assign each time then to check if its needed */ name[sizeof(name)-1]= 0; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 4fda85a3247..f685d0ec151 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -51,6 +51,7 @@ #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "BLI_bpath.h" +#include "BLI_string.h" #include "BKE_animsys.h" #include "BKE_displist.h" @@ -1614,7 +1615,7 @@ static void calculate_tface_materialname(char *matname, char *newname, int flag) int digits = integer_getdigits(flag); /* clamp the old name, remove the MA prefix and add the .TF.flag suffix e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */ - sprintf(newname, "%.*s.TF.%0*d", MAX_ID_NAME-(digits+5), matname, digits, flag); + BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME-(digits+5), matname, digits, flag); } /* returns -1 if no match */ @@ -1661,8 +1662,8 @@ static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag) short mat_nr= -1; /* new material, the name uses the flag*/ - sprintf(idname, "MAMaterial.TF.%0*d", integer_getdigits(flag), flag); - + BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag); + if ((ma= BLI_findstring(&main->mat, idname+2, offsetof(ID, name)+2))) { mat_nr= mesh_getmaterialnumber(me, ma); /* assign the material to the mesh */ diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 57fc7473860..fe2c10d7091 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -356,7 +356,7 @@ int is_basis_mball(Object *ob) int is_mball_basis_for(Object *ob1, Object *ob2) { int basis1nr, basis2nr; - char basis1name[32], basis2name[32]; + char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME]; BLI_split_name_num(basis1name, &basis1nr, ob1->id.name+2, '.'); BLI_split_name_num(basis2name, &basis2nr, ob2->id.name+2, '.'); @@ -378,7 +378,7 @@ void copy_mball_properties(Scene *scene, Object *active_object) Object *ob; MetaBall *active_mball = (MetaBall*)active_object->data; int basisnr, obnr; - char basisname[32], obname[32]; + char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; BLI_split_name_num(basisname, &basisnr, active_object->id.name+2, '.'); @@ -423,7 +423,7 @@ Object *find_basis_mball(Scene *scene, Object *basis) Object *ob,*bob= basis; MetaElem *ml=NULL; int basisnr, obnr; - char basisname[32], obname[32]; + char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; BLI_split_name_num(basisname, &basisnr, basis->id.name+2, '.'); totelem= 0; @@ -1596,7 +1596,7 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */ float size, totsize, obinv[4][4], obmat[4][4], vec[3]; //float max=0.0; int a, obnr, zero_size=0; - char obname[32]; + char obname[MAX_ID_NAME]; copy_m4_m4(obmat, ob->obmat); /* to cope with duplicators from next_object */ invert_m4_m4(obinv, ob->obmat); @@ -1619,7 +1619,7 @@ float init_meta(Scene *scene, Object *ob) /* return totsize */ else ml= mb->elems.first; } else { - char name[32]; + char name[MAX_ID_NAME]; int nr; BLI_split_name_num(name, &nr, bob->id.name+2, '.'); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 408a141608d..cba92e7a14c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -42,12 +42,12 @@ #include "DNA_meshdata_types.h" #include "DNA_ipo_types.h" +#include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_bpath.h" #include "BLI_editVert.h" #include "BLI_math.h" #include "BLI_edgehash.h" -#include "BLI_utildefines.h" #include "BKE_animsys.h" #include "BKE_main.h" @@ -1248,8 +1248,6 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) mf->flag &= ~ME_SMOOTH; } } - - mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); } void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3]) @@ -1294,11 +1292,11 @@ float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3] { int i, numVerts = me->totvert; float (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos1"); - + if (numVerts_r) *numVerts_r = numVerts; for (i=0; i<numVerts; i++) - VECCOPY(cos[i], me->mvert[i].co); - + copy_v3_v3(cos[i], me->mvert[i].co); + return cos; } @@ -1591,7 +1589,7 @@ int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, mesh_loops_to_mface_corners(fdata, ldata, pdata, lindex, k, i, 3, numTex, numCol, hasWCol); - test_index_face(mf, fdata, totface, 3); + test_index_face(mf, fdata, k, 3); } else { /*sort loop indices to ensure winding is correct*/ @@ -1611,7 +1609,7 @@ int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, mesh_loops_to_mface_corners(fdata, ldata, pdata, lindex, k, i, 4, numTex, numCol, hasWCol); - test_index_face(mf, fdata, totface, 4); + test_index_face(mf, fdata, k, 4); } mf->edcode= 0; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 5a389019519..911d303b4cf 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -142,6 +142,19 @@ int modifier_supportsMapping(ModifierData *md) (mti->flags & eModifierTypeFlag_SupportsMapping)); } +int modifier_isPreview(ModifierData *md) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (!(mti->flags & eModifierTypeFlag_UsesPreview)) + return FALSE; + + if (md->mode & eModifierMode_Realtime) + return TRUE; + + return FALSE; +} + ModifierData *modifiers_findByType(Object *ob, ModifierType type) { ModifierData *md = ob->modifiers.first; @@ -385,6 +398,21 @@ LinkNode *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData return dataMasks; } +ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, int required_mode) +{ + ModifierData *tmp_md = NULL; + + if (required_mode != eModifierMode_Realtime) + return tmp_md; + + /* Find the latest modifier in stack generating preview. */ + for(; md; md = md->next) { + if(modifier_isEnabled(scene, md, required_mode) && modifier_isPreview(md)) + tmp_md = md; + } + return tmp_md; +} + ModifierData *modifiers_getVirtualModifierList(Object *ob) { /* Kinda hacky, but should be fine since we are never @@ -545,6 +573,20 @@ int modifiers_isCorrectableDeformed(Object *ob) return 0; } +/* Check whether the given object has a modifier in its stack that uses WEIGHT_MCOL CD layer + * to preview something... Used by DynamicPaint and WeightVG currently. */ +int modifiers_isPreview(Object *ob) +{ + ModifierData *md = ob->modifiers.first; + + for (; md; md = md->next) { + if (modifier_isPreview(md)) + return TRUE; + } + + return FALSE; +} + int modifiers_indexInObject(Object *ob, ModifierData *md_seek) { int i= 0; diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index ab963f1e78c..c90faa7e0ca 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -257,18 +257,30 @@ typedef struct MovieClipCache { /* regular movie cache */ struct MovieCache *moviecache; - /* cache for stable shot */ - int stable_framenr; - float stable_loc[2], stable_scale, stable_angle; - ImBuf *stableibuf; - int proxy; - short render_flag; + /* cached postprocessed shot */ + struct { + ImBuf *ibuf; + int framenr; + int flag; - /* cache for undistorted shot */ - int undist_framenr; - float principal[2]; - float k1, k2, k3; - ImBuf *undistibuf; + /* cache for undistorted shot */ + float principal[2]; + float k1, k2, k3; + short undistoriton_used; + + int proxy; + short render_flag; + } postprocessed; + + /* cache for stable shot */ + struct { + ImBuf *ibuf; + int framenr; + + float loc[2], scale, angle; + int proxy; + short render_flag; + } stabilized; } MovieClipCache; typedef struct MovieClipImBufCacheKey { @@ -465,111 +477,180 @@ static void real_ibuf_size(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, in } } -static int need_undistorted_cache(MovieClipUser *user, int flag) +static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *distortion, ImBuf *ibuf) +{ + ImBuf *undistibuf; + + /* XXX: because of #27997 do not use float buffers to undistort, + otherwise, undistorted proxy can be darker than it should */ + imb_freerectfloatImBuf(ibuf); + + if(distortion) + undistibuf= BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1); + else + undistibuf= BKE_tracking_undistort(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f); + + if(undistibuf->userflags&IB_RECT_INVALID) { + ibuf->userflags&= ~IB_RECT_INVALID; + IMB_rect_from_float(undistibuf); + } + + IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y); + + return undistibuf; +} + +static int need_undistortion_postprocess(MovieClipUser *user, int flag) { + int result = 0; + /* only full undistorted render can be used as on-fly undistorting image */ - if(flag&MCLIP_USE_PROXY) { - if(user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL || (user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT)==0) - return 0; + if(flag & MCLIP_USE_PROXY) { + result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) && + (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; } - else return 0; - return 1; + return result; +} + +static int need_postprocessed_frame(MovieClipUser *user, int flag, int postprocess_flag) +{ + int result = postprocess_flag; + + result |= need_undistortion_postprocess(user, flag); + + return result; } -static ImBuf *get_undistorted_cache(MovieClip *clip, MovieClipUser *user) +static int check_undistortion_cache_flags(MovieClip *clip) { MovieClipCache *cache= clip->cache; MovieTrackingCamera *camera= &clip->tracking.camera; + + /* check for distortion model changes */ + if(!equals_v2v2(camera->principal, cache->postprocessed.principal)) + return 0; + + if(!equals_v3v3(&camera->k1, &cache->postprocessed.k1)) + return 0; + + return 1; +} + +static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *user, int flag, int postprocess_flag) +{ + MovieClipCache *cache= clip->cache; int framenr= user->framenr; + short proxy= IMB_PROXY_NONE; + int render_flag= 0; - /* no cache or no cached undistorted image */ - if(!clip->cache || !clip->cache->undistibuf) + if(flag&MCLIP_USE_PROXY) { + proxy= rendersize_to_proxy(user, flag); + render_flag= user->render_flag; + } + + /* no cache or no cached postprocessed image */ + if(!clip->cache || !clip->cache->postprocessed.ibuf) return NULL; - /* undistortion happened for other frame */ - if(cache->undist_framenr!=framenr) + /* postprocessing happened for other frame */ + if(cache->postprocessed.framenr != framenr) return NULL; - /* check for distortion model changes */ - if(!equals_v2v2(camera->principal, cache->principal)) + /* cached ibuf used different proxy settings */ + if(cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy) + return NULL; + + if(cache->postprocessed.flag != postprocess_flag) return NULL; - if(!equals_v3v3(&camera->k1, &cache->k1)) + if(need_undistortion_postprocess(user, flag)) { + if(!check_undistortion_cache_flags(clip)) + return NULL; + } + else if(cache->postprocessed.undistoriton_used) return NULL; - IMB_refImBuf(cache->undistibuf); + IMB_refImBuf(cache->postprocessed.ibuf); - return cache->undistibuf; + return cache->postprocessed.ibuf; } -static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *distortion, ImBuf *ibuf) +static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag) { - ImBuf *undistibuf; + MovieClipCache *cache= clip->cache; + MovieTrackingCamera *camera= &clip->tracking.camera; + ImBuf *postproc_ibuf = NULL; - /* XXX: because of #27997 do not use float buffers to undistort, - otherwise, undistorted proxy can be darker than it should */ - imb_freerectfloatImBuf(ibuf); + if(cache->postprocessed.ibuf) + IMB_freeImBuf(cache->postprocessed.ibuf); - if(distortion) - undistibuf= BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1); - else - undistibuf= BKE_tracking_undistort(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f); + cache->postprocessed.framenr= user->framenr; + cache->postprocessed.flag = postprocess_flag; - if(undistibuf->userflags&IB_RECT_INVALID) { - ibuf->userflags&= ~IB_RECT_INVALID; - IMB_rect_from_float(undistibuf); + if(flag&MCLIP_USE_PROXY) { + cache->postprocessed.proxy= rendersize_to_proxy(user, flag); + cache->postprocessed.render_flag= user->render_flag; + } + else { + cache->postprocessed.proxy = IMB_PROXY_NONE; + cache->postprocessed.render_flag = 0; } - IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y); + if(need_undistortion_postprocess(user, flag)) { + copy_v2_v2(cache->postprocessed.principal, camera->principal); + copy_v3_v3(&cache->postprocessed.k1, &camera->k1); + cache->postprocessed.undistoriton_used = 1; + postproc_ibuf= get_undistorted_ibuf(clip, NULL, ibuf); + } + else cache->postprocessed.undistoriton_used = 0; - return undistibuf; -} + if(postprocess_flag) { + int disable_red = postprocess_flag & MOVIECLIP_DISABLE_RED, + disable_green = postprocess_flag & MOVIECLIP_DISABLE_GREEN, + disable_blue = postprocess_flag & MOVIECLIP_DISABLE_BLUE, + grayscale = postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE; -static ImBuf *put_undistorted_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf) -{ - MovieClipCache *cache= clip->cache; - MovieTrackingCamera *camera= &clip->tracking.camera; + if(!postproc_ibuf) + postproc_ibuf = IMB_dupImBuf(ibuf); - copy_v2_v2(cache->principal, camera->principal); - copy_v3_v3(&cache->k1, &camera->k1); - cache->undist_framenr= user->framenr; + if(disable_red || disable_green || disable_blue || grayscale) + BKE_tracking_disable_imbuf_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1); + } - if(cache->undistibuf) - IMB_freeImBuf(cache->undistibuf); + IMB_refImBuf(postproc_ibuf); - cache->undistibuf= get_undistorted_ibuf(clip, NULL, ibuf); + cache->postprocessed.ibuf= postproc_ibuf; - if(cache->stableibuf) { + if(cache->stabilized.ibuf) { /* force stable buffer be re-calculated */ - IMB_freeImBuf(cache->stableibuf); - cache->stableibuf= NULL; + IMB_freeImBuf(cache->stabilized.ibuf); + cache->stabilized.ibuf= NULL; } - IMB_refImBuf(cache->undistibuf); - - return cache->undistibuf; + return postproc_ibuf; } -ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user) +static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int flag, + int postprocess_flag, int cache_flag) { ImBuf *ibuf= NULL; - int framenr= user->framenr; - int cache_undistorted= 0; + int framenr= user->framenr, need_postprocess= 0; /* cache isn't threadsafe itself and also loading of movies can't happen from concurent threads that's why we use lock here */ BLI_lock_thread(LOCK_MOVIECLIP); - /* try to obtain cached undistorted image first */ - if(need_undistorted_cache(user, clip->flag)) { - ibuf= get_undistorted_cache(clip, user); + /* try to obtain cached postprocessed frame first */ + if(need_postprocessed_frame(user, flag, postprocess_flag)) { + ibuf= get_postprocessed_cached_frame(clip, user, flag, postprocess_flag); + if(!ibuf) - cache_undistorted= 1; + need_postprocess= 1; } if(!ibuf) - ibuf= get_imbuf_cache(clip, user, clip->flag); + ibuf= get_imbuf_cache(clip, user, flag); if(!ibuf) { int use_sequence= 0; @@ -579,23 +660,23 @@ ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user) (user->render_size!=MCLIP_PROXY_RENDER_SIZE_FULL); if(clip->source==MCLIP_SRC_SEQUENCE || use_sequence) - ibuf= movieclip_load_sequence_file(clip, user, framenr, clip->flag); + ibuf= movieclip_load_sequence_file(clip, user, framenr, flag); else { - ibuf= movieclip_load_movie_file(clip, user, framenr, clip->flag); + ibuf= movieclip_load_movie_file(clip, user, framenr, flag); } - if(ibuf) - put_imbuf_cache(clip, user, ibuf, clip->flag); + if(ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) + put_imbuf_cache(clip, user, ibuf, flag); } if(ibuf) { clip->lastframe= framenr; real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]); - /* put undistorted frame to cache */ - if(cache_undistorted) { + /* postprocess frame and put to cache */ + if(need_postprocess) { ImBuf *tmpibuf= ibuf; - ibuf= put_undistorted_cache(clip, user, tmpibuf); + ibuf= put_postprocessed_frame_to_cache(clip, user, tmpibuf, flag, postprocess_flag); IMB_freeImBuf(tmpibuf); } } @@ -605,105 +686,113 @@ ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user) return ibuf; } -ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag) +ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user) { - ImBuf *ibuf= NULL; - int framenr= user->framenr; - int cache_undistorted= 0; + return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0); +} - /* cache isn't threadsafe itself and also loading of movies - can't happen from concurent threads that's why we use lock here */ - BLI_lock_thread(LOCK_MOVIECLIP); +ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag, int cache_flag) +{ + return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag); +} - /* try to obtain cached undistorted image first */ - if(need_undistorted_cache(user, flag)) { - ibuf= get_undistorted_cache(clip, user); - if(!ibuf) - cache_undistorted= 1; +ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int postprocess_flag) +{ + return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0); +} + +static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, int framenr) +{ + MovieClipCache *cache = clip->cache; + ImBuf *stableibuf; + float tloc[2], tscale, tangle; + short proxy = IMB_PROXY_NONE; + int render_flag = 0; + + if(clip->flag&MCLIP_USE_PROXY) { + proxy = rendersize_to_proxy(user, clip->flag); + render_flag = user->render_flag; } - ibuf= get_imbuf_cache(clip, user, flag); + /* there's no cached frame or it was calculated for another frame */ + if(!cache->stabilized.ibuf || cache->stabilized.framenr != framenr) + return NULL; - if(!ibuf) { - if(clip->source==MCLIP_SRC_SEQUENCE) { - ibuf= movieclip_load_sequence_file(clip, user, framenr, flag); - } else { - ibuf= movieclip_load_movie_file(clip, user, framenr, flag); - } + /* cached ibuf used different proxy settings */ + if(cache->stabilized.render_flag!=render_flag || cache->stabilized.proxy!=proxy) + return NULL; - if(ibuf) { - int bits= MCLIP_USE_PROXY|MCLIP_USE_PROXY_CUSTOM_DIR; + stableibuf = cache->stabilized.ibuf; - if((flag&bits)==(clip->flag&bits)) - put_imbuf_cache(clip, user, ibuf, clip->flag); - } - } + BKE_tracking_stabilization_data(&clip->tracking, framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); - /* put undistorted frame to cache */ - if(ibuf && cache_undistorted) { - ImBuf *tmpibuf= ibuf; - ibuf= put_undistorted_cache(clip, user, tmpibuf); - IMB_freeImBuf(tmpibuf); + /* check for stabilization parameters */ + if(tscale != cache->stabilized.scale || + tangle != cache->stabilized.angle || + !equals_v2v2(tloc, cache->stabilized.loc)) + { + return NULL; } - BLI_unlock_thread(LOCK_MOVIECLIP); + IMB_refImBuf(stableibuf); - return ibuf; + return stableibuf; } -ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle) +static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int framenr) { - ImBuf *ibuf, *stableibuf= NULL; - int framenr= user->framenr; + MovieClipCache *cache = clip->cache; + ImBuf *stableibuf; + float tloc[2], tscale, tangle; - ibuf= BKE_movieclip_get_ibuf(clip, user); + if(cache->stabilized.ibuf) + IMB_freeImBuf(cache->stabilized.ibuf); - if(!ibuf) - return NULL; + stableibuf = BKE_tracking_stabilize(&clip->tracking, framenr, ibuf, tloc, &tscale, &tangle); - if(clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) { - float tloc[2], tscale, tangle; - short proxy= IMB_PROXY_NONE; - int render_flag= 0; + cache->stabilized.ibuf= stableibuf; - if(clip->flag&MCLIP_USE_PROXY) { - proxy= rendersize_to_proxy(user, clip->flag); - render_flag= user->render_flag; - } + copy_v2_v2(cache->stabilized.loc, tloc); - if(clip->cache->stableibuf && clip->cache->stable_framenr==framenr) { /* there's cached ibuf */ - if(clip->cache->render_flag==render_flag && clip->cache->proxy==proxy) { /* cached ibuf used the same proxy settings */ - stableibuf= clip->cache->stableibuf; + cache->stabilized.scale = tscale; + cache->stabilized.angle = tangle; + cache->stabilized.framenr = framenr; - BKE_tracking_stabilization_data(&clip->tracking, framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); + if(clip->flag&MCLIP_USE_PROXY) { + cache->stabilized.proxy= rendersize_to_proxy(user, clip->flag); + cache->stabilized.render_flag= user->render_flag; + } + else { + cache->stabilized.proxy = IMB_PROXY_NONE; + cache->stabilized.render_flag = 0; + } - /* check for stabilization parameters */ - if(!equals_v2v2(tloc, clip->cache->stable_loc) || tscale!=clip->cache->stable_scale || tangle!=clip->cache->stable_angle) { - stableibuf= NULL; - } - } - } + IMB_refImBuf(stableibuf); - if(!stableibuf) { - if(clip->cache->stableibuf) - IMB_freeImBuf(clip->cache->stableibuf); + return stableibuf; +} - stableibuf= BKE_tracking_stabilize(&clip->tracking, framenr, ibuf, tloc, &tscale, &tangle); +ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle, int postprocess_flag) +{ + ImBuf *ibuf, *stableibuf= NULL; + int framenr= user->framenr; - copy_v2_v2(clip->cache->stable_loc, tloc); - clip->cache->stable_scale= tscale; - clip->cache->stable_angle= tangle; - clip->cache->stable_framenr= framenr; - clip->cache->stableibuf= stableibuf; - clip->cache->proxy= proxy; - clip->cache->render_flag= render_flag; - } + ibuf= BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag); + + if(!ibuf) + return NULL; - IMB_refImBuf(stableibuf); + if(clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) { + MovieClipCache *cache= clip->cache; + + stableibuf= get_stable_cached_frame(clip, user, framenr); - if(loc) copy_v2_v2(loc, tloc); - if(scale) *scale= tscale; - if(angle) *angle= tangle; + if(!stableibuf) + stableibuf= put_stabilized_frame_to_cache(clip, user, ibuf, framenr); + + if(loc) copy_v2_v2(loc, cache->stabilized.loc); + if(scale) *scale= cache->stabilized.scale; + if(angle) *angle= cache->stabilized.angle; } else { if(loc) zero_v2(loc); if(scale) *scale= 1.0f; @@ -786,11 +875,11 @@ static void free_buffers(MovieClip *clip) if(clip->cache) { IMB_moviecache_free(clip->cache->moviecache); - if(clip->cache->stableibuf) - IMB_freeImBuf(clip->cache->stableibuf); + if(clip->cache->postprocessed.ibuf) + IMB_freeImBuf(clip->cache->postprocessed.ibuf); - if(clip->cache->undistibuf) - IMB_freeImBuf(clip->cache->undistibuf); + if(clip->cache->stabilized.ibuf) + IMB_freeImBuf(clip->cache->stabilized.ibuf); MEM_freeN(clip->cache); clip->cache= NULL; @@ -860,7 +949,9 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip undist_marker.pos[1]/= height*aspy; } - tmpibuf= BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 1, 1, scopes->track_pos, NULL); + /* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */ + tmpibuf= BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */, + 1 /* anchor */, scopes->track_pos, NULL); if(tmpibuf->rect_float) IMB_rect_from_float(tmpibuf); @@ -891,7 +982,7 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i { char name[FILE_MAX]; int quality, rectx, recty; - int size= size= rendersize_to_number(proxy_render_size); + int size= rendersize_to_number(proxy_render_size); ImBuf *scaleibuf; get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name); @@ -931,7 +1022,7 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct Movi user.render_flag= 0; user.render_size= MCLIP_PROXY_RENDER_SIZE_FULL; - ibuf= BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag); + ibuf= BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP); if(ibuf) { ImBuf *tmpibuf= ibuf; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 458fb895b64..3fb49d508cd 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1616,7 +1616,7 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); - if(!mdisps || !mmd) return; + if(!mdisps || !mmd || !mmd->totlvl) return; /* we need derived mesh created from highest resolution */ high_mmd= *mmd; diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index fd184b9def4..12f403d028f 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1448,9 +1448,17 @@ void BKE_nla_validate_state (AnimData *adt) */ // TODO: 1 solution is to tie this in with auto-blending... if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) { + /* 1) First strip must be set to extend hold, otherwise, stuff before acts dodgy + * 2) Only overwrite extend mode if *not* changing it will most probably result in + * occlusion problems, which will occur iff + * - blendmode = REPLACE + * - all channels the same (this is fiddly to test, so is currently assumed) + * + * Should fix problems such as [#29869] + */ if (strip == fstrip) strip->extendmode= NLASTRIP_EXTEND_HOLD; - else + else if (strip->blendmode == NLASTRIP_MODE_REPLACE) strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD; } } @@ -1542,6 +1550,34 @@ short BKE_nla_tweakmode_enter (AnimData *adt) break; } } + + /* There are situations where we may have multiple strips selected and we want to enter tweakmode on all + * of those at once. Usually in those cases, it will usually just be a single strip per AnimData. + * In such cases, compromise and take the last selected track and/or last selected strip [#28468] + */ + if (activeTrack == NULL) { + /* try last selected track for active strip */ + for (nlt = adt->nla_tracks.last; nlt; nlt = nlt->prev) { + if (nlt->flag & NLATRACK_SELECTED) { + /* assume this is the active track */ + activeTrack= nlt; + + /* try to find active strip */ + activeStrip= BKE_nlastrip_find_active(nlt); + break; + } + } + } + if ((activeTrack) && (activeStrip == NULL)) { + /* no active strip in active or last selected track; compromise for first selected (assuming only single)... */ + for (strip = activeTrack->strips.first; strip; strip= strip->next) { + if (strip->flag & (NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_ACTIVE)) { + activeStrip = strip; + break; + } + } + } + if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) { if (G.f & G_DEBUG) { printf("NLA tweakmode enter - neither active requirement found \n"); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 9befb46674f..1c7fe3b2cea 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -159,7 +159,6 @@ void ntreeInitTypes(bNodeTree *ntree) static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char *name, int type) { - bNodeSocketType *stype= ntreeGetSocketType(type); bNodeSocket *sock; sock= MEM_callocN(sizeof(bNodeSocket), "sock"); @@ -169,8 +168,8 @@ static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char sock->type= type; sock->storage = NULL; - if (stype->value_structsize > 0) - sock->default_value = MEM_callocN(stype->value_structsize, "default socket value"); + sock->default_value = node_socket_make_default_value(type); + node_socket_init_default_value(type, sock->default_value); return sock; } @@ -216,8 +215,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock) BLI_remlink(&node->inputs, sock); BLI_remlink(&node->outputs, sock); - if (sock->default_value) - MEM_freeN(sock->default_value); + node_socket_free_default_value(sock->type, sock->default_value); MEM_freeN(sock); node->update |= NODE_UPDATE; @@ -236,13 +234,10 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node) } for (sock=node->inputs.first; sock; sock=sock->next) - if (sock->default_value) - MEM_freeN(sock->default_value); + node_socket_free_default_value(sock->type, sock->default_value); BLI_freelistN(&node->inputs); for (sock=node->outputs.first; sock; sock=sock->next) - if (sock->default_value) - MEM_freeN(sock->default_value); - + node_socket_free_default_value(sock->type, sock->default_value); BLI_freelistN(&node->outputs); node->update |= NODE_UPDATE; @@ -396,7 +391,8 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) oldsock->new_sock= sock; sock->stack_index= 0; - sock->default_value = (oldsock->default_value ? MEM_dupallocN(oldsock->default_value) : NULL); + sock->default_value = node_socket_make_default_value(oldsock->type); + node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value); /* XXX some compositor node (e.g. image, render layers) still store * some persistent buffer data here, need to clear this to avoid dangling pointers. @@ -410,7 +406,8 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) oldsock->new_sock= sock; sock->stack_index= 0; - sock->default_value = (oldsock->default_value ? MEM_dupallocN(oldsock->default_value) : NULL); + sock->default_value = node_socket_make_default_value(oldsock->type); + node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value); /* XXX some compositor node (e.g. image, render layers) still store * some persistent buffer data here, need to clear this to avoid dangling pointers. @@ -658,13 +655,15 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree) for(gsock= newtree->inputs.first, oldgsock= ntree->inputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) { oldgsock->new_sock= gsock; gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); - gsock->default_value = (oldgsock->default_value ? MEM_dupallocN(oldgsock->default_value) : NULL); + gsock->default_value = node_socket_make_default_value(oldgsock->type); + node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value); } BLI_duplicatelist(&newtree->outputs, &ntree->outputs); for(gsock= newtree->outputs.first, oldgsock= ntree->outputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) { oldgsock->new_sock= gsock; gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); - gsock->default_value = (oldgsock->default_value ? MEM_dupallocN(oldgsock->default_value) : NULL); + gsock->default_value = node_socket_make_default_value(oldgsock->type); + node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value); } /* copy links */ @@ -790,16 +789,11 @@ void nodeAddToPreview(bNode *node, float *col, int x, int y, int do_manage) unsigned char *tar= preview->rect+ 4*((preview->xsize*y) + x); if(do_manage) { - tar[0]= FTOCHAR(linearrgb_to_srgb(col[0])); - tar[1]= FTOCHAR(linearrgb_to_srgb(col[1])); - tar[2]= FTOCHAR(linearrgb_to_srgb(col[2])); + linearrgb_to_srgb_uchar4(tar, col); } else { - tar[0]= FTOCHAR(col[0]); - tar[1]= FTOCHAR(col[1]); - tar[2]= FTOCHAR(col[2]); + rgba_float_to_uchar(tar, col); } - tar[3]= FTOCHAR(col[3]); } //else printf("prv out bound x y %d %d\n", x, y); } @@ -868,14 +862,12 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) for (sock=node->inputs.first; sock; sock = nextsock) { nextsock = sock->next; - if (sock->default_value) - MEM_freeN(sock->default_value); + node_socket_free_default_value(sock->type, sock->default_value); MEM_freeN(sock); } for (sock=node->outputs.first; sock; sock = nextsock) { nextsock = sock->next; - if (sock->default_value) - MEM_freeN(sock->default_value); + node_socket_free_default_value(sock->type, sock->default_value); MEM_freeN(sock); } @@ -929,12 +921,10 @@ void ntreeFreeTree(bNodeTree *ntree) } for (sock=ntree->inputs.first; sock; sock=sock->next) - if (sock->default_value) - MEM_freeN(sock->default_value); + node_socket_free_default_value(sock->type, sock->default_value); BLI_freelistN(&ntree->inputs); for (sock=ntree->outputs.first; sock; sock=sock->next) - if (sock->default_value) - MEM_freeN(sock->default_value); + node_socket_free_default_value(sock->type, sock->default_value); BLI_freelistN(&ntree->outputs); } @@ -1325,6 +1315,11 @@ void nodeSetActive(bNodeTree *ntree, bNode *node) node->flag |= NODE_ACTIVE_TEXTURE; } +int nodeSocketIsHidden(bNodeSocket *sock) +{ + return ((sock->flag & (SOCK_HIDDEN | SOCK_AUTO_HIDDEN | SOCK_UNAVAIL)) != 0); +} + /* ************** dependency stuff *********** */ /* node is guaranteed to be not checked before */ @@ -1857,7 +1852,8 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_channel_matte(ttype); register_node_type_cmp_color_spill(ttype); register_node_type_cmp_luma_matte(ttype); - + register_node_type_cmp_doubleedgemask(ttype); + register_node_type_cmp_translate(ttype); register_node_type_cmp_rotate(ttype); register_node_type_cmp_scale(ttype); @@ -1893,6 +1889,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_material(ttype); register_node_type_sh_camera(ttype); register_node_type_sh_gamma(ttype); + register_node_type_sh_brightcontrast(ttype); register_node_type_sh_value(ttype); register_node_type_sh_rgb(ttype); register_node_type_sh_mix_rgb(ttype); @@ -1948,6 +1945,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_tex_musgrave(ttype); register_node_type_sh_tex_gradient(ttype); register_node_type_sh_tex_magic(ttype); + register_node_type_sh_tex_checker(ttype); } static void registerTextureNodes(bNodeTreeType *ttype) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 8251c4796ea..d2b81a345a7 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -430,7 +430,8 @@ void unlink_object(Object *ob) if(pchan->custom==ob) pchan->custom= NULL; } - } else if(ELEM(OB_MBALL, ob->type, obt->type)) { + } + else if(ELEM(OB_MBALL, ob->type, obt->type)) { if(is_mball_basis_for(obt, ob)) obt->recalc|= OB_RECALC_DATA; } @@ -608,21 +609,6 @@ void unlink_object(Object *ob) sce= sce->id.next; } -#if 0 // XXX old animation system - /* ipos */ - ipo= bmain->ipo.first; - while(ipo) { - if(ipo->id.lib==NULL) { - IpoCurve *icu; - for(icu= ipo->curve.first; icu; icu= icu->next) { - if(icu->driver && icu->driver->ob==ob) - icu->driver->ob= NULL; - } - } - ipo= ipo->id.next; - } -#endif // XXX old animation system - /* screens */ sc= bmain->screen.first; while(sc) { @@ -844,7 +830,7 @@ Object *add_object(struct Scene *scene, int type) { Object *ob; Base *base; - char name[32]; + char name[MAX_ID_NAME]; BLI_strncpy(name, get_obdata_defname(type), sizeof(name)); ob = add_only_object(type, name); @@ -990,7 +976,7 @@ void copy_object_particlesystems(Object *obn, Object *ob) } else if (md->type==eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData*) md; - + if(smd->type==MOD_SMOKE_TYPE_FLOW) { if (smd->flow) { if (smd->flow->psys == psys) @@ -1026,22 +1012,6 @@ static void copy_object_pose(Object *obn, Object *ob) ListBase targets = {NULL, NULL}; bConstraintTarget *ct; -#if 0 // XXX old animation system - /* note that we can't change lib linked ipo blocks. for making - * proxies this still works correct however because the object - * is changed to object->proxy_from when evaluating the driver. */ - if(con->ipo && !con->ipo->id.lib) { - IpoCurve *icu; - - con->ipo= copy_ipo(con->ipo); - - for(icu= con->ipo->curve.first; icu; icu= icu->next) { - if(icu->driver && icu->driver->ob==ob) - icu->driver->ob= obn; - } - } -#endif // XXX old animation system - if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); @@ -1071,8 +1041,7 @@ static int object_pose_context(Object *ob) } } -//Object *object_pose_armature_get(Object *ob) -Object *object_pose_armature_get(struct Object *ob) +Object *object_pose_armature_get(Object *ob) { if(ob==NULL) return NULL; @@ -1178,13 +1147,8 @@ Object *copy_object(Object *ob) static void extern_local_object(Object *ob) { - //bActionStrip *strip; ParticleSystem *psys; -#if 0 // XXX old animation system - id_lib_extern((ID *)ob->action); - id_lib_extern((ID *)ob->ipo); -#endif // XXX old animation system id_lib_extern((ID *)ob->data); id_lib_extern((ID *)ob->dup_group); id_lib_extern((ID *)ob->poselib); @@ -1192,11 +1156,6 @@ static void extern_local_object(Object *ob) extern_local_matarar(ob->mat, ob->totcol); -#if 0 // XXX old animation system - for (strip=ob->nlastrips.first; strip; strip=strip->next) { - id_lib_extern((ID *)strip->act); - } -#endif // XXX old animation system for(psys=ob->particlesystem.first; psys; psys=psys->next) id_lib_extern((ID *)psys->part); } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 7be8aefc883..2decc40da81 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -251,7 +251,7 @@ static char *find_new_name(char *name) if (fop_exists(name)) { for (number = 1; number <= 999; number++) { - sprintf(tempname, "%s.%03d", name, number); + BLI_snprintf(tempname, sizeof(tempname), "%s.%03d", name, number); if (! fop_exists(tempname)) { break; } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index fe848f3d76c..2b3f792f777 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -66,6 +66,11 @@ Paint *paint_get_active(Scene *sce) return &ts->wpaint->paint; case OB_MODE_TEXTURE_PAINT: return &ts->imapaint.paint; + case OB_MODE_EDIT: + if(ts->use_uv_sculpt) + return &ts->uvsculpt->paint; + else + return &ts->imapaint.paint; } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index ce50c58a6e1..3a4ae5797a0 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3409,14 +3409,14 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n psys->part = psys_new_settings("ParticleSettings", NULL); if(BLI_countlist(&ob->particlesystem)>1) - sprintf(psys->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + BLI_snprintf(psys->name, sizeof(psys->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); else strcpy(psys->name, "ParticleSystem"); md= modifier_new(eModifierType_ParticleSystem); if(name) BLI_strncpy(md->name, name, sizeof(md->name)); - else sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + else BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); modifier_unique_name(&ob->modifiers, md); psmd= (ParticleSystemModifierData*) md; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 4afe9412786..5a64da7354e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1126,6 +1126,9 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D fprintf(stderr,"Particle distribution error: Nothing to emit from!\n"); if(dm != finaldm) dm->release(dm); + + BLI_kdtree_free(tree); + return 0; } @@ -3477,6 +3480,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) int totedge; int k; float hairmat[4][4]; + float (*deformedVerts)[3]; if(!psys->clmd) { psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth); @@ -3570,7 +3574,15 @@ static void do_hair_dynamics(ParticleSimulationData *sim) psys->clmd->point_cache = psys->pointcache; psys->clmd->sim_parms->effector_weights = psys->part->effector_weights; - psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm); + deformedVerts = MEM_callocN(sizeof(*deformedVerts)*dm->getNumVerts(dm), "do_hair_dynamics vertexCos"); + psys->hair_out_dm = CDDM_copy(dm); + psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts); + + clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, deformedVerts); + + CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts); + + MEM_freeN(deformedVerts); psys->clmd->sim_parms->effector_weights = NULL; } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 411e77de858..6fd89db10e7 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3096,7 +3096,7 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c } closedir(dir); - strcpy(pid->cache->name, old_name); + BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name)); } void BKE_ptcache_load_external(PTCacheID *pid) @@ -3217,11 +3217,11 @@ void BKE_ptcache_update_info(PTCacheID *pid) /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) - sprintf(cache->info, "%i frames found!", totframes); + BLI_snprintf(cache->info, sizeof(cache->info), "%i frames found!", totframes); else if(totframes && cache->totpoint) - sprintf(cache->info, "%i points found!", cache->totpoint); + BLI_snprintf(cache->info, sizeof(cache->info), "%i points found!", cache->totpoint); else - sprintf(cache->info, "No valid data to read!"); + BLI_snprintf(cache->info, sizeof(cache->info), "No valid data to read!"); return; } @@ -3231,9 +3231,9 @@ void BKE_ptcache_update_info(PTCacheID *pid) int totpoint = pid->totpoint(pid->calldata, 0); if(cache->totpoint > totpoint) - sprintf(mem_info, "%i cells + High Resolution cached", totpoint); + BLI_snprintf(mem_info, sizeof(mem_info), "%i cells + High Resolution cached", totpoint); else - sprintf(mem_info, "%i cells cached", totpoint); + BLI_snprintf(mem_info, sizeof(mem_info), "%i cells cached", totpoint); } else { int cfra = cache->startframe; @@ -3243,7 +3243,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - sprintf(mem_info, "%i frames on disk", totframes); + BLI_snprintf(mem_info, sizeof(mem_info), "%i frames on disk", totframes); } } else { @@ -3267,20 +3267,21 @@ void BKE_ptcache_update_info(PTCacheID *pid) mb = (bytes > 1024.0f * 1024.0f); - sprintf(mem_info, "%i frames in memory (%.1f %s)", + BLI_snprintf(mem_info, sizeof(mem_info), "%i frames in memory (%.1f %s)", totframes, bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), mb ? "Mb" : "kb"); } if(cache->flag & PTCACHE_OUTDATED) { - sprintf(cache->info, "%s, cache is outdated!", mem_info); + BLI_snprintf(cache->info, sizeof(cache->info), "%s, cache is outdated!", mem_info); } else if(cache->flag & PTCACHE_FRAMES_SKIPPED) { - sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact); + BLI_snprintf(cache->info, sizeof(cache->info), "%s, not exact since frame %i.", mem_info, cache->last_exact); + } + else { + BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info); } - else - sprintf(cache->info, "%s.", mem_info); } void BKE_ptcache_validate(PointCache *cache, int framenr) diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c index d6c4b5f3a2e..5668907b094 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -171,7 +171,7 @@ void unique_property(bProperty *first, bProperty *prop, int force) i= 0; do { /* ensure we have enough chars for the new number in the name */ - sprintf(num, "%d", i++); + 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)); diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index f7eda6bd9b3..92dfe90eec1 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -428,7 +428,7 @@ void init_actuator(bActuator *act) case ACT_CAMERA: act->data= MEM_callocN(sizeof(bCameraActuator), "camact"); ca = act->data; - ca->axis = ACT_CAMERA_X; + ca->axis = OB_POSX; ca->damping = 1.0/32.0; break; case ACT_EDIT_OBJECT: diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index ebe360ef91b..c8ec71d512f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -78,8 +78,6 @@ //XXX #include "BIF_previewrender.h" //XXX #include "BIF_editseq.h" -//XXX #include "nla.h" - #ifdef WIN32 #else #include <sys/time.h> @@ -299,6 +297,10 @@ void free_scene(Scene *sce) free_paint(&sce->toolsettings->sculpt->paint); MEM_freeN(sce->toolsettings->sculpt); } + if(sce->toolsettings->uvsculpt) { + free_paint(&sce->toolsettings->uvsculpt->paint); + MEM_freeN(sce->toolsettings->uvsculpt); + } free_paint(&sce->toolsettings->imapaint.paint); MEM_freeN(sce->toolsettings); @@ -529,6 +531,8 @@ Scene *add_scene(const char *name) sce->gm.recastData.detailsampledist = 6.0f; sce->gm.recastData.detailsamplemaxerror = 1.0f; + sce->gm.exitkey = 218; // Blender key code for ESC + sound_create_scene(sce); return sce; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 718b3144677..a8f89b0a1eb 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -176,7 +176,7 @@ static void open_plugin_seq(PluginSeq *pis, const char *seqname) MEM_freeN(info); cp= BLI_dynlib_find_symbol(pis->handle, "seqname"); - if(cp) BLI_strncpy(cp, seqname, 21); + if(cp) BLI_strncpy(cp, seqname, SEQ_NAME_MAXSTR); } else { printf ("Plugin returned unrecognized version number\n"); return; @@ -303,7 +303,10 @@ static struct ImBuf * do_plugin_effect( cp = BLI_dynlib_find_symbol( seq->plugin->handle, "seqname"); - if(cp) strncpy(cp, seq->name+2, 22); + /* XXX: it's crappy to limit copying buffer by it's lemgth, + * but assuming plugin stuff is using correct buffer size + * it should be fine */ + if(cp) strncpy(cp, seq->name+2, sizeof(seq->name)-2); if (seq->plugin->current_private_data) { *seq->plugin->current_private_data @@ -1574,7 +1577,6 @@ typedef struct WipeZone { int flip; int xo, yo; int width; - float invwidth; float pythangle; } WipeZone; @@ -1585,33 +1587,25 @@ static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo wipezone->xo = xo; wipezone->yo = yo; wipezone->width = (int)(wipe->edgeWidth*((xo+yo)/2.0f)); - wipezone->pythangle = 1.0f/sqrtf(wipe->angle*wipe->angle + 1.0f); - - if(wipe->wipetype == DO_SINGLE_WIPE) - wipezone->invwidth = 1.0f/wipezone->width; - else - wipezone->invwidth = 1.0f/(0.5f*wipezone->width); + wipezone->pythangle = 1.0f/sqrtf(wipezone->angle*wipezone->angle + 1.0f); } // This function calculates the blur band for the wipe effects -static float in_band(WipeZone *wipezone,float width,float dist,float perc,int side,int dir) +static float in_band(float width,float dist,int side,int dir) { - float t1,t2,alpha; + float alpha; if(width == 0) return (float)side; - + if(width < dist) - return side; - - t1 = dist * wipezone->invwidth; //percentange of width that is - t2 = wipezone->invwidth; //amount of alpha per % point - + return (float)side; + if(side == 1) - alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe + alpha = (dist+0.5*width) / (width); else - alpha = (1-perc) - (t1*t2*100); - + alpha = (0.5*width-dist) / (width); + if(dir == 0) alpha = 1-alpha; @@ -1648,7 +1642,6 @@ float hyp3,hyp4,b4,b5 switch (wipe->wipetype) { case DO_SINGLE_WIPE: width = wipezone->width; - hwidth = width*0.5f; if(angle == 0.0f) { b1 = posy; @@ -1669,15 +1662,15 @@ float hyp3,hyp4,b4,b5 if(wipe->forward) { if(b1 < b2) - output = in_band(wipezone,width,hyp,facf0,1,1); + output = in_band(width,hyp,1,1); else - output = in_band(wipezone,width,hyp,facf0,0,1); + output = in_band(width,hyp,0,1); } else { if(b1 < b2) - output = in_band(wipezone,width,hyp,facf0,0,1); + output = in_band(width,hyp,0,1); else - output = in_band(wipezone,width,hyp,facf0,1,1); + output = in_band(width,hyp,1,1); } break; @@ -1700,27 +1693,23 @@ float hyp3,hyp4,b4,b5 b3 = (yo-posy*0.5f) - (-angle)*(xo-posx*0.5f); b2 = y - (-angle)*x; - hyp = abs(angle*x+y+(-posy*0.5f-angle*posx*0.5f))*wipezone->pythangle; - hyp2 = abs(angle*x+y+(-(yo-posy*0.5f)-angle*(xo-posx*0.5f)))*wipezone->pythangle; + hyp = fabsf(angle*x+y+(-posy*0.5f-angle*posx*0.5f))*wipezone->pythangle; + hyp2 = fabsf(angle*x+y+(-(yo-posy*0.5f)-angle*(xo-posx*0.5f)))*wipezone->pythangle; } - temp1 = xo*(1-facf0*0.5f)-xo*facf0*0.5f; - temp2 = yo*(1-facf0*0.5f)-yo*facf0*0.5f; - pointdist = sqrt(temp1*temp1 + temp2*temp2); + hwidth= MIN2(hwidth, fabsf(b3-b1)/2.0f); if(b2 < b1 && b2 < b3 ){ - if(hwidth < pointdist) - output = in_band(wipezone,hwidth,hyp,facf0,0,1); + output = in_band(hwidth,hyp,0,1); } else if(b2 > b1 && b2 > b3 ){ - if(hwidth < pointdist) - output = in_band(wipezone,hwidth,hyp2,facf0,0,1); + output = in_band(hwidth,hyp2,0,1); } else { if( hyp < hwidth && hyp2 > hwidth ) - output = in_band(wipezone,hwidth,hyp,facf0,1,1); + output = in_band(hwidth,hyp,1,1); else if( hyp > hwidth && hyp2 < hwidth ) - output = in_band(wipezone,hwidth,hyp2,facf0,1,1); + output = in_band(hwidth,hyp2,1,1); else - output = in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1); + output = in_band(hwidth,hyp2,1,1) * in_band(hwidth,hyp,1,1); } if(!wipe->forward)output = 1-output; break; @@ -1840,8 +1829,8 @@ float hyp3,hyp4,b4,b5 pointdist = sqrt(temp1*temp1 + temp1*temp1); temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y)); - if(temp2 > pointdist) output = in_band(wipezone,hwidth,fabs(temp2-pointdist),facf0,0,1); - else output = in_band(wipezone,hwidth,fabs(temp2-pointdist),facf0,1,1); + if(temp2 > pointdist) output = in_band(hwidth,fabs(temp2-pointdist),0,1); + else output = in_band(hwidth,fabs(temp2-pointdist),1,1); if(!wipe->forward) output = 1-output; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index cc4b8917a32..08b53115919 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -833,8 +833,8 @@ void clear_scene_in_allseqs(Main *bmain, Scene *scene) typedef struct SeqUniqueInfo { Sequence *seq; - char name_src[32]; - char name_dest[32]; + char name_src[SEQ_NAME_MAXSTR]; + char name_dest[SEQ_NAME_MAXSTR]; int count; int match; } SeqUniqueInfo; @@ -850,7 +850,8 @@ static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui) Sequence *seq; for(seq=seqbasep->first; seq; seq= seq->next) { if (sui->seq != seq && strcmp(sui->name_dest, seq->name+2)==0) { - sprintf(sui->name_dest, "%.17s.%03d", sui->name_src, sui->count++); /*24 - 2 for prefix, -1 for \0 */ + /* SEQ_NAME_MAXSTR - 2 for prefix, -1 for \0, -4 for the number */ + BLI_snprintf(sui->name_dest, sizeof(sui->name_dest), "%.59s.%03d", sui->name_src, sui->count++); sui->match= 1; /* be sure to re-scan */ } } @@ -1689,10 +1690,10 @@ static ImBuf * input_preprocess( if(rct) { float rgb[3]; for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { - rgb_byte_to_float(rct, rgb); + rgb_uchar_to_float(rgb, rct); rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb+1, rgb+2); - rgb_float_to_byte(rgb, rct); + rgb_float_to_uchar(rct, rgb); } } @@ -3070,10 +3071,10 @@ void seq_sound_init(Scene *scene, Sequence *seq) } else { if(seq->sound) { - seq->scene_sound = sound_add_scene_sound(scene, seq, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); + seq->scene_sound = sound_add_scene_sound_defaults(scene, seq); } if(seq->scene) { - sound_scene_add_scene_sound(scene, seq, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); + sound_scene_add_scene_sound_defaults(scene, seq); } } } @@ -3227,10 +3228,8 @@ void seq_update_sound_bounds_all(Scene *scene) void seq_update_sound_bounds(Scene* scene, Sequence *seq) { - if(seq->scene_sound) { - sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); - /* mute is set in seq_update_muting_recursive */ - } + sound_move_scene_sound_defaults(scene, seq); + /* mute is set in seq_update_muting_recursive */ } static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute) @@ -3390,13 +3389,13 @@ int seq_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) { - char str[32]; + char str[SEQ_NAME_MAXSTR+3]; FCurve *fcu; if(scene->adt==NULL || ofs==0 || scene->adt->action==NULL) return; - sprintf(str, "[\"%s\"]", seq->name+2); + BLI_snprintf(str, sizeof(str), "[\"%s\"]", seq->name+2); for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) { if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { @@ -3413,7 +3412,7 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) void seq_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) { - char str_from[32]; + char str_from[SEQ_NAME_MAXSTR+3]; FCurve *fcu; FCurve *fcu_last; FCurve *fcu_cpy; @@ -3422,7 +3421,7 @@ void seq_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) if(scene->adt==NULL || scene->adt->action==NULL) return; - sprintf(str_from, "[\"%s\"]", name_src); + BLI_snprintf(str_from, sizeof(str_from), "[\"%s\"]", name_src); fcu_last= scene->adt->action->curves.last; @@ -3443,13 +3442,13 @@ void seq_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) /* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */ static void seq_free_animdata(Scene *scene, Sequence *seq) { - char str[32]; + char str[SEQ_NAME_MAXSTR+3]; FCurve *fcu; if(scene->adt==NULL || scene->adt->action==NULL) return; - sprintf(str, "[\"%s\"]", seq->name+2); + BLI_snprintf(str, sizeof(str), "[\"%s\"]", seq->name+2); fcu= scene->adt->action->curves.first; @@ -3772,7 +3771,7 @@ static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence } else if(seq->type == SEQ_SCENE) { seqn->strip->stripdata = NULL; if(seq->scene_sound) - seqn->scene_sound = sound_scene_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); + seqn->scene_sound = sound_scene_add_scene_sound_defaults(sce_audio, seqn); } else if(seq->type == SEQ_MOVIE) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); @@ -3781,7 +3780,7 @@ static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); if(seq->scene_sound) - seqn->scene_sound = sound_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); + seqn->scene_sound = sound_add_scene_sound_defaults(sce_audio, seqn); seqn->sound->id.us++; } else if(seq->type == SEQ_IMAGE) { diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 60941ef78a3..424f97f57ed 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -77,6 +77,9 @@ #include "BKE_smoke.h" +/* UNUSED so far, may be enabled later */ +/* #define USE_SMOKE_COLLISION_DM */ + #ifdef WITH_SMOKE #ifdef _WIN32 @@ -617,9 +620,11 @@ static void smokeModifier_freeCollision(SmokeModifierData *smd) smd->coll->bvhtree = NULL; } +#ifdef USE_SMOKE_COLLISION_DM if(smd->coll->dm) smd->coll->dm->release(smd->coll->dm); smd->coll->dm = NULL; +#endif MEM_freeN(smd->coll); smd->coll = NULL; @@ -682,9 +687,11 @@ void smokeModifier_reset(struct SmokeModifierData *smd) smd->coll->bvhtree = NULL; } +#ifdef USE_SMOKE_COLLISION_DM if(smd->coll->dm) smd->coll->dm->release(smd->coll->dm); smd->coll->dm = NULL; +#endif } } @@ -772,7 +779,10 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->coll->points = NULL; smd->coll->numpoints = 0; smd->coll->bvhtree = NULL; + +#ifdef USE_SMOKE_COLLISION_DM smd->coll->dm = NULL; +#endif } } } @@ -1339,11 +1349,13 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM { // XXX TODO smd->time = scene->r.cfra; - + +#ifdef USE_SMOKE_COLLISION_DM if(smd->coll->dm) smd->coll->dm->release(smd->coll->dm); smd->coll->dm = CDDM_copy(dm); +#endif // rigid movement support copy_m4_m4(smd->coll->mat_old, smd->coll->mat); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index cab621eeff7..46a3f776e43 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3468,7 +3468,7 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff,Object * bs->len= globallen((bp-dw-dv-1)->vec, bp->vec,ob); bs++; } - if( (v < lt->pntsv-1) && (u) ) { + if( (v < lt->pntsv-1) && (u != 0) ) { bs->v1 = bpc; bs->v2 = bpc-dw+dv-1; bs->springtype=SB_BEND; @@ -3485,7 +3485,7 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff,Object * bs->len= globallen((bp+dw-dv-1)->vec, bp->vec,ob); bs++; } - if( (v < lt->pntsv-1) && (u) ) { + if( (v < lt->pntsv-1) && (u != 0) ) { bs->v1 = bpc; bs->v2 = bpc+dw+dv-1; bs->springtype=SB_BEND; @@ -3728,6 +3728,8 @@ SoftBody *sbNew(Scene *scene) if(!sb->effector_weights) sb->effector_weights = BKE_add_effector_weights(NULL); + sb->last_frame= MINFRAME-1; + return sb; } @@ -4108,6 +4110,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i softbody_update_positions(ob, sb, vertexCos, numVerts); softbody_step(scene, ob, sb, dtime); softbody_to_object(ob, vertexCos, numVerts, 0); + sb->last_frame = framenr; return; } @@ -4123,6 +4126,9 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i BKE_ptcache_validate(cache, framenr); cache->flag &= ~PTCACHE_REDO_NEEDED; + + sb->last_frame = framenr; + return; } @@ -4137,6 +4143,8 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) BKE_ptcache_write(&pid, framenr); + sb->last_frame = framenr; + return; } else if(cache_result==PTCACHE_READ_OLD) { @@ -4148,6 +4156,9 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i return; } + if(framenr!=sb->last_frame+1) + return; + /* if on second frame, write cache for first frame */ if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) BKE_ptcache_write(&pid, startframe); @@ -4164,5 +4175,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i BKE_ptcache_validate(cache, framenr); BKE_ptcache_write(&pid, framenr); + + sb->last_frame = framenr; } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index ceaba2502d9..f5b677203f6 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -233,7 +233,7 @@ struct bSound* sound_new_buffer(struct Main *bmain, struct bSound *source) { bSound* sound = NULL; - char name[25]; + char name[MAX_ID_NAME+5]; strcpy(name, "buf_"); strcpy(name + 4, source->id.name); @@ -257,7 +257,7 @@ struct bSound* sound_new_limiter(struct Main *bmain, struct bSound *source, floa { bSound* sound = NULL; - char name[25]; + char name[MAX_ID_NAME+5]; strcpy(name, "lim_"); strcpy(name + 4, source->id.name); @@ -449,6 +449,13 @@ void* sound_scene_add_scene_sound(struct Scene *scene, struct Sequence* sequence return NULL; } +void* sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence* sequence) +{ + return sound_scene_add_scene_sound(scene, sequence, + sequence->startdisp, sequence->enddisp, + sequence->startofs + sequence->anim_startofs); +} + void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip) { void* handle = AUD_addSequence(scene->sound_scene, sequence->sound->playback_handle, startframe / FPS, endframe / FPS, frameskip / FPS); @@ -459,6 +466,13 @@ void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int return handle; } +void* sound_add_scene_sound_defaults(struct Scene *scene, struct Sequence* sequence) +{ + return sound_add_scene_sound(scene, sequence, + sequence->startdisp, sequence->enddisp, + sequence->startofs + sequence->anim_startofs); +} + void sound_remove_scene_sound(struct Scene *scene, void* handle) { AUD_removeSequence(scene->sound_scene, handle); @@ -474,6 +488,15 @@ void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, i AUD_moveSequence(handle, startframe / FPS, endframe / FPS, frameskip / FPS); } +void sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence* sequence) +{ + if (sequence->scene_sound) { + sound_move_scene_sound(scene, sequence->scene_sound, + sequence->startdisp, sequence->enddisp, + sequence->startofs + sequence->anim_startofs); + } +} + void sound_update_scene_sound(void* handle, struct bSound* sound) { AUD_updateSequenceSound(handle, sound->playback_handle); @@ -781,11 +804,13 @@ 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)) {} -static void sound_start_play_scene(struct Scene *UNUSED(scene)) {} +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)) {} diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index e773eb6dd35..ffcbd0bdc56 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -92,9 +92,17 @@ static void arena_release(CCGAllocatorHDL a) { BLI_memarena_free(a); } -static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int UNUSED(useFlatSubdiv)) { +typedef enum { + CCG_USE_AGING = 1, + CCG_USE_ARENA = 2, + CCG_CALC_NORMALS = 4, +} CCGFlags; + +static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, CCGFlags flags) { CCGMeshIFC ifc; CCGSubSurf *ccgSS; + int useAging = !!(flags & CCG_USE_AGING); + int useArena = flags & CCG_USE_ARENA; /* subdivLevels==0 is not allowed */ subdivLevels = MAX2(subdivLevels, 1); @@ -102,7 +110,6 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAgin if (prevSS) { int oldUseAging; - useAging = !!useAging; ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL); if (oldUseAging!=useAging) { @@ -119,7 +126,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAgin } else { ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8; } - ifc.vertDataSize = sizeof(DMGridData); + ifc.vertDataSize = sizeof(float) * (flags & CCG_CALC_NORMALS ? 6 : 3); if (useArena) { CCGAllocatorIFC allocatorIFC; @@ -139,7 +146,10 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAgin ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8); } - ccgSubSurf_setCalcVertexNormals(ccgSS, 1, offsetof(DMGridData, no)); + if (flags & CCG_CALC_NORMALS) + ccgSubSurf_setCalcVertexNormals(ccgSS, 1, offsetof(DMGridData, no)); + else + ccgSubSurf_setCalcVertexNormals(ccgSS, 0, 0); return ccgSS; } @@ -322,7 +332,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, return; /* create a CCGSubSurf from uv's */ - uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 0, 1, 0); + uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), CCG_USE_ARENA); if(!ss_sync_from_uv(uvss, ss, dm, dmtface)) { ccgSubSurf_free(uvss); @@ -353,14 +363,14 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int numVerts = ccgSubSurf_getFaceNumVerts(f); for (S=0; S<numVerts; S++) { - DMGridData *faceGridData= ccgSubSurf_getFaceGridDataArray(uvss, f, S); + float (*faceGridData)[3]= ccgSubSurf_getFaceGridDataArray(uvss, f, S); for(y = 0; y < gridFaces; y++) { for(x = 0; x < gridFaces; x++) { - copy_v2_v2(tf->uv[0], faceGridData[(y + 0)*gridSize + x + 0].co); - copy_v2_v2(tf->uv[1], faceGridData[(y + 1)*gridSize + x + 0].co); - copy_v2_v2(tf->uv[2], faceGridData[(y + 1)*gridSize + x + 1].co); - copy_v2_v2(tf->uv[3], faceGridData[(y + 0)*gridSize + x + 1].co); + copy_v2_v2(tf->uv[0], faceGridData[(y + 0)*gridSize + x + 0]); + copy_v2_v2(tf->uv[1], faceGridData[(y + 1)*gridSize + x + 0]); + copy_v2_v2(tf->uv[2], faceGridData[(y + 1)*gridSize + x + 1]); + copy_v2_v2(tf->uv[3], faceGridData[(y + 0)*gridSize + x + 1]); tf++; } @@ -2773,7 +2783,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( int isFinalCalc, int forEditMode, int inEditMode) { int useSimple = smd->subdivType == ME_SIMPLE_SUBSURF; - int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr; + CCGFlags useAging = smd->flags & eSubsurfModifierFlag_DebugIncr ? CCG_USE_AGING : 0; int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv; int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges); CCGDerivedMesh *result; @@ -2781,8 +2791,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( if(forEditMode) { int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels; - smd->emCache = _getSubSurf(smd->emCache, levels, useAging, 0, - useSimple); + smd->emCache = _getSubSurf(smd->emCache, levels, useAging|CCG_CALC_NORMALS); ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple); result = getCCGDerivedMesh(smd->emCache, @@ -2796,7 +2805,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( if(levels == 0) return dm; - ss = _getSubSurf(NULL, levels, 0, 1, useSimple); + ss = _getSubSurf(NULL, levels, CCG_USE_ARENA|CCG_CALC_NORMALS); ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); @@ -2806,7 +2815,6 @@ struct DerivedMesh *subsurf_make_derived_from_derived( result->freeSS = 1; } else { int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental); - int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr; int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels; CCGSubSurf *ss; @@ -2827,8 +2835,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( } if(useIncremental && isFinalCalc) { - smd->mCache = ss = _getSubSurf(smd->mCache, levels, - useAging, 0, useSimple); + smd->mCache = ss = _getSubSurf(smd->mCache, levels, useAging|CCG_CALC_NORMALS); ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); @@ -2841,7 +2848,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( smd->mCache = NULL; } - ss = _getSubSurf(NULL, levels, 0, 1, useSimple); + ss = _getSubSurf(NULL, levels, CCG_USE_ARENA|CCG_CALC_NORMALS); ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm); @@ -2863,7 +2870,7 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) * calculated vert positions is incorrect for the verts * on the boundary of the mesh. */ - CCGSubSurf *ss = _getSubSurf(NULL, 1, 0, 1, 0); + CCGSubSurf *ss = _getSubSurf(NULL, 1, CCG_USE_ARENA); float edge_sum[3], face_sum[3]; CCGVertIterator *vi; DerivedMesh *dm = CDDM_from_mesh(me, NULL); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 7e102bc9854..ba48db588c4 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -33,6 +33,8 @@ #include <string.h> /* strstr */ #include <sys/types.h> #include <sys/stat.h> +#include <wchar.h> +#include <wctype.h> #include "MEM_guardedalloc.h" @@ -215,8 +217,48 @@ Text *add_empty_text(const char *name) return ta; } +/* this function replaces extended ascii characters */ +/* to a valid utf-8 sequences */ +int txt_extended_ascii_as_utf8(char **str) +{ + int bad_char, added= 0, i= 0; + int length = strlen(*str); + + while ((*str)[i]) { + if((bad_char= BLI_utf8_invalid_byte(*str+i, length-i)) == -1) + break; + + added++; + i+= bad_char + 1; + } + + if (added != 0) { + char *newstr = MEM_mallocN(length+added+1, "text_line"); + int mi = 0; + i= 0; + + while ((*str)[i]) { + if((bad_char= BLI_utf8_invalid_byte((*str)+i, length-i)) == -1) { + memcpy(newstr+mi, (*str)+i, length - i + 1); + break; + } + + memcpy(newstr+mi, (*str)+i, bad_char); + + BLI_str_utf8_from_unicode((*str)[i+bad_char], newstr+mi+bad_char); + i+= bad_char+1; + mi+= bad_char+2; + } + newstr[length+added] = '\0'; + MEM_freeN(*str); + *str = newstr; + } + + return added; +} + // this function removes any control characters from -// a textline +// a textline and fixes invalid utf-8 sequences static void cleanup_textline(TextLine * tl) { @@ -229,6 +271,7 @@ static void cleanup_textline(TextLine * tl) i--; } } + tl->len+= txt_extended_ascii_as_utf8(&tl->line); } int reopen_text(Text *text) @@ -689,16 +732,10 @@ static void txt_make_dirty (Text *text) } /* 0:whitespace, 1:punct, 2:alphanumeric */ -static short txt_char_type (char ch) -{ - if (ch <= ' ') return 0; /* 32 */ - if (ch <= '/') return 1; /* 47 */ - if (ch <= '9') return 2; /* 57 */ - if (ch <= '@') return 1; /* 64 */ - if (ch <= 'Z') return 2; /* 90 */ - if (ch == '_') return 2; /* 95, dont delimit '_' */ - if (ch <= '`') return 1; /* 96 */ - if (ch <= 'z') return 2; /* 122 */ +static short txt_char_type(unsigned int ch) +{ + if (iswspace(ch)) return 0; + if (iswalpha(ch) || iswdigit(ch)) return 2; return 1; } @@ -731,29 +768,63 @@ static void txt_curs_first (Text *text, TextLine **linep, int *charp) } } -/****************************/ +/*****************************/ /* Cursor movement functions */ -/****************************/ +/*****************************/ + +int txt_utf8_offset_to_index(char *str, int offset) +{ + int index= 0, pos= 0; + while (pos != offset) { + pos += BLI_str_utf8_size(str + pos); + index++; + } + return index; +} + +int txt_utf8_index_to_offset(char *str, int index) +{ + int offset= 0, pos= 0; + while (pos != index) { + offset += BLI_str_utf8_size(str + offset); + pos++; + } + return offset; +} + +/* returns the real number of characters in string */ +/* not the same as BLI_strlen_utf8, which returns length for wide characters */ +static int txt_utf8_len(const char *src) +{ + int len; + + for (len=0; *src; len++) { + src += BLI_str_utf8_size(src); + } + + return len; +} void txt_move_up(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; + /* int old; */ /* UNUSED */ if (!text) return; if(sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - old= *charp; + /* old= *charp; */ /* UNUSED */ if((*linep)->prev) { + int index = txt_utf8_offset_to_index((*linep)->line, *charp); *linep= (*linep)->prev; - if (*charp > (*linep)->len) { - *charp= (*linep)->len; - if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->next), old, txt_get_span(text->lines.first, *linep), (unsigned short) *charp); - } else { - if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); - } + if (index > txt_utf8_len((*linep)->line)) *charp= (*linep)->len; + else *charp= txt_utf8_index_to_offset((*linep)->line, index); + + if(!undoing) + txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); } else { txt_move_bol(text, sel); } @@ -764,21 +835,23 @@ void txt_move_up(Text *text, short sel) void txt_move_down(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; + /* int old; */ /* UNUSED */ if (!text) return; if(sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - old= *charp; + /* old= *charp; */ /* UNUSED */ if((*linep)->next) { + int index = txt_utf8_offset_to_index((*linep)->line, *charp); *linep= (*linep)->next; - if (*charp > (*linep)->len) { - *charp= (*linep)->len; - if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->prev), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); - } else - if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); + if (index > txt_utf8_len((*linep)->line)) *charp= (*linep)->len; + else *charp= txt_utf8_index_to_offset((*linep)->line, index); + + if(!undoing) + txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); } else { txt_move_eol(text, sel); } @@ -790,7 +863,7 @@ void txt_move_left(Text *text, short sel) { TextLine **linep; int *charp, oundoing= undoing; - int tabsize = 1, i=0; + int tabsize= 0, i= 0; if (!text) return; if(sel) txt_curs_sel(text, &linep, &charp); @@ -799,32 +872,36 @@ void txt_move_left(Text *text, short sel) undoing= 1; - // do nice left only if there are only spaces - // TXT_TABSIZE hardcoded in DNA_text_types.h - if (text->flags & TXT_TABSTOSPACES) { - tabsize = TXT_TABSIZE; - - if (*charp < tabsize) - tabsize = *charp; - else { - for (i=0;i<(*charp);i++) + if (*charp== 0) { + if ((*linep)->prev) { + txt_move_up(text, sel); + *charp= (*linep)->len; + } + } + else { + // do nice left only if there are only spaces + // TXT_TABSIZE hardcoded in DNA_text_types.h + if (text->flags & TXT_TABSTOSPACES) { + tabsize= (*charp < TXT_TABSIZE) ? *charp : TXT_TABSIZE; + + for (i=0; i<(*charp); i++) if ((*linep)->line[i] != ' ') { - tabsize = 1; + tabsize= 0; break; } + // if in the middle of the space-tab - if ((*charp) % tabsize != 0) - tabsize = ((*charp) % tabsize); + if (tabsize && (*charp) % TXT_TABSIZE != 0) + tabsize= ((*charp) % TXT_TABSIZE); } - } - - if (*charp== 0) { - if ((*linep)->prev) { - txt_move_up(text, sel); - *charp= (*linep)->len; + + if (tabsize) + (*charp)-= tabsize; + else { + const char *prev= BLI_str_prev_char_utf8((*linep)->line + *charp); + *charp= prev - (*linep)->line; } } - else (*charp)-= tabsize; undoing= oundoing; if(!undoing) txt_undo_add_op(text, sel?UNDO_SLEFT:UNDO_CLEFT); @@ -835,8 +912,7 @@ void txt_move_left(Text *text, short sel) void txt_move_right(Text *text, short sel) { TextLine **linep; - int *charp, oundoing= undoing; - int tabsize=1, i=0; + int *charp, oundoing= undoing, do_tab= 0, i; if (!text) return; if(sel) txt_curs_sel(text, &linep, &charp); @@ -845,32 +921,33 @@ void txt_move_right(Text *text, short sel) undoing= 1; - // do nice right only if there are only spaces - // spaces hardcoded in DNA_text_types.h - if (text->flags & TXT_TABSTOSPACES) { - tabsize = TXT_TABSIZE; - - if ((*charp) + tabsize > (*linep)->len) - tabsize = 1; - else { - for (i=0;i<(*charp) + tabsize - ((*charp) % tabsize);i++) - if ((*linep)->line[i] != ' ') { - tabsize = 1; - break; - } - // if in the middle of the space-tab - tabsize -= (*charp) % tabsize; - } - } - if (*charp== (*linep)->len) { if ((*linep)->next) { txt_move_down(text, sel); *charp= 0; } - } else { - (*charp)+=tabsize; + } + else { + // do nice right only if there are only spaces + // spaces hardcoded in DNA_text_types.h + if (text->flags & TXT_TABSTOSPACES && (*linep)->line[*charp]== ' ') { + do_tab= 1; + for (i=0; i<*charp; i++) + if ((*linep)->line[i]!= ' ') { + do_tab= 0; + break; + } + } + + if (do_tab) { + int tabsize= (*charp) % TXT_TABSIZE + 1; + for (i=*charp+1; (*linep)->line[i]==' ' && tabsize<TXT_TABSIZE; i++) + tabsize++; + (*charp)= i; + } + else (*charp)+= BLI_str_utf8_size((*linep)->line + *charp); } + undoing= oundoing; if(!undoing) txt_undo_add_op(text, sel?UNDO_SRIGHT:UNDO_CRIGHT); @@ -896,9 +973,12 @@ void txt_jump_left(Text *text, short sel) count= 0; for (i=0; i<3; i++) { if (count < 2) { - while (*charp>0 && txt_char_type((*linep)->line[*charp-1])==i) { - txt_move_left(text, sel); - count++; + while (*charp>0) { + char *sym= BLI_str_prev_char_utf8((*linep)->line + *charp); + if (txt_char_type(BLI_str_utf8_as_unicode(sym))==i) { + txt_move_left(text, sel); + count++; + } else break; } } } @@ -927,9 +1007,12 @@ void txt_jump_right(Text *text, short sel) count= 0; for (i=0; i<3; i++) { if (count < 2) { - while (*charp<(*linep)->len && txt_char_type((*linep)->line[*charp])==i) { - txt_move_right(text, sel); - count++; + while (*charp<(*linep)->len) { + char *sym= (*linep)->line + *charp; + if (txt_char_type(BLI_str_utf8_as_unicode(sym))==i) { + txt_move_right(text, sel); + count++; + } else break; } } } @@ -1014,6 +1097,7 @@ void txt_move_toline (Text *text, unsigned int line, short sel) txt_move_to(text, line, 0, sel); } +/* Moves to a certain byte in a line, not a certain utf8-character! */ void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel) { TextLine **linep, *oldl; @@ -1396,42 +1480,45 @@ static void txt_shift_markers(Text *text, int lineno, int count) void txt_insert_buf(Text *text, const char *in_buffer) { - int i=0, l=0, j, u, len, lineno= -1, count= 0; + int l=0, u, len, lineno= -1, count= 0; + size_t i=0, j; TextLine *add; + char *buffer; if (!text) return; if (!in_buffer) return; txt_delete_sel(text); - if(!undoing) txt_undo_add_block (text, UNDO_IBLOCK, in_buffer); + len= strlen(in_buffer); + buffer= BLI_strdupn(in_buffer, len); + len+= txt_extended_ascii_as_utf8(&buffer); + + if(!undoing) txt_undo_add_block(text, UNDO_IBLOCK, buffer); u= undoing; undoing= 1; /* Read the first line (or as close as possible */ - while (in_buffer[i] && in_buffer[i]!='\n') { - txt_add_raw_char(text, in_buffer[i]); - i++; - } + while (buffer[i] && buffer[i]!='\n') + txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i)); - if (in_buffer[i]=='\n') txt_split_curline(text); - else { undoing = u; return; } + if (buffer[i]=='\n') txt_split_curline(text); + else { undoing = u; MEM_freeN(buffer); return; } i++; /* Read as many full lines as we can */ - len= strlen(in_buffer); lineno= txt_get_span(text->lines.first, text->curl); while (i<len) { l=0; - while (in_buffer[i] && in_buffer[i]!='\n') { + while (buffer[i] && buffer[i]!='\n') { i++; l++; } - if(in_buffer[i]=='\n') { - add= txt_new_linen(in_buffer +(i-l), l); + if(buffer[i]=='\n') { + add= txt_new_linen(buffer +(i-l), l); BLI_insertlinkbefore(&text->lines, text->curl, add); i++; count++; @@ -1441,21 +1528,19 @@ void txt_insert_buf(Text *text, const char *in_buffer) count= 0; } - for (j= i-l; j<i && j<(int)strlen(in_buffer); j++) { - txt_add_raw_char(text, in_buffer[j]); - } + for (j= i-l; j<i && j<len; ) + txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j)); break; } } + + MEM_freeN(buffer); if(count) { txt_shift_markers(text, lineno, count); - count= 0; } undoing= u; - - (void)count; } /******************/ @@ -1525,12 +1610,30 @@ void txt_print_undo(Text *text) ops= "Selection "; } else if (op==UNDO_CTO) { ops= "Cursor "; - } else if (op==UNDO_INSERT) { - ops= "Insert"; - } else if (op==UNDO_BS) { - ops= "Backspace"; - } else if (op==UNDO_DEL) { - ops= "Delete"; + } else if (op==UNDO_INSERT_1) { + ops= "Insert ascii "; + } else if (op==UNDO_INSERT_2) { + ops= "Insert 2 bytes "; + } else if (op==UNDO_INSERT_3) { + ops= "Insert 3 bytes "; + } else if (op==UNDO_INSERT_4) { + ops= "Insert unicode "; + } else if (op==UNDO_BS_1) { + ops= "Backspace for ascii "; + } else if (op==UNDO_BS_2) { + ops= "Backspace for 2 bytes "; + } else if (op==UNDO_BS_3) { + ops= "Backspace for 3 bytes "; + } else if (op==UNDO_BS_4) { + ops= "Backspace for unicode "; + } else if (op==UNDO_DEL_1) { + ops= "Delete ascii "; + } else if (op==UNDO_DEL_2) { + ops= "Delete 2 bytes "; + } else if (op==UNDO_DEL_3) { + ops= "Delete 3 bytes "; + } else if (op==UNDO_DEL_4) { + ops= "Delete unicode "; } else if (op==UNDO_SWAP) { ops= "Cursor swap"; } else if (op==UNDO_DBLOCK) { @@ -1550,10 +1653,35 @@ void txt_print_undo(Text *text) } printf ("Op (%o) at %d = %s", op, i, ops); - if (op==UNDO_INSERT || op==UNDO_BS || op==UNDO_DEL) { - i++; - printf (" - Char is %c", text->undo_buf[i]); + if (op >= UNDO_INSERT_1 && op <= UNDO_DEL_4) { i++; + printf (" - Char is "); + switch (op) { + case UNDO_INSERT_1: case UNDO_BS_1: case UNDO_DEL_1: + printf ("%c", text->undo_buf[i]); + i++; + break; + case UNDO_INSERT_2: case UNDO_BS_2: case UNDO_DEL_2: + printf ("%c%c", text->undo_buf[i], text->undo_buf[i+1]); + i+=2; + break; + case UNDO_INSERT_3: case UNDO_BS_3: case UNDO_DEL_3: + 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: { + unsigned int uc; + char c[BLI_UTF8_MAX+1]; + size_t c_len; + uc= text->undo_buf[i]; i++; + uc= uc+(text->undo_buf[i]<<8); i++; + uc= uc+(text->undo_buf[i]<<16); i++; + uc= uc+(text->undo_buf[i]<<24); i++; + c_len= BLI_str_utf8_from_unicode(uc, c); + c[c_len]= '\0'; + printf ("%s", c); + } + } } else if (op==UNDO_STO || op==UNDO_CTO) { i++; @@ -1635,40 +1763,43 @@ static void txt_undo_add_op(Text *text, int op) text->undo_buf[text->undo_pos+1]= 0; } +static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value) +{ + undo_buf[*undo_pos]= (value)&0xff; + (*undo_pos)++; + undo_buf[*undo_pos]= (value>>8)&0xff; + (*undo_pos)++; +} + +static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int value) +{ + undo_buf[*undo_pos]= (value)&0xff; + (*undo_pos)++; + undo_buf[*undo_pos]= (value>>8)&0xff; + (*undo_pos)++; + undo_buf[*undo_pos]= (value>>16)&0xff; + (*undo_pos)++; + undo_buf[*undo_pos]= (value>>24)&0xff; + (*undo_pos)++; +} + static void txt_undo_add_block(Text *text, int op, const char *buf) { - int length; - - length= strlen(buf); + unsigned int length= strlen(buf); if(!max_undo_test(text, length+11)) return; text->undo_pos++; text->undo_buf[text->undo_pos]= op; - - text->undo_pos++; - text->undo_buf[text->undo_pos]= (length)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (length>>8)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (length>>16)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (length>>24)&0xff; - text->undo_pos++; + + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length); + strncpy(text->undo_buf+text->undo_pos, buf, length); text->undo_pos+=length; - text->undo_buf[text->undo_pos]= (length)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (length>>8)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (length>>16)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (length>>24)&0xff; - - text->undo_pos++; + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length); text->undo_buf[text->undo_pos]= op; text->undo_buf[text->undo_pos+1]= 0; @@ -1685,51 +1816,147 @@ void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fr text->undo_buf[text->undo_pos]= op; text->undo_pos++; - text->undo_buf[text->undo_pos]= (fromc)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (fromc>>8)&0xff; + + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, fromc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, froml); + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, toc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, tol); + + text->undo_buf[text->undo_pos]= op; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (froml)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (froml>>8)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (froml>>16)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (froml>>24)&0xff; + text->undo_buf[text->undo_pos+1]= 0; +} +static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) +{ + char utf8[BLI_UTF8_MAX]; + size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8); + + if(!max_undo_test(text, 3 + utf8_size)) + return; + text->undo_pos++; - text->undo_buf[text->undo_pos]= (toc)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (toc>>8)&0xff; + + if (utf8_size < 4) { + text->undo_buf[text->undo_pos]= op_start + utf8_size - 1; + text->undo_pos++; + + for (i = 0; i < utf8_size; i++) { + text->undo_buf[text->undo_pos]= utf8[i]; + text->undo_pos++; + } + + text->undo_buf[text->undo_pos]= op_start + utf8_size - 1; + } else { + text->undo_buf[text->undo_pos]= op_start + 3; + text->undo_pos++; + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c); + text->undo_buf[text->undo_pos]= op_start + 3; + } + + text->undo_buf[text->undo_pos+1]= 0; +} - text->undo_pos++; - text->undo_buf[text->undo_pos]= (tol)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (tol>>8)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (tol>>16)&0xff; - text->undo_pos++; - text->undo_buf[text->undo_pos]= (tol>>24)&0xff; +static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos) +{ + unsigned short val; + val= undo_buf[*undo_pos]; (*undo_pos)--; + val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--; + return val; +} - text->undo_pos++; - text->undo_buf[text->undo_pos]= op; +static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos) +{ + unsigned int val; + val= undo_buf[*undo_pos]; (*undo_pos)--; + val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--; + val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--; + val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--; + return val; +} - text->undo_buf[text->undo_pos+1]= 0; +static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) +{ + unsigned int unicode; + char utf8[BLI_UTF8_MAX+1]; + + switch (bytes) { + case 1: /* ascii */ + unicode = undo_buf[*undo_pos]; (*undo_pos)--; + break; + case 2: /* 2-byte symbol */ + utf8[2] = '\0'; + utf8[1] = undo_buf[*undo_pos]; (*undo_pos)--; + utf8[0] = undo_buf[*undo_pos]; (*undo_pos)--; + unicode= BLI_str_utf8_as_unicode(utf8); + break; + case 3: /* 3-byte symbol */ + utf8[3] = '\0'; + utf8[2] = undo_buf[*undo_pos]; (*undo_pos)--; + utf8[1] = undo_buf[*undo_pos]; (*undo_pos)--; + utf8[0] = undo_buf[*undo_pos]; (*undo_pos)--; + unicode= BLI_str_utf8_as_unicode(utf8); + break; + case 4: /* 32-bit unicode symbol */ + unicode= txt_undo_read_uint32(undo_buf, undo_pos); + default: + /* should never happen */ + BLI_assert(0); + unicode= 0; + } + + return unicode; } -static void txt_undo_add_charop(Text *text, int op, char c) +static unsigned short txt_redo_read_uint16(const char *undo_buf, int *undo_pos) { - if(!max_undo_test(text, 4)) - return; + unsigned short val; + val = undo_buf[*undo_pos]; (*undo_pos)++; + val = val+(undo_buf[*undo_pos]<<8); (*undo_pos)++; + return val; +} - text->undo_pos++; - text->undo_buf[text->undo_pos]= op; - text->undo_pos++; - text->undo_buf[text->undo_pos]= c; - text->undo_pos++; - text->undo_buf[text->undo_pos]= op; - text->undo_buf[text->undo_pos+1]= 0; +static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos) +{ + unsigned int val; + val= undo_buf[*undo_pos]; (*undo_pos)++; + val= val+(undo_buf[*undo_pos]<<8); (*undo_pos)++; + val= val+(undo_buf[*undo_pos]<<16); (*undo_pos)++; + val= val+(undo_buf[*undo_pos]<<24); (*undo_pos)++; + return val; +} + +static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) +{ + unsigned int unicode; + char utf8[BLI_UTF8_MAX+1]; + + switch (bytes) { + case 1: /* ascii */ + unicode = undo_buf[*undo_pos]; (*undo_pos)++; + break; + case 2: /* 2-byte symbol */ + utf8[0] = undo_buf[*undo_pos]; (*undo_pos)++; + utf8[1] = undo_buf[*undo_pos]; (*undo_pos)++; + utf8[2] = '\0'; + unicode= BLI_str_utf8_as_unicode(utf8); + break; + case 3: /* 3-byte symbol */ + utf8[0] = undo_buf[*undo_pos]; (*undo_pos)++; + utf8[1] = undo_buf[*undo_pos]; (*undo_pos)++; + utf8[2] = undo_buf[*undo_pos]; (*undo_pos)++; + utf8[3] = '\0'; + unicode= BLI_str_utf8_as_unicode(utf8); + break; + case 4: /* 32-bit unicode symbol */ + unicode= txt_undo_read_uint32(undo_buf, undo_pos); + default: + /* should never happen */ + BLI_assert(0); + unicode= 0; + } + + return unicode; } void txt_do_undo(Text *text) @@ -1792,13 +2019,8 @@ void txt_do_undo(Text *text) text->undo_pos--; text->undo_pos--; - linep= text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - - charp= text->undo_buf[text->undo_pos]; text->undo_pos--; - charp= (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos); + charp= txt_undo_read_uint16(text->undo_buf, &text->undo_pos); if (op==UNDO_CTO) { txt_move_toline(text, linep, 0); @@ -1812,23 +2034,23 @@ void txt_do_undo(Text *text) text->undo_pos--; break; - case UNDO_INSERT: + case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: txt_backspace_char(text); - text->undo_pos--; + text->undo_pos-= op - UNDO_INSERT_1 + 1; text->undo_pos--; break; - case UNDO_BS: - txt_add_char(text, text->undo_buf[text->undo_pos]); - text->undo_pos--; + case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: + charp = op - UNDO_BS_1 + 1; + txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); text->undo_pos--; - break; - - case UNDO_DEL: - txt_add_char(text, text->undo_buf[text->undo_pos]); + break; + + case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: + charp = op - UNDO_DEL_1 + 1; + txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); txt_move_left(text, 0); text->undo_pos--; - text->undo_pos--; break; case UNDO_SWAP: @@ -1836,10 +2058,7 @@ void txt_do_undo(Text *text) break; case UNDO_DBLOCK: - linep= text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos); buf= MEM_mallocN(linep+1, "dblock buffer"); for (i=0; i < linep; i++){ @@ -1863,25 +2082,31 @@ void txt_do_undo(Text *text) } text->curc= holdc; - linep= text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; text->undo_pos--; break; case UNDO_IBLOCK: - linep= text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - + linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos); txt_delete_sel(text); + + /* txt_backspace_char removes utf8-characters, not bytes */ + buf= MEM_mallocN(linep+1, "iblock buffer"); + for (i=0; i < linep; i++){ + buf[(linep-1)-i]= text->undo_buf[text->undo_pos]; + text->undo_pos--; + } + buf[i]= 0; + linep= txt_utf8_len(buf); + MEM_freeN(buf); + while (linep>0) { txt_backspace_char(text); - text->undo_pos--; linep--; } @@ -1897,30 +2122,23 @@ void txt_do_undo(Text *text) case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: - linep= text->undo_buf[text->undo_pos]; text->undo_pos--; - linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos); //linep is now the end line of the selection - charp = text->undo_buf[text->undo_pos]; text->undo_pos--; - charp = (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); //charp is the last char selected or text->line->len - //set the selcetion for this now + + //set the selection for this now text->selc = charp; text->sell = text->lines.first; for (i= 0; i < linep; i++) { text->sell = text->sell->next; } - linep= text->undo_buf[text->undo_pos]; text->undo_pos--; - linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; - linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos); //first line to be selected - charp = text->undo_buf[text->undo_pos]; text->undo_pos--; - charp = (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); //first postion to be selected text->curc = charp; text->curl = text->lines.first; @@ -2014,22 +2232,22 @@ void txt_do_redo(Text *text) txt_move_down(text, 1); break; - case UNDO_INSERT: - text->undo_pos++; - txt_add_char(text, text->undo_buf[text->undo_pos]); + case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: text->undo_pos++; + charp = op - UNDO_INSERT_1 + 1; + txt_add_char(text, txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp)); break; - case UNDO_BS: + case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: text->undo_pos++; txt_backspace_char(text); - text->undo_pos++; + text->undo_pos+= op - UNDO_BS_1 + 1; break; - case UNDO_DEL: + case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: text->undo_pos++; txt_delete_char(text); - text->undo_pos++; + text->undo_pos+= op - UNDO_DEL_1 + 1; break; case UNDO_SWAP: @@ -2049,15 +2267,8 @@ void txt_do_redo(Text *text) text->undo_pos++; - charp= text->undo_buf[text->undo_pos]; - text->undo_pos++; - charp= charp+(text->undo_buf[text->undo_pos]<<8); - - text->undo_pos++; - linep= text->undo_buf[text->undo_pos]; text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; + charp= txt_redo_read_uint16(text->undo_buf, &text->undo_pos); + linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos); if (op==UNDO_CTO) { txt_move_toline(text, linep, 0); @@ -2072,12 +2283,9 @@ void txt_do_redo(Text *text) case UNDO_DBLOCK: text->undo_pos++; - linep= text->undo_buf[text->undo_pos]; text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; - + linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos); txt_delete_sel(text); + text->undo_pos+=linep; text->undo_pos++; @@ -2089,10 +2297,7 @@ void txt_do_redo(Text *text) case UNDO_IBLOCK: text->undo_pos++; - linep= text->undo_buf[text->undo_pos]; text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; + linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos); buf= MEM_mallocN(linep+1, "iblock buffer"); memcpy (buf, &text->undo_buf[text->undo_pos], linep); @@ -2102,26 +2307,21 @@ void txt_do_redo(Text *text) txt_insert_buf(text, buf); MEM_freeN(buf); - linep= text->undo_buf[text->undo_pos]; text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; - linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; - (void)linep; - + text->undo_pos++; + text->undo_pos++; + text->undo_pos++; + text->undo_pos++; break; + case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: text->undo_pos++; - charp = text->undo_buf[text->undo_pos]; text->undo_pos++; - charp = charp+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; + charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); //charp is the first char selected or 0 - linep= text->undo_buf[text->undo_pos]; text->undo_pos++; - linep = linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; - linep = linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; - linep = linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; + linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos); //linep is now the first line of the selection //set the selcetion for this now text->curc = charp; @@ -2130,13 +2330,10 @@ void txt_do_redo(Text *text) text->curl = text->curl->next; } - charp = text->undo_buf[text->undo_pos]; text->undo_pos++; - charp = charp+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; + charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); //last postion to be selected - linep= text->undo_buf[text->undo_pos]; text->undo_pos++; - linep = linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; - linep = linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; - linep = linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; + + linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos); //Last line to be selected text->selc = charp; @@ -2203,8 +2400,7 @@ void txt_split_curline (Text *text) left[text->curc]=0; right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string"); - if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc); - right[text->curl->len - text->curc]=0; + memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc+1); MEM_freeN(text->curl->line); if (text->curl->format) MEM_freeN(text->curl->format); @@ -2228,7 +2424,7 @@ void txt_split_curline (Text *text) txt_clean_text(text); txt_pop_sel(text); - if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, '\n'); + if(!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n'); } static void txt_delete_line (Text *text, TextLine *line) @@ -2296,9 +2492,9 @@ static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb) txt_clean_text(text); } -void txt_delete_char (Text *text) +void txt_delete_char(Text *text) { - char c='\n'; + unsigned int c='\n'; if (!text) return; if (!text->curl) return; @@ -2314,12 +2510,14 @@ void txt_delete_char (Text *text) txt_pop_sel(text); } } else { /* Just deleting a char */ - int i= text->curc; + size_t c_len = 0; + TextMarker *mrk; + c= BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len); - TextMarker *mrk= txt_find_marker_region(text, text->curl, i-1, text->curl->len, 0, 0); + mrk= txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); if (mrk) { int lineno= mrk->lineno; - if (mrk->end==i) { + if (mrk->end==text->curc) { if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { txt_clear_markers(text, mrk->group, TMARK_TEMP); } else { @@ -2328,18 +2526,15 @@ void txt_delete_char (Text *text) return; } do { - if (mrk->start>i) mrk->start--; - mrk->end--; + if (mrk->start>text->curc) mrk->start-= c_len; + mrk->end-= c_len; mrk= mrk->next; } while (mrk && mrk->lineno==lineno); } - c= text->curl->line[i]; - while(i< text->curl->len) { - text->curl->line[i]= text->curl->line[i+1]; - i++; - } - text->curl->len--; + memmove(text->curl->line+text->curc, text->curl->line+text->curc+c_len, text->curl->len-text->curc-c_len+1); + + text->curl->len-= c_len; txt_pop_sel(text); } @@ -2347,7 +2542,7 @@ void txt_delete_char (Text *text) txt_make_dirty(text); txt_clean_text(text); - if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c); + if(!undoing) txt_undo_add_charop(text, UNDO_DEL_1, c); } void txt_delete_word (Text *text) @@ -2358,7 +2553,7 @@ void txt_delete_word (Text *text) void txt_backspace_char (Text *text) { - char c='\n'; + unsigned int c='\n'; if (!text) return; if (!text->curl) return; @@ -2378,12 +2573,15 @@ void txt_backspace_char (Text *text) txt_pop_sel(text); } else { /* Just backspacing a char */ - int i= text->curc-1; + size_t c_len = 0; + TextMarker *mrk; + char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc); + c= BLI_str_utf8_as_unicode_and_size(prev, &c_len); - TextMarker *mrk= txt_find_marker_region(text, text->curl, i, text->curl->len, 0, 0); + mrk= txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); if (mrk) { int lineno= mrk->lineno; - if (mrk->start==i+1) { + if (mrk->start==text->curc) { if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { txt_clear_markers(text, mrk->group, TMARK_TEMP); } else { @@ -2392,19 +2590,16 @@ void txt_backspace_char (Text *text) return; } do { - if (mrk->start>i) mrk->start--; - mrk->end--; + if (mrk->start>text->curc - c_len) mrk->start-= c_len; + mrk->end-= c_len; mrk= mrk->next; } while (mrk && mrk->lineno==lineno); } - c= text->curl->line[i]; - while(i< text->curl->len) { - text->curl->line[i]= text->curl->line[i+1]; - i++; - } - text->curl->len--; - text->curc--; + memcpy(text->curl->line + text->curc - c_len, text->curl->line + text->curc, text->curl->len-text->curc+1); + + text->curl->len-= c_len; + text->curc-= c_len; txt_pop_sel(text); } @@ -2412,7 +2607,7 @@ void txt_backspace_char (Text *text) txt_make_dirty(text); txt_clean_text(text); - if(!undoing) txt_undo_add_charop(text, UNDO_BS, c); + if(!undoing) txt_undo_add_charop(text, UNDO_BS_1, c); } void txt_backspace_word (Text *text) @@ -2436,11 +2631,12 @@ static void txt_convert_tab_to_spaces (Text *text) txt_insert_buf(text, sb); } -static int txt_add_char_intern (Text *text, char add, int replace_tabs) +static int txt_add_char_intern (Text *text, unsigned int add, int replace_tabs) { - int len, lineno; - char *tmp; + int lineno; + char *tmp, ch[BLI_UTF8_MAX]; TextMarker *mrk; + size_t add_len; if (!text) return 0; if (!text->curl) return 0; @@ -2458,43 +2654,42 @@ static int txt_add_char_intern (Text *text, char add, int replace_tabs) txt_delete_sel(text); + add_len = BLI_str_utf8_from_unicode(add, ch); mrk= txt_find_marker_region(text, text->curl, text->curc-1, text->curl->len, 0, 0); if (mrk) { lineno= mrk->lineno; do { - if (mrk->start>text->curc) mrk->start++; - mrk->end++; + if (mrk->start>text->curc) mrk->start+= add_len; + mrk->end+= add_len; mrk= mrk->next; } while (mrk && mrk->lineno==lineno); } - tmp= MEM_mallocN(text->curl->len+2, "textline_string"); - - if(text->curc) memcpy(tmp, text->curl->line, text->curc); - tmp[text->curc]= add; + tmp= MEM_mallocN(text->curl->len+add_len+1, "textline_string"); - len= text->curl->len - text->curc; - if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); - tmp[text->curl->len+1]=0; + memcpy(tmp, text->curl->line, text->curc); + memcpy(tmp+text->curc, ch, add_len); + memcpy(tmp+text->curc+add_len, text->curl->line+text->curc, text->curl->len-text->curc+1); + make_new_line(text->curl, tmp); - text->curc++; + text->curc+= add_len; txt_pop_sel(text); txt_make_dirty(text); txt_clean_text(text); - if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, add); + if(!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); return 1; } -int txt_add_char (Text *text, char add) +int txt_add_char (Text *text, unsigned int add) { return txt_add_char_intern(text, add, text->flags & TXT_TABSTOSPACES); } -int txt_add_raw_char (Text *text, char add) +int txt_add_raw_char (Text *text, unsigned int add) { return txt_add_char_intern(text, add, 0); } @@ -2505,34 +2700,48 @@ void txt_delete_selected(Text *text) txt_make_dirty(text); } -int txt_replace_char (Text *text, char add) +int txt_replace_char (Text *text, unsigned int add) { - char del; + unsigned int del; + size_t del_size = 0, add_size; + char ch[BLI_UTF8_MAX]; if (!text) return 0; if (!text->curl) return 0; /* If text is selected or we're at the end of the line just use txt_add_char */ if (text->curc==text->curl->len || txt_has_sel(text) || add=='\n') { - TextMarker *mrk; int i= txt_add_char(text, add); - mrk= txt_find_marker(text, text->curl, text->curc, 0, 0); - if (mrk && mrk->end==text->curc) mrk->end--; + TextMarker *mrk= txt_find_marker(text, text->curl, text->curc, 0, 0); + if (mrk) BLI_freelinkN(&text->markers, mrk); return i; } - del= text->curl->line[text->curc]; - text->curl->line[text->curc]= (unsigned char) add; - text->curc++; - txt_pop_sel(text); + del= BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size); + add_size= BLI_str_utf8_from_unicode(add, ch); + + if (add_size > del_size) { + char *tmp= MEM_mallocN(text->curl->len+add_size-del_size+1, "textline_string"); + memcpy(tmp, text->curl->line, text->curc); + memcpy(tmp+text->curc+add_size, text->curl->line+text->curc+del_size, text->curl->len-text->curc-del_size+1); + MEM_freeN(text->curl->line); + text->curl->line = tmp; + } else if (add_size < del_size) { + char *tmp= text->curl->line; + memmove(tmp+text->curc+add_size, tmp+text->curc+del_size, text->curl->len-text->curc-del_size+1); + } + + memcpy(text->curl->line + text->curc, ch, add_size); + text->curc+= add_size; + txt_pop_sel(text); txt_make_dirty(text); txt_clean_text(text); /* Should probably create a new op for this */ if(!undoing) { - txt_undo_add_charop(text, UNDO_DEL, del); - txt_undo_add_charop(text, UNDO_INSERT, add); + txt_undo_add_charop(text, UNDO_DEL_1, del); + txt_undo_add_charop(text, UNDO_INSERT_1, add); } return 1; } @@ -2548,15 +2757,19 @@ void txt_indent(Text *text) /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; + if (ELEM3(NULL, text, text->curl, text->sell)) { + return; + } + + if (!text) return; + if (!text->curl) return; + if (!text->sell) return; + /* insert spaces rather than tabs */ if (text->flags & TXT_TABSTOSPACES){ add = tab_to_spaces; indentlen = spaceslen; } - - if (!text) return; - if (!text->curl) return; - if (!text->sell) return; num = 0; while (TRUE) @@ -2609,16 +2822,16 @@ void txt_unindent(Text *text) /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; + if (!text) return; + if (!text->curl) return; + if (!text->sell) return; + /* insert spaces rather than tabs */ if (text->flags & TXT_TABSTOSPACES){ remove = tab_to_spaces; indent = spaceslen; } - if (!text) return; - if (!text->curl) return; - if (!text->sell) return; - while(TRUE) { int i = 0; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 7051376a1f4..88858c9ff51 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -168,7 +168,7 @@ PluginTex *add_plugin_tex(char *str) pit= MEM_callocN(sizeof(PluginTex), "plugintex"); - strcpy(pit->name, str); + BLI_strncpy(pit->name, str, sizeof(pit->name)); open_plugin_tex(pit); if(pit->doit==NULL) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 7bfc7a8ef87..e6032a50854 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -70,6 +70,10 @@ typedef struct MovieDistortion { struct libmv_CameraIntrinsics *intrinsics; } MovieDistortion; +static struct { + ListBase tracks; +} tracking_clipboard; + /*********************** common functions *************************/ void BKE_tracking_init_settings(MovieTracking *tracking) @@ -238,6 +242,7 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr track->margin= settings->default_margin; track->pattern_match= settings->default_pattern_match; track->frames_limit= settings->default_frames_limit; + track->flag= settings->default_flag; memset(&marker, 0, sizeof(marker)); marker.pos[0]= x; @@ -261,7 +266,7 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr return track; } -void BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker) +MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker) { MovieTrackingMarker *old_marker= NULL; @@ -270,6 +275,8 @@ void BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker * if(old_marker) { *old_marker= *marker; + + return old_marker; } else { int a= track->markersnr; @@ -287,6 +294,8 @@ void BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker * track->markers[a+1]= *marker; track->last_marker= a+1; + + return &track->markers[a+1]; } } @@ -387,6 +396,13 @@ int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr) return BKE_tracking_exact_marker(track, framenr) != 0; } +int BKE_tracking_has_enabled_marker(MovieTrackingTrack *track, int framenr) +{ + MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + + return marker && (marker->flag & MARKER_DISABLED) == 0; +} + void BKE_tracking_free_track(MovieTrackingTrack *track) { if(track->markers) MEM_freeN(track->markers); @@ -574,10 +590,76 @@ void BKE_tracking_free(MovieTracking *tracking) BKE_tracking_distortion_destroy(tracking->camera.intrinsics); } +static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track) +{ + MovieTrackingTrack *new_track; + + new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track"); + + *new_track= *track; + new_track->next = new_track->prev = NULL; + + new_track->markers = MEM_dupallocN(new_track->markers); + + return new_track; +} + +/*********************** clipboard *************************/ + +void BKE_tracking_free_clipboard(void) +{ + MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track; + + while (track) { + next_track = track->next; + + BKE_tracking_free_track(track); + MEM_freeN(track); + + track = next_track; + } +} + +void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object) +{ + ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; + + while (track) { + if (TRACK_SELECTED(track)) { + MovieTrackingTrack *new_track = duplicate_track(track); + + BLI_addtail(&tracking_clipboard.tracks, new_track); + } + + track = track->next; + } +} + +int BKE_tracking_clipboard_has_tracks(void) +{ + return tracking_clipboard.tracks.first != NULL; +} + +void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object) +{ + ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); + MovieTrackingTrack *track = tracking_clipboard.tracks.first; + + while (track) { + MovieTrackingTrack *new_track = duplicate_track(track); + + BLI_addtail(tracksbase, new_track); + BKE_track_unique_name(tracksbase, new_track); + + track = track->next; + } +} + /*********************** tracks map *************************/ typedef struct TracksMap { - char object_name[32]; + char object_name[MAX_NAME]; int is_camera; int num_tracks; @@ -595,7 +677,7 @@ static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num { TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap"); - strcpy(map->object_name, object_name); + BLI_strncpy(map->object_name, object_name, sizeof(map->object_name)); map->is_camera= is_camera; map->num_tracks= num_tracks; @@ -696,9 +778,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) } } - new_track= MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track"); - *new_track= *track; - new_track->markers= MEM_dupallocN(new_track->markers); + new_track= duplicate_track(track); BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */ BLI_ghash_insert(map->hash, track, new_track); @@ -938,19 +1018,19 @@ void BKE_tracking_context_free(MovieTrackingContext *context) /* zap channels from the imbuf that are disabled by the user. this can lead to * better tracks sometimes. however, instead of simply zeroing the channels * out, do a partial grayscale conversion so the display is better. */ -static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) +void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, int grayscale) { int x, y; float scale; - if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0 && !grayscale) + if(!disable_red && !disable_green && !disable_blue && !grayscale) return; /* If only some components are selected, it's important to rescale the result * appropriately so that e.g. if only blue is selected, it's not zeroed out. */ - scale = ((track->flag&TRACK_DISABLE_RED ) ? 0.0f : 0.2126f) + - ((track->flag&TRACK_DISABLE_GREEN) ? 0.0f : 0.7152f) + - ((track->flag&TRACK_DISABLE_BLUE) ? 0.0f : 0.0722f); + scale = (disable_red ? 0.0f : 0.2126f) + + (disable_green ? 0.0f : 0.7152f) + + (disable_blue ? 0.0f : 0.0722f); for(y= 0; y<ibuf->y; y++) { for (x= 0; x<ibuf->x; x++) { @@ -958,9 +1038,9 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g if(ibuf->rect_float) { float *rrgbf= ibuf->rect_float + pixel*4; - float r = (track->flag&TRACK_DISABLE_RED) ? 0.0f : rrgbf[0]; - float g = (track->flag&TRACK_DISABLE_GREEN) ? 0.0f : rrgbf[1]; - float b = (track->flag&TRACK_DISABLE_BLUE) ? 0.0f : rrgbf[2]; + float r = disable_red ? 0.0f : rrgbf[0]; + float g = disable_green ? 0.0f : rrgbf[1]; + float b = disable_blue ? 0.0f : rrgbf[2]; if (grayscale) { float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale; rrgbf[0] = rrgbf[1] = rrgbf[2] = gray; @@ -971,9 +1051,9 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g } } else { char *rrgb= (char*)ibuf->rect + pixel*4; - char r = (track->flag&TRACK_DISABLE_RED) ? 0 : rrgb[0]; - char g = (track->flag&TRACK_DISABLE_GREEN) ? 0 : rrgb[1]; - char b = (track->flag&TRACK_DISABLE_BLUE) ? 0 : rrgb[2]; + char r = disable_red ? 0 : rrgb[0]; + char g = disable_green ? 0 : rrgb[1]; + char b = disable_blue ? 0 : rrgb[2]; if (grayscale) { float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale; rrgb[0] = rrgb[1] = rrgb[2] = gray; @@ -987,29 +1067,40 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g } } +static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) +{ + BKE_tracking_disable_imbuf_channels(ibuf, track->flag&TRACK_DISABLE_RED, + track->flag&TRACK_DISABLE_GREEN, track->flag&TRACK_DISABLE_BLUE, grayscale); +} + static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2]) { ImBuf *tmpibuf; int x, y; - int x1, y1, x2, y2, w, h; + int x1, y1, w, h; float mpos[2]; copy_v2_v2(mpos, marker->pos); if(anchored) add_v2_v2(mpos, track->offset); + if(pos) + zero_v2(pos); + x= mpos[0]*ibuf->x; y= mpos[1]*ibuf->y; - x1= x-(int)(-min[0]*ibuf->x); - y1= y-(int)(-min[1]*ibuf->y); - x2= x+(int)(max[0]*ibuf->x); - y2= y+(int)(max[1]*ibuf->y); - /* dimensions should be odd */ - w= (x2-x1)|1; - h= (y2-y1)|1; + w= (max[0]-min[0])*ibuf->x; + h= (max[1]-min[1])*ibuf->y; + + w= w|1; + h= h|1; + + x1= x-(int)(w/2.0f); + y1= y-(int)(h/2.0f); + /* dimensions should be odd */ tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect); IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2); @@ -1023,10 +1114,11 @@ static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTracki origin[1]= y1-margin; } - if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || - (track->flag & TRACK_DISABLE_RED) || - (track->flag & TRACK_DISABLE_GREEN) || - (track->flag & TRACK_DISABLE_BLUE) ) { + if((track->flag & TRACK_PREVIEW_GRAYSCALE) || + (track->flag & TRACK_DISABLE_RED) || + (track->flag & TRACK_DISABLE_GREEN) || + (track->flag & TRACK_DISABLE_BLUE)) + { disable_imbuf_channels(tmpibuf, track, 1 /* grayscale */); } @@ -1094,10 +1186,11 @@ static unsigned char *get_ucharbuf(ImBuf *ibuf) int pixel= ibuf->x*y + x; if(ibuf->rect_float) { - float *rrgbf= ibuf->rect_float + pixel*4; - *cp= FTOCHAR(0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2]); + const float *rrgbf= ibuf->rect_float + pixel*4; + const float grey_f= 0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2]; + *cp= FTOCHAR(grey_f); } else { - unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4; + const unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4; *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2]; } cp++; @@ -1133,7 +1226,7 @@ static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr) user.framenr= framenr; - ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag); + ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag, MOVIECLIP_CACHE_SKIP); return ibuf; } @@ -1237,7 +1330,7 @@ int BKE_tracking_next(MovieTrackingContext *context) if(context->backwards) context->user.framenr--; else context->user.framenr++; - ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag); + ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP); if(!ibuf_new) return 0; @@ -1443,7 +1536,7 @@ typedef struct MovieReconstructContext { struct libmv_Reconstruction *reconstruction; #endif - char object_name[32]; + char object_name[MAX_NAME]; int is_camera; float focal_length; @@ -1656,8 +1749,8 @@ static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tra track= tracksbase->first; while(track) { - if(BKE_tracking_has_marker(track, frame1)) - if(BKE_tracking_has_marker(track, frame2)) + if(BKE_tracking_has_enabled_marker(track, frame1)) + if(BKE_tracking_has_enabled_marker(track, frame2)) tot++; track= track->next; @@ -1673,7 +1766,7 @@ int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *o ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); if(count_tracks_on_both_keyframes(tracking, tracksbase)<8) { - BLI_strncpy(error_msg, "At least 8 tracks on both of keyframes are needed for reconstruction", error_size); + BLI_strncpy(error_msg, "At least 8 common tracks on both of keyframes are needed for reconstruction", error_size); return 0; } @@ -1698,7 +1791,7 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking * int sfra= INT_MAX, efra= INT_MIN; MovieTrackingTrack *track; - strcpy(context->object_name, object->name); + BLI_strncpy(context->object_name, object->name, sizeof(context->object_name)); context->is_camera = object->flag&TRACKING_OBJECT_CAMERA; context->tracks_map= tracks_map_new(context->object_name, context->is_camera, num_tracks, 0); @@ -1753,7 +1846,7 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking * context->k1= camera->k1; context->k2= camera->k2; - context->k2= camera->k2; + context->k3= camera->k3; return context; } diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index da64c464dce..dbb37ad9c1d 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -52,7 +52,8 @@ /* callbacks */ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports); static void end_avi(void); -static int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports); +static int append_avi(RenderData *rd, int start_frame, int frame, int *pixels, + int rectx, int recty, ReportList *reports); static void filepath_avi(char *string, RenderData *rd); /* ********************** general blender movie support ***************************** */ @@ -121,7 +122,6 @@ bMovieHandle *BKE_get_movie_handle(const char imtype) static AviMovie *avi=NULL; -static int sframe; static void filepath_avi (char *string, RenderData *rd) { @@ -150,7 +150,6 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL filepath_avi(name, rd); - sframe = (rd->sfra); x = rectx; y = recty; @@ -183,7 +182,8 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL return 1; } -static int append_avi(RenderData *UNUSED(rd), int frame, int *pixels, int rectx, int recty, ReportList *UNUSED(reports)) +static int append_avi(RenderData *UNUSED(rd), int start_frame, int frame, int *pixels, + int rectx, int recty, ReportList *UNUSED(reports)) { unsigned int *rt1, *rt2, *rectot; int x, y; @@ -212,8 +212,8 @@ static int append_avi(RenderData *UNUSED(rd), int frame, int *pixels, int rectx, } } - AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32, rectot, rectx*recty*4); -// printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe); + AVI_write_frame (avi, (frame-start_frame), AVI_FORMAT_RGB32, rectot, rectx*recty*4); +// printf ("added frame %3d (frame %3d in avi): ", frame, frame-start_frame); return 1; } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index bf547584b9e..0b043e26ab7 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -236,13 +236,13 @@ static const char** get_file_extensions(int format) } /* Write a frame to the output file */ -static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports) +static int write_video_frame(RenderData *rd, int cfra, AVFrame* frame, ReportList *reports) { int outsize = 0; int ret, success= 1; AVCodecContext* c = video_stream->codec; - frame->pts = rd->cfra - rd->sfra; + frame->pts = cfra; if (rd->mode & R_FIELDS) { frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0); @@ -918,7 +918,7 @@ static void write_audio_frames(double to_pts) } #endif -int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) +int append_ffmpeg(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports) { AVFrame* avframe; int success = 1; @@ -933,7 +933,7 @@ int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, if(video_stream) { avframe= generate_video_frame((unsigned char*) pixels, reports); - success= (avframe && write_video_frame(rd, avframe, reports)); + success= (avframe && write_video_frame(rd, frame - start_frame, avframe, reports)); if (ffmpeg_autosplit) { if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) { @@ -1077,9 +1077,9 @@ IDProperty *ffmpeg_property_add(RenderData *rd, const char *type, int opt_index, } if (parent_index) { - sprintf(name, "%s:%s", parent->name, o->name); + BLI_snprintf(name, sizeof(name), "%s:%s", parent->name, o->name); } else { - strcpy(name, o->name); + BLI_strncpy(name, o->name, sizeof(name)); } fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n", @@ -1200,6 +1200,56 @@ int ffmpeg_property_add_string(RenderData *rd, const char * type, const char * s return 1; } +static void ffmpeg_set_expert_options(RenderData *rd, int preset) +{ + if(rd->ffcodecdata.properties) + IDP_FreeProperty(rd->ffcodecdata.properties); + + if(preset == FFMPEG_PRESET_H264) { + /* + * All options here are for x264, but must be set via ffmpeg. + * The names are therefore different - Search for "x264 to FFmpeg option mapping" + * to get a list. + */ + + /* + * Use CABAC coder. Using "coder:1", which should be equivalent, + * crashes Blender for some reason. Either way - this is no big deal. + */ + ffmpeg_property_add_string(rd, "video", "coder:vlc"); + + /* + * The other options were taken from the libx264-default.preset + * included in the ffmpeg distribution. + */ + ffmpeg_property_add_string(rd, "video", "flags:loop"); + ffmpeg_property_add_string(rd, "video", "cmp:chroma"); + ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); + ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); + ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); + ffmpeg_property_add_string(rd, "video", "me:hex"); + ffmpeg_property_add_string(rd, "video", "subq:6"); + ffmpeg_property_add_string(rd, "video", "me_range:16"); + ffmpeg_property_add_string(rd, "video", "qdiff:4"); + ffmpeg_property_add_string(rd, "video", "keyint_min:25"); + ffmpeg_property_add_string(rd, "video", "sc_threshold:40"); + ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71"); + ffmpeg_property_add_string(rd, "video", "b_strategy:1"); + ffmpeg_property_add_string(rd, "video", "bf:3"); + ffmpeg_property_add_string(rd, "video", "refs:2"); + ffmpeg_property_add_string(rd, "video", "qcomp:0.6"); + ffmpeg_property_add_string(rd, "video", "directpred:3"); + ffmpeg_property_add_string(rd, "video", "trellis:0"); + ffmpeg_property_add_string(rd, "video", "flags2:wpred"); + ffmpeg_property_add_string(rd, "video", "flags2:dct8x8"); + ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); + ffmpeg_property_add_string(rd, "video", "wpredp:2"); + + if(rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) + ffmpeg_property_add_string(rd, "video", "cqp:0"); + } +} + void ffmpeg_set_preset(RenderData *rd, int preset) { int isntsc = (rd->frs_sec != 25); @@ -1267,47 +1317,7 @@ void ffmpeg_set_preset(RenderData *rd, int preset) rd->ffcodecdata.mux_packet_size = 2048; rd->ffcodecdata.mux_rate = 10080000; - /* - * All options here are for x264, but must be set via ffmpeg. - * The names are therefore different - Search for "x264 to FFmpeg option mapping" - * to get a list. - */ - - /* - * Use CABAC coder. Using "coder:1", which should be equivalent, - * crashes Blender for some reason. Either way - this is no big deal. - */ - ffmpeg_property_add_string(rd, "video", "coder:vlc"); - - /* - * The other options were taken from the libx264-default.preset - * included in the ffmpeg distribution. - */ - ffmpeg_property_add_string(rd, "video", "flags:loop"); - ffmpeg_property_add_string(rd, "video", "cmp:chroma"); - ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); - ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); - ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); - ffmpeg_property_add_string(rd, "video", "me:hex"); - ffmpeg_property_add_string(rd, "video", "subq:6"); - ffmpeg_property_add_string(rd, "video", "me_range:16"); - ffmpeg_property_add_string(rd, "video", "qdiff:4"); - ffmpeg_property_add_string(rd, "video", "keyint_min:25"); - ffmpeg_property_add_string(rd, "video", "sc_threshold:40"); - ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71"); - ffmpeg_property_add_string(rd, "video", "b_strategy:1"); - ffmpeg_property_add_string(rd, "video", "bf:3"); - ffmpeg_property_add_string(rd, "video", "refs:2"); - ffmpeg_property_add_string(rd, "video", "qcomp:0.6"); - ffmpeg_property_add_string(rd, "video", "directpred:3"); - ffmpeg_property_add_string(rd, "video", "trellis:0"); - ffmpeg_property_add_string(rd, "video", "flags2:wpred"); - ffmpeg_property_add_string(rd, "video", "flags2:dct8x8"); - ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); - ffmpeg_property_add_string(rd, "video", "wpredp:2"); - - // This makes x264 output lossless. Will be a separate option later. - //ffmpeg_property_add_string(rd, "video", "cqp:0"); + ffmpeg_set_expert_options(rd, preset); break; case FFMPEG_PRESET_THEORA: @@ -1378,4 +1388,11 @@ void ffmpeg_verify_image_type(RenderData *rd, ImageFormatData *imf) } } +void ffmpeg_verify_lossless_format(RenderData *rd, ImageFormatData *imf) +{ + if(imf->imtype == R_IMF_IMTYPE_H264) { + ffmpeg_set_expert_options(rd, FFMPEG_PRESET_H264); + } +} + #endif diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index ae65b913283..c163155c8fb 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -310,7 +310,7 @@ int frameserver_loop(RenderData *rd, ReportList *UNUSED(reports)) } } - len = recv(connsock, buf, 4095, 0); + len = recv(connsock, buf, sizeof(buf) - 1, 0); if (len < 0) { return -1; @@ -362,7 +362,8 @@ static void serve_ppm(int *pixels, int rectx, int recty) connsock = -1; } -int append_frameserver(RenderData *UNUSED(rd), int frame, int *pixels, int rectx, int recty, ReportList *UNUSED(reports)) +int append_frameserver(RenderData *UNUSED(rd), int UNUSED(start_frame), int frame, int *pixels, + int rectx, int recty, ReportList *UNUSED(reports)) { fprintf(stderr, "Serving frame: %d\n", frame); if (write_ppm) { |