Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDalai Felinto <dfelinto@gmail.com>2012-02-02 03:22:55 +0400
committerDalai Felinto <dfelinto@gmail.com>2012-02-02 03:22:55 +0400
commit28f1fdd39bbb11b1081594e2f41bebef77a31518 (patch)
tree3475d4f0b15d7ba8e59150fec25adc582ae62afb /source/blender/blenkernel/intern
parent6b39a476cbe83febfe67daa31be6fade83194c7a (diff)
parentd882f05b824f4111ef5c319c89a2f85b1773c579 (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')
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c234
-rw-r--r--source/blender/blenkernel/intern/anim.c11
-rw-r--r--source/blender/blenkernel/intern/armature.c367
-rw-r--r--source/blender/blenkernel/intern/boids.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c571
-rw-r--r--source/blender/blenkernel/intern/cloth.c63
-rw-r--r--source/blender/blenkernel/intern/colortools.c2
-rw-r--r--source/blender/blenkernel/intern/constraint.c80
-rw-r--r--source/blender/blenkernel/intern/context.c6
-rw-r--r--source/blender/blenkernel/intern/curve.c5
-rw-r--r--source/blender/blenkernel/intern/customdata.c2
-rw-r--r--source/blender/blenkernel/intern/deform.c24
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c20
-rw-r--r--source/blender/blenkernel/intern/displist.c9
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c499
-rw-r--r--source/blender/blenkernel/intern/image.c19
-rw-r--r--source/blender/blenkernel/intern/image_gen.c15
-rw-r--r--source/blender/blenkernel/intern/implicit.c3
-rw-r--r--source/blender/blenkernel/intern/ipo.c14
-rw-r--r--source/blender/blenkernel/intern/key.c2
-rw-r--r--source/blender/blenkernel/intern/lattice.c109
-rw-r--r--source/blender/blenkernel/intern/library.c44
-rw-r--r--source/blender/blenkernel/intern/material.c7
-rw-r--r--source/blender/blenkernel/intern/mball.c10
-rw-r--r--source/blender/blenkernel/intern/mesh.c14
-rw-r--r--source/blender/blenkernel/intern/modifier.c42
-rw-r--r--source/blender/blenkernel/intern/movieclip.c395
-rw-r--r--source/blender/blenkernel/intern/multires.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c38
-rw-r--r--source/blender/blenkernel/intern/node.c58
-rw-r--r--source/blender/blenkernel/intern/object.c51
-rw-r--r--source/blender/blenkernel/intern/packedFile.c2
-rw-r--r--source/blender/blenkernel/intern/paint.c5
-rw-r--r--source/blender/blenkernel/intern/particle.c4
-rw-r--r--source/blender/blenkernel/intern/particle_system.c14
-rw-r--r--source/blender/blenkernel/intern/pointcache.c25
-rw-r--r--source/blender/blenkernel/intern/property.c2
-rw-r--r--source/blender/blenkernel/intern/sca.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c8
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c67
-rw-r--r--source/blender/blenkernel/intern/sequencer.c37
-rw-r--r--source/blender/blenkernel/intern/smoke.c14
-rw-r--r--source/blender/blenkernel/intern/softbody.c17
-rw-r--r--source/blender/blenkernel/intern/sound.c31
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c45
-rw-r--r--source/blender/blenkernel/intern/text.c839
-rw-r--r--source/blender/blenkernel/intern/texture.c2
-rw-r--r--source/blender/blenkernel/intern/tracking.c173
-rw-r--r--source/blender/blenkernel/intern/writeavi.c12
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c111
-rw-r--r--source/blender/blenkernel/intern/writeframeserver.c5
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, &timescale);
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 &lt->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) {