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:
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c103
-rw-r--r--source/blender/blenkernel/intern/action.c6
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c17
-rw-r--r--source/blender/blenkernel/intern/armature.c9
-rw-r--r--source/blender/blenkernel/intern/blender.c12
-rw-r--r--source/blender/blenkernel/intern/bpath.c12
-rw-r--r--source/blender/blenkernel/intern/brush.c98
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c294
-rw-r--r--source/blender/blenkernel/intern/camera.c4
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c381
-rw-r--r--source/blender/blenkernel/intern/constraint.c28
-rw-r--r--source/blender/blenkernel/intern/context.c14
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c33
-rw-r--r--source/blender/blenkernel/intern/curve.c296
-rw-r--r--source/blender/blenkernel/intern/deform.c55
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c92
-rw-r--r--source/blender/blenkernel/intern/displist.c211
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c7
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c4
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c86
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/fcurve.c31
-rw-r--r--source/blender/blenkernel/intern/freestyle.c2
-rw-r--r--source/blender/blenkernel/intern/gpencil.c2
-rw-r--r--source/blender/blenkernel/intern/idcode.c2
-rw-r--r--source/blender/blenkernel/intern/idprop.c6
-rw-r--r--source/blender/blenkernel/intern/image.c4
-rw-r--r--source/blender/blenkernel/intern/implicit.c7
-rw-r--r--source/blender/blenkernel/intern/ipo.c8
-rw-r--r--source/blender/blenkernel/intern/lattice.c135
-rw-r--r--source/blender/blenkernel/intern/library.c34
-rw-r--r--source/blender/blenkernel/intern/linestyle.c149
-rw-r--r--source/blender/blenkernel/intern/mask.c2
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c2
-rw-r--r--source/blender/blenkernel/intern/material.c135
-rw-r--r--source/blender/blenkernel/intern/mball.c50
-rw-r--r--source/blender/blenkernel/intern/mesh.c43
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c136
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c57
-rw-r--r--source/blender/blenkernel/intern/modifier.c30
-rw-r--r--source/blender/blenkernel/intern/multires.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c8
-rw-r--r--source/blender/blenkernel/intern/node.c9
-rw-r--r--source/blender/blenkernel/intern/object.c131
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c4
-rw-r--r--source/blender/blenkernel/intern/paint.c105
-rw-r--r--source/blender/blenkernel/intern/particle.c7
-rw-r--r--source/blender/blenkernel/intern/particle_system.c17
-rw-r--r--source/blender/blenkernel/intern/pbvh.c15
-rw-r--r--source/blender/blenkernel/intern/report.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c193
-rw-r--r--source/blender/blenkernel/intern/sca.c4
-rw-r--r--source/blender/blenkernel/intern/scene.c142
-rw-r--r--source/blender/blenkernel/intern/screen.c26
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c303
-rw-r--r--source/blender/blenkernel/intern/sequencer.c77
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c80
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c50
-rw-r--r--source/blender/blenkernel/intern/text.c17
-rw-r--r--source/blender/blenkernel/intern/texture.c273
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c6
-rw-r--r--source/blender/blenkernel/intern/treehash.c2
-rw-r--r--source/blender/blenkernel/intern/unit.c145
-rw-r--r--source/blender/blenkernel/intern/world.c3
-rw-r--r--source/blender/blenkernel/intern/writeavi.c2
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c9
69 files changed, 3036 insertions, 1203 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 6cda0a1bc33..623fb50b62c 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -119,7 +119,7 @@ static void _ehash_insert(EHash *eh, EHEntry *entry)
eh->buckets[hash] = entry;
eh->numEntries++;
- if (eh->numEntries > (numBuckets * 3)) {
+ if (UNLIKELY(eh->numEntries > (numBuckets * 3))) {
EHEntry **oldBuckets = eh->buckets;
eh->curSize = kHashSizes[++eh->curSizeIdx];
@@ -1274,7 +1274,7 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
CCGFace *f = NULL, *fNew;
int j, k, topologyChanged = 0;
- if (numVerts > ss->lenTempArrays) {
+ if (UNLIKELY(numVerts > ss->lenTempArrays)) {
ss->lenTempArrays = (numVerts < ss->lenTempArrays * 2) ? ss->lenTempArrays * 2 : numVerts;
ss->tempVerts = MEM_reallocN(ss->tempVerts, sizeof(*ss->tempVerts) * ss->lenTempArrays);
ss->tempEdges = MEM_reallocN(ss->tempEdges, sizeof(*ss->tempEdges) * ss->lenTempArrays);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index a70238da34e..52ded77b117 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -37,12 +37,14 @@
#include "DNA_cloth_types.h"
#include "DNA_key_types.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
+#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
@@ -500,11 +502,36 @@ void DM_update_materials(DerivedMesh *dm, Object *ob)
dm->mat = MEM_callocN(totmat * sizeof(*dm->mat), "DerivedMesh.mat");
- for (i = 1; i < totmat; i++) {
- dm->mat[i] = give_current_material(ob, i);
+ /* we leave last material as empty - rationale here is being able to index
+ * the materials by using the mf->mat_nr directly and leaving the last
+ * material as NULL in case no materials exist on mesh, so indexing will not fail */
+ for (i = 0; i < totmat - 1; i++) {
+ dm->mat[i] = give_current_material(ob, i + 1);
}
}
+MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr)
+{
+ MTFace *tf_base;
+
+ BLI_assert(mat_nr < dm->totmat);
+
+ if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot &&
+ dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname)
+ {
+ tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
+ dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname);
+ /* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material
+ * texture slot.*/
+ if (!tf_base)
+ tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ }
+ else {
+ tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ }
+
+ return tf_base;
+}
void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
{
@@ -1107,7 +1134,7 @@ static void weightpaint_color(unsigned char r_col[4], DMWeightColorInfo *dm_wcin
static void calc_weightpaint_vert_color(
unsigned char r_col[4],
- MDeformVert *dv,
+ const MDeformVert *dv,
DMWeightColorInfo *dm_wcinfo,
const int defbase_tot, const int defbase_act,
const bool *defbase_sel, const int defbase_sel_tot,
@@ -1122,7 +1149,7 @@ static void calc_weightpaint_vert_color(
bool was_a_nonzero = false;
unsigned int i;
- MDeformWeight *dw = dv->dw;
+ const MDeformWeight *dw = dv->dw;
for (i = dv->totweight; i != 0; i--, dw++) {
/* in multipaint, get the average if auto normalize is inactive
* get the sum if it is active */
@@ -1995,9 +2022,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
previewmd = modifiers_getLastPreview(scene, md, required_mode);
/* even if the modifier doesn't need the data, to make a preview it may */
if (previewmd) {
- if (do_mod_wmcol) {
- previewmask = CD_MASK_MDEFORMVERT;
- }
+ previewmask = CD_MASK_MDEFORMVERT;
}
}
@@ -2473,6 +2498,28 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
return getEditDerivedBMesh(em, obedit, NULL);
}
+/***/
+
+/* get derived mesh from an object, using editbmesh if available. */
+DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+
+ if (for_render) {
+ /* TODO(sergey): use proper derived render here in the future. */
+ return ob->derivedFinal;
+ }
+
+ if (em) {
+ DerivedMesh *dm = em->derivedFinal;
+ return dm;
+ }
+
+ return ob->derivedFinal;
+}
+
+
/* UNUSED */
#if 0
@@ -2533,6 +2580,46 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
#endif
+/* same as above but for vert coords */
+typedef struct {
+ float (*vertexcos)[3];
+ BLI_bitmap *vertex_visit;
+} MappedUserData;
+
+static void make_vertexcos__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ MappedUserData *mappedData = (MappedUserData *)userData;
+
+ if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) {
+ /* we need coord from prototype vertex, not from copies,
+ * assume they stored in the beginning of vertex array stored in DM
+ * (mirror modifier for eg does this) */
+ copy_v3_v3(mappedData->vertexcos[index], co);
+ BLI_BITMAP_ENABLE(mappedData->vertex_visit, index);
+ }
+}
+
+void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int totcos)
+{
+ float (*vertexcos)[3];
+
+ if (dm->foreachMappedVert) {
+ MappedUserData userData;
+ memset(r_cos, 0, sizeof(r_cos) * totcos);
+ userData.vertexcos = r_cos;
+ userData.vertex_visit = BLI_BITMAP_NEW(totcos, "vertexcos flags");
+ dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP);
+ MEM_freeN(userData.vertex_visit);
+ }
+ else {
+ int i;
+ for (i = 0; i < totcos; i++) {
+ dm->getVertCo(dm, i, vertexcos[i]);
+ }
+ }
+}
+
/* ******************* GLSL ******************** */
typedef struct {
@@ -3090,7 +3177,7 @@ static void navmesh_drawColored(DerivedMesh *dm)
static void navmesh_DM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
(void) setDrawOptions;
(void) compareDrawOptions;
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 8f1382dacc3..c6dcca576fb 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -315,7 +315,7 @@ bActionGroup *action_groups_add_new(bAction *act, const char name[])
void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
{
/* sanity checks */
- if (ELEM3(NULL, act, agrp, fcurve))
+ if (ELEM(NULL, act, agrp, fcurve))
return;
/* if no channels anywhere, just add to two lists at the same time */
@@ -417,7 +417,7 @@ void action_groups_remove_channel(bAction *act, FCurve *fcu)
bActionGroup *BKE_action_group_find_name(bAction *act, const char name[])
{
/* sanity checks */
- if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0))
+ if (ELEM(NULL, act, act->groups.first, name) || (name[0] == 0))
return NULL;
/* do string comparisons */
@@ -526,7 +526,7 @@ bPoseChannel *BKE_pose_channel_active(Object *ob)
bArmature *arm = (ob) ? ob->data : NULL;
bPoseChannel *pchan;
- if (ELEM3(NULL, ob, ob->pose, arm)) {
+ if (ELEM(NULL, ob, ob->pose, arm)) {
return NULL;
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 995b2ac5321..5ee82bb5842 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -405,7 +405,7 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha
FCurve *fcu, *fcn = NULL;
/* sanity checks */
- if (ELEM3(NULL, srcAct, dstAct, basepath)) {
+ if (ELEM(NULL, srcAct, dstAct, basepath)) {
if (G.debug & G_DEBUG) {
printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n",
(void *)srcAct, (void *)dstAct, (void *)basepath);
@@ -1062,7 +1062,7 @@ KS_Path *BKE_keyingset_find_path(KeyingSet *ks, ID *id, const char group_name[],
KS_Path *ksp;
/* sanity checks */
- if (ELEM3(NULL, ks, rna_path, id))
+ if (ELEM(NULL, ks, rna_path, id))
return NULL;
/* loop over paths in the current KeyingSet, finding the first one where all settings match
@@ -2338,6 +2338,17 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData
/* 3. free temporary evaluation data that's not used elsewhere */
BLI_freelistN(&estrips);
+
+ /* Tag ID as updated so render engines will recognize changes in data
+ * which is animated but doesn't have actions.
+ */
+ if (ptr->id.data != NULL) {
+ ID *id = ptr->id.data;
+ if (!(id->flag & LIB_ANIM_NO_RECALC)) {
+ id->flag |= LIB_ID_RECALC;
+ DAG_id_type_tag(G.main, GS(id->name));
+ }
+ }
}
/* NLA Evaluation function (mostly for use through do_animdata)
@@ -2392,7 +2403,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
/* Overview of how this system works:
* 1) Depsgraph sorts data as necessary, so that data is in an order that means
- * that all dependencies are resolved before dependants.
+ * that all dependencies are resolved before dependents.
* 2) All normal animation is evaluated, so that drivers have some basis values to
* work with
* a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 95f8426872d..16b5574709e 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -574,7 +574,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
if (do_scale) {
/* correct for scaling when this matrix is used in scaled space */
- mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(result_array[a].mat, iscalemat, result_array[a].mat, scalemat);
}
}
}
@@ -622,8 +622,7 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info
invert_m4_m4(tmat, b_bone_rest[a].mat);
- mul_serie_m4(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat,
- NULL, NULL, NULL);
+ mul_m4_series(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat);
if (use_quaternion)
mat4_to_dquat(&b_bone_dual_quats[a], bone->arm_mat, b_bone_mats[a + 1].mat);
@@ -1042,7 +1041,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
if (!use_quaternion) /* quaternion already is scale corrected */
mul_m3_fl(smat, armature_weight / contrib);
- mul_serie_m3(defMats[i], tmpmat, pre, smat, post, NULL, NULL, NULL, NULL);
+ mul_m3_series(defMats[i], post, smat, pre, tmpmat);
}
}
@@ -1881,7 +1880,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
*/
/* only happens on reload file, but violates depsgraph still... fix! */
- if (ELEM3(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
+ if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
BKE_displist_make_curveTypes(scene, ikData->tar, 0);
/* path building may fail in EditMode after removing verts [#33268]*/
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 9be9db77d39..fff8265a158 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -170,7 +170,7 @@ static void clear_global(void)
static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const char *path_src)
{
strcpy(path_dst, path_src);
- BLI_clean(path_dst);
+ BLI_path_native_slash(path_dst);
return !STREQ(path_dst, path_src);
}
@@ -182,7 +182,7 @@ static void clean_paths(Main *main)
BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
for (scene = main->scene.first; scene; scene = scene->id.next) {
- BLI_clean(scene->r.pic);
+ BLI_path_native_slash(scene->r.pic);
}
}
@@ -479,7 +479,9 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
return (bfd ? retval : BKE_READ_FILE_FAIL);
}
-int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, ReportList *reports, int update_defaults)
+bool BKE_read_file_from_memory(
+ bContext *C, const void *filebuf, int filelength,
+ ReportList *reports, bool update_defaults)
{
BlendFileData *bfd;
@@ -496,7 +498,9 @@ int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength,
}
/* memfile is the undo buffer */
-int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *reports)
+bool BKE_read_file_from_memfile(
+ bContext *C, MemFile *memfile,
+ ReportList *reports)
{
BlendFileData *bfd;
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index dc2d0924bba..3cd26dacebd 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -107,7 +107,7 @@ typedef struct BPathRemap_Data {
int count_failed;
} BPathRemap_Data;
-static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
{
BPathRemap_Data *data = (BPathRemap_Data *)userdata;
@@ -133,6 +133,7 @@ static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const cha
void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
{
BPathRemap_Data data = {NULL};
+ const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
if (basedir[0] == '\0') {
printf("%s: basedir='', this is a bug\n", __func__);
@@ -142,14 +143,14 @@ void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *re
data.basedir = basedir;
data.reports = reports;
- BKE_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, bpath_relative_convert_visit_cb, flag, (void *)&data);
BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
"Total files %d | Changed %d | Failed %d",
data.count_tot, data.count_changed, data.count_failed);
}
-static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
{
BPathRemap_Data *data = (BPathRemap_Data *)userdata;
@@ -176,6 +177,7 @@ static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const cha
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
{
BPathRemap_Data data = {NULL};
+ const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
if (basedir[0] == '\0') {
printf("%s: basedir='', this is a bug\n", __func__);
@@ -185,7 +187,7 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re
data.basedir = basedir;
data.reports = reports;
- BKE_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, bpath_absolute_convert_visit_cb, flag, (void *)&data);
BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
"Total files %d | Changed %d | Failed %d",
@@ -422,7 +424,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
Image *ima;
ima = (Image *)id;
if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
- if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
if (!ima->packedfile) {
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 967e89e0dd1..76b0cad337f 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -83,6 +83,7 @@ static void brush_defaults(Brush *brush)
brush->plane_trim = 0.5f;
brush->clone.alpha = 0.5f;
brush->normal_weight = 0.0f;
+ brush->fill_threshold = 0.2f;
brush->flag |= BRUSH_ALPHA_PRESSURE;
/* BRUSH PAINT TOOL SETTINGS */
@@ -90,6 +91,8 @@ static void brush_defaults(Brush *brush)
brush->rgb[1] = 1.0f;
brush->rgb[2] = 1.0f;
+ zero_v3(brush->secondary_rgb);
+
/* BRUSH STROKE SETTINGS */
brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN);
brush->spacing = 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
@@ -161,6 +164,9 @@ Brush *BKE_brush_copy(Brush *brush)
if (brush->mask_mtex.tex)
id_us_plus((ID *)brush->mask_mtex.tex);
+ if (brush->paint_curve)
+ id_us_plus((ID *)brush->paint_curve);
+
if (brush->icon_imbuf)
brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf);
@@ -180,11 +186,9 @@ Brush *BKE_brush_copy(Brush *brush)
/* not brush itself */
void BKE_brush_free(Brush *brush)
{
- if (brush->mtex.tex)
- brush->mtex.tex->id.us--;
-
- if (brush->mask_mtex.tex)
- brush->mask_mtex.tex->id.us--;
+ id_us_min((ID *)brush->mtex.tex);
+ id_us_min((ID *)brush->mask_mtex.tex);
+ id_us_min((ID *)brush->paint_curve);
if (brush->icon_imbuf)
IMB_freeImBuf(brush->icon_imbuf);
@@ -192,6 +196,9 @@ void BKE_brush_free(Brush *brush)
BKE_previewimg_free(&(brush->preview));
curvemapping_free(brush->curve);
+
+ if (brush->gradient)
+ MEM_freeN(brush->gradient);
}
static void extern_local_brush(Brush *brush)
@@ -199,6 +206,7 @@ static void extern_local_brush(Brush *brush)
id_lib_extern((ID *)brush->mtex.tex);
id_lib_extern((ID *)brush->mask_mtex.tex);
id_lib_extern((ID *)brush->clone.image);
+ id_lib_extern((ID *)brush->paint_curve);
}
void BKE_brush_make_local(Brush *brush)
@@ -742,10 +750,23 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
+ CLAMP(intensity, 0.0f, 1.0f);
+
+ switch (br->mask_pressure) {
+ case BRUSH_MASK_PRESSURE_CUTOFF:
+ intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f;
+ break;
+ case BRUSH_MASK_PRESSURE_RAMP:
+ intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value);
+ break;
+ default:
+ break;
+ }
+
return intensity;
}
-/* Unified Size and Strength */
+/* Unified Size / Strength / Color */
/* XXX: be careful about setting size and unprojected radius
* because they depend on one another
@@ -760,6 +781,29 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
* In any case, a better solution is needed to prevent
* inconsistency. */
+
+float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush)
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb;
+}
+
+float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush)
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb;
+}
+
+void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3])
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+
+ if (ups->flag & UNIFIED_PAINT_COLOR)
+ copy_v3_v3(ups->rgb, color);
+ else
+ copy_v3_v3(brush->rgb, color);
+}
+
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -886,39 +930,27 @@ void BKE_brush_scale_size(int *r_brush_size,
void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2])
{
- int use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ?
- (brush->jitter_absolute != 0) : (brush->jitter != 0);
+ float rand_pos[2];
+ float spread;
+ int diameter;
- /* jitter-ed brush gives weird and unpredictable result for this
- * kinds of stroke, so manually disable jitter usage (sergey) */
- use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
+ do {
+ rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f;
+ rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f;
+ } while (len_squared_v2(rand_pos) > (0.5f * 0.5f));
- if (use_jitter) {
- float rand_pos[2];
- float spread;
- int diameter;
- do {
- rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f;
- rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f;
- } while (len_squared_v2(rand_pos) > (0.5f * 0.5f));
-
-
- if (brush->flag & BRUSH_ABSOLUTE_JITTER) {
- diameter = 2 * brush->jitter_absolute;
- spread = 1.0;
- }
- else {
- diameter = 2 * BKE_brush_size_get(scene, brush);
- spread = brush->jitter;
- }
- /* find random position within a circle of diameter 1 */
- jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread;
- jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread;
+ if (brush->flag & BRUSH_ABSOLUTE_JITTER) {
+ diameter = 2 * brush->jitter_absolute;
+ spread = 1.0;
}
else {
- copy_v2_v2(jitterpos, pos);
+ diameter = 2 * BKE_brush_size_get(scene, brush);
+ spread = brush->jitter;
}
+ /* find random position within a circle of diameter 1 */
+ jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread;
+ jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread;
}
void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mask)
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index f85a91b66cb..4ad577a7bda 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -77,288 +77,6 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con
return FLT_MAX;
}
-
-/*
- * Function adapted from David Eberly's distance tools (LGPL)
- * http://www.geometrictools.com/LibFoundation/Distance/Distance.html
- */
-float nearest_point_in_tri_surface_squared(
- const float v0[3], const float v1[3], const float v2[3],
- const float p[3], int *v, int *e, float nearest[3])
-{
- float diff[3];
- float e0[3];
- float e1[3];
- float A00;
- float A01;
- float A11;
- float B0;
- float B1;
- float C;
- float Det;
- float S;
- float T;
- float sqrDist;
- int lv = -1, le = -1;
-
- sub_v3_v3v3(diff, v0, p);
- sub_v3_v3v3(e0, v1, v0);
- sub_v3_v3v3(e1, v2, v0);
-
- A00 = dot_v3v3(e0, e0);
- A01 = dot_v3v3(e0, e1);
- A11 = dot_v3v3(e1, e1);
- B0 = dot_v3v3(diff, e0);
- B1 = dot_v3v3(diff, e1);
- C = dot_v3v3(diff, diff);
- Det = fabsf(A00 * A11 - A01 * A01);
- S = A01 * B1 - A11 * B0;
- T = A01 * B0 - A00 * B1;
-
- if (S + T <= Det) {
- if (S < 0.0f) {
- if (T < 0.0f) { /* Region 4 */
- if (B0 < 0.0f) {
- T = 0.0f;
- if (-B0 >= A00) {
- S = 1.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else {
- if (fabsf(A00) > FLT_EPSILON)
- S = -B0 / A00;
- else
- S = 0.0f;
- sqrDist = B0 * S + C;
- le = 0;
- }
- }
- else {
- S = 0.0f;
- if (B1 >= 0.0f) {
- T = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else if (-B1 >= A11) {
- T = 1.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else {
- if (fabsf(A11) > FLT_EPSILON)
- T = -B1 / A11;
- else
- T = 0.0f;
- sqrDist = B1 * T + C;
- le = 1;
- }
- }
- }
- else { /* Region 3 */
- S = 0.0f;
- if (B1 >= 0.0f) {
- T = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else if (-B1 >= A11) {
- T = 1.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else {
- if (fabsf(A11) > FLT_EPSILON)
- T = -B1 / A11;
- else
- T = 0.0;
- sqrDist = B1 * T + C;
- le = 1;
- }
- }
- }
- else if (T < 0.0f) { /* Region 5 */
- T = 0.0f;
- if (B0 >= 0.0f) {
- S = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else if (-B0 >= A00) {
- S = 1.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else {
- if (fabsf(A00) > FLT_EPSILON)
- S = -B0 / A00;
- else
- S = 0.0f;
- sqrDist = B0 * S + C;
- le = 0;
- }
- }
- else { /* Region 0 */
- /* Minimum at interior lv */
- float invDet;
- if (fabsf(Det) > FLT_EPSILON)
- invDet = 1.0f / Det;
- else
- invDet = 0.0f;
- S *= invDet;
- T *= invDet;
- sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) +
- T * (A01 * S + A11 * T + 2.0f * B1) + C;
- }
- }
- else {
- float tmp0, tmp1, numer, denom;
-
- if (S < 0.0f) { /* Region 2 */
- tmp0 = A01 + B0;
- tmp1 = A11 + B1;
- if (tmp1 > tmp0) {
- numer = tmp1 - tmp0;
- denom = A00 - 2.0f * A01 + A11;
- if (numer >= denom) {
- S = 1.0f;
- T = 0.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else {
- if (fabsf(denom) > FLT_EPSILON)
- S = numer / denom;
- else
- S = 0.0f;
- T = 1.0f - S;
- sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) +
- T * (A01 * S + A11 * T + 2.0f * B1) + C;
- le = 2;
- }
- }
- else {
- S = 0.0f;
- if (tmp1 <= 0.0f) {
- T = 1.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else if (B1 >= 0.0f) {
- T = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else {
- if (fabsf(A11) > FLT_EPSILON)
- T = -B1 / A11;
- else
- T = 0.0f;
- sqrDist = B1 * T + C;
- le = 1;
- }
- }
- }
- else if (T < 0.0f) { /* Region 6 */
- tmp0 = A01 + B1;
- tmp1 = A00 + B0;
- if (tmp1 > tmp0) {
- numer = tmp1 - tmp0;
- denom = A00 - 2.0f * A01 + A11;
- if (numer >= denom) {
- T = 1.0f;
- S = 0.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else {
- if (fabsf(denom) > FLT_EPSILON)
- T = numer / denom;
- else
- T = 0.0f;
- S = 1.0f - T;
- sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) +
- T * (A01 * S + A11 * T + 2.0f * B1) + C;
- le = 2;
- }
- }
- else {
- T = 0.0f;
- if (tmp1 <= 0.0f) {
- S = 1.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else if (B0 >= 0.0f) {
- S = 0.0f;
- sqrDist = C;
- lv = 0;
- }
- else {
- if (fabsf(A00) > FLT_EPSILON)
- S = -B0 / A00;
- else
- S = 0.0f;
- sqrDist = B0 * S + C;
- le = 0;
- }
- }
- }
- else { /* Region 1 */
- numer = A11 + B1 - A01 - B0;
- if (numer <= 0.0f) {
- S = 0.0f;
- T = 1.0f;
- sqrDist = A11 + 2.0f * B1 + C;
- lv = 2;
- }
- else {
- denom = A00 - 2.0f * A01 + A11;
- if (numer >= denom) {
- S = 1.0f;
- T = 0.0f;
- sqrDist = A00 + 2.0f * B0 + C;
- lv = 1;
- }
- else {
- if (fabsf(denom) > FLT_EPSILON)
- S = numer / denom;
- else
- S = 0.0f;
- T = 1.0f - S;
- sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) +
- T * (A01 * S + A11 * T + 2.0f * B1) + C;
- le = 2;
- }
- }
- }
- }
-
- /* Account for numerical round-off error */
- if (sqrDist < FLT_EPSILON)
- sqrDist = 0.0f;
-
- {
- float w[3], x[3], y[3], z[3];
- copy_v3_v3(w, v0);
- copy_v3_v3(x, e0);
- mul_v3_fl(x, S);
- copy_v3_v3(y, e1);
- mul_v3_fl(y, T);
- add_v3_v3v3(z, w, x);
- add_v3_v3v3(z, z, y);
- //sub_v3_v3v3(d, p, z);
- copy_v3_v3(nearest, z);
- //d = p - ( v0 + S * e0 + T * e1 );
- }
- *v = lv;
- *e = le;
-
- return sqrDist;
-}
-
-
/*
* BVH from meshes callbacks
*/
@@ -380,9 +98,10 @@ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3
do {
float nearest_tmp[3], dist_sq;
- int vertex, edge;
-
- dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
+
+ closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
if (dist_sq < nearest->dist_sq) {
nearest->index = index;
nearest->dist_sq = dist_sq;
@@ -413,9 +132,10 @@ static void editmesh_faces_nearest_point(void *userdata, int index, const float
{
float nearest_tmp[3], dist_sq;
- int vertex, edge;
- dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
+ closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
if (dist_sq < nearest->dist_sq) {
nearest->index = index;
nearest->dist_sq = dist_sq;
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index b20ba40c0dd..6ce3abe7a32 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -201,7 +201,7 @@ void BKE_camera_params_init(CameraParams *params)
/* fallback for non camera objects */
params->clipsta = 0.1f;
- params->clipsta = 100.0f;
+ params->clipend = 100.0f;
}
void BKE_camera_params_from_object(CameraParams *params, Object *ob)
@@ -473,7 +473,7 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data)
unsigned int i;
for (i = 0; i < 4; i++) {
- float nd = dist_squared_to_plane_v3(co, data->plane_tx[i]);
+ float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
if (nd < data->dist_vals_sq[i]) {
data->dist_vals_sq[i] = nd;
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index f39b4e20b70..08052127fbf 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -49,6 +49,7 @@
#include "BKE_editmesh.h"
#include "BKE_curve.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -668,7 +669,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
DMSetDrawOptions drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag uvflag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
MVert *mv = cddm->mvert;
@@ -679,6 +680,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
MCol *mcol;
int i, orig;
int colType, startFace = 0;
+ bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
/* double lookup */
const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
@@ -717,14 +719,35 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
cdDM_update_normals_from_pbvh(dm);
if (GPU_buffer_legacy(dm)) {
+ int mat_nr_cache = -1;
+ MTFace *tf_base = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ MTFace *tf_stencil_base = NULL;
+ MTFace *tf_stencil = NULL;
+
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
+ int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ }
+
DEBUG_VBO("Using legacy code. cdDM_drawFacesTex_common\n");
for (i = 0; i < dm->numTessFaceData; i++, mf++) {
MVert *mvert;
DMDrawOption draw_option;
unsigned char *cp = NULL;
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
+ if (mf->mat_nr != mat_nr_cache) {
+ tf_base = DM_paint_uvlayer_active_get(dm, mf->mat_nr);
+
+ mat_nr_cache = mf->mat_nr;
+ }
+ }
+
+ tf = tf_base ? tf_base + i : NULL;
+ tf_stencil = tf_stencil_base ? tf_stencil_base + i : NULL;
+
if (drawParams) {
- draw_option = drawParams(tf ? &tf[i] : NULL, (mcol != NULL), mf->mat_nr);
+ draw_option = drawParams(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr);
}
else {
if (index_mf_to_mpoly) {
@@ -777,21 +800,24 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES);
- if (tf) glTexCoord2fv(tf[i].uv[0]);
+ if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
mvert = &mv[mf->v1];
if (lnors) glNormal3sv((const GLshort *)lnors[0][0]);
else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
glVertex3fv(mvert->co);
- if (tf) glTexCoord2fv(tf[i].uv[1]);
+ if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
mvert = &mv[mf->v2];
if (lnors) glNormal3sv((const GLshort *)lnors[0][1]);
else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
glVertex3fv(mvert->co);
- if (tf) glTexCoord2fv(tf[i].uv[2]);
+ if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
mvert = &mv[mf->v3];
if (lnors) glNormal3sv((const GLshort *)lnors[0][2]);
@@ -799,7 +825,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
glVertex3fv(mvert->co);
if (mf->v4) {
- if (tf) glTexCoord2fv(tf[i].uv[3]);
+ if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
mvert = &mv[mf->v4];
if (lnors) glNormal3sv((const GLshort *)lnors[0][3]);
@@ -818,7 +845,10 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
- GPU_uv_setup(dm);
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
+ GPU_texpaint_uv_setup(dm);
+ else
+ GPU_uv_setup(dm);
if (mcol) {
GPU_color_setup(dm, colType);
}
@@ -838,7 +868,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
if (drawParams) {
- draw_option = drawParams(tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
+ draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
}
else {
if (index_mf_to_mpoly) {
@@ -894,9 +924,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
static void cdDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag uvflag)
{
- cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
+ cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, uvflag);
}
static void cdDM_drawMappedFaces(DerivedMesh *dm,
@@ -1122,9 +1152,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
static void cdDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
+ cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert,
@@ -2541,25 +2571,200 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm)
#if 1
/**
+ * Poly compare with vtargetmap
+ * Function used by #CDDM_merge_verts.
+ * The function compares poly_source after applying vtargetmap, with poly_target.
+ * The two polys are identical if they share the same vertices in the same order, or in reverse order,
+ * but starting position loopstart may be different.
+ * The function is called with direct_reverse=1 for same order (i.e. same normal),
+ * and may be called again with direct_reverse=-1 for reverse order.
+ * \return 1 if polys are identical, 0 if polys are different.
+ */
+static int cddm_poly_compare(MLoop *mloop_array, MPoly *mpoly_source, MPoly *mpoly_target, const int *vtargetmap, const int direct_reverse)
+{
+ int vert_source, first_vert_source, vert_target;
+ int i_loop_source;
+ int i_loop_target, i_loop_target_start, i_loop_target_offset, i_loop_target_adjusted;
+ bool compare_completed = false;
+ bool same_loops = false;
+
+ MLoop *mloop_source, *mloop_target;
+
+ BLI_assert(direct_reverse == 1 || direct_reverse == -1);
+
+ i_loop_source = 0;
+ mloop_source = mloop_array + mpoly_source->loopstart;
+ vert_source = mloop_source->v;
+
+ if (vtargetmap[vert_source] != -1) {
+ vert_source = vtargetmap[vert_source];
+ }
+ else {
+ /* All source loop vertices should be mapped */
+ BLI_assert(false);
+ }
+
+ /* Find same vertex within mpoly_target's loops */
+ mloop_target = mloop_array + mpoly_target->loopstart;
+ for (i_loop_target = 0; i_loop_target < mpoly_target->totloop; i_loop_target++, mloop_target++) {
+ if (mloop_target->v == vert_source) {
+ break;
+ }
+ }
+
+ /* If same vertex not found, then polys cannot be equal */
+ if (i_loop_target >= mpoly_target->totloop) {
+ return false;
+ }
+
+ /* Now mloop_source and m_loop_target have one identical vertex */
+ /* mloop_source is at position 0, while m_loop_target has advanced to find identical vertex */
+ /* Go around the loop and check that all vertices match in same order */
+ /* Skipping source loops when consecutive source vertices are mapped to same target vertex */
+
+ i_loop_target_start = i_loop_target;
+ i_loop_target_offset = 0;
+ first_vert_source = vert_source;
+
+ compare_completed = false;
+ same_loops = false;
+
+ while (!compare_completed) {
+
+ vert_target = mloop_target->v;
+
+ /* First advance i_loop_source, until it points to different vertex, after mapping applied */
+ do {
+ i_loop_source++;
+
+ if (i_loop_source == mpoly_source->totloop) {
+ /* End of loops for source, must match end of loop for target. */
+ if (i_loop_target_offset == mpoly_target->totloop - 1) {
+ compare_completed = true;
+ same_loops = true;
+ break; /* Polys are identical */
+ }
+ else {
+ compare_completed = true;
+ same_loops = false;
+ break; /* Polys are different */
+ }
+ }
+
+ mloop_source++;
+ vert_source = mloop_source->v;
+
+ if (vtargetmap[vert_source] != -1) {
+ vert_source = vtargetmap[vert_source];
+ }
+ else {
+ /* All source loop vertices should be mapped */
+ BLI_assert(false);
+ }
+
+ } while (vert_source == vert_target);
+
+ if (compare_completed) {
+ break;
+ }
+
+ /* Now advance i_loop_target as well */
+ i_loop_target_offset++;
+
+ if (i_loop_target_offset == mpoly_target->totloop) {
+ /* End of loops for target only, that means no match */
+ /* except if all remaining source vertices are mapped to first target */
+ for (; i_loop_source < mpoly_source->totloop; i_loop_source++, mloop_source++) {
+ vert_source = vtargetmap[mloop_source->v];
+ if (vert_source != first_vert_source) {
+ compare_completed = true;
+ same_loops = false;
+ break;
+ }
+ }
+ if (!compare_completed) {
+ same_loops = true;
+ }
+ break;
+ }
+
+ /* Adjust i_loop_target for cycling around and for direct/reverse order defined by delta = +1 or -1 */
+ i_loop_target_adjusted = (i_loop_target_start + direct_reverse * i_loop_target_offset) % mpoly_target->totloop;
+ if (i_loop_target_adjusted < 0) {
+ i_loop_target_adjusted += mpoly_target->totloop;
+ }
+ mloop_target = mloop_array + mpoly_target->loopstart + i_loop_target_adjusted;
+ vert_target = mloop_target->v;
+
+ if (vert_target != vert_source) {
+ same_loops = false; /* Polys are different */
+ break;
+ }
+ }
+ return same_loops;
+}
+
+/* Utility stuff for using GHash with polys */
+
+typedef struct PolyKey {
+ int poly_index; /* index of the MPoly within the derived mesh */
+ int totloops; /* number of loops in the poly */
+ unsigned int hash_sum; /* Sum of all vertices indices */
+ unsigned int hash_xor; /* Xor of all vertices indices */
+} PolyKey;
+
+
+static unsigned int poly_gset_hash_fn(const void *key)
+{
+ const PolyKey *pk = key;
+ return pk->hash_sum;
+}
+
+static int poly_gset_compare_fn(const void *k1, const void *k2)
+{
+ const PolyKey *pk1 = k1;
+ const PolyKey *pk2 = k2;
+ if ((pk1->hash_sum == pk2->hash_sum) &&
+ (pk1->hash_xor == pk2->hash_xor) &&
+ (pk1->totloops == pk2->totloops))
+ {
+ /* Equality - note that this does not mean equality of polys */
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+/**
* Merge Verts
*
+ * This frees dm, and returns a new one.
+ *
* \param vtargetmap The table that maps vertices to target vertices. a value of -1
* indicates a vertex is a target, and is to be kept.
* This array is aligned with 'dm->numVertData'
*
- * \param tot_vtargetmap The number of non '-1' values in vtargetmap.
- * (not the size )
- *
- * this frees dm, and returns a new one.
+ * \param tot_vtargetmap The number of non '-1' values in vtargetmap. (not the size)
*
- * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces.
+ * \param merge_mode enum with two modes.
+ * - #CDDM_MERGE_VERTS_DUMP_IF_MAPPED
+ * When called by the Mirror Modifier,
+ * In this mode it skips any faces that have all vertices merged (to avoid creating pairs
+ * of faces sharing the same set of vertices)
+ * - #CDDM_MERGE_VERTS_DUMP_IF_EQUAL
+ * When called by the Array Modifier,
+ * In this mode, faces where all vertices are merged are double-checked,
+ * to see whether all target vertices actually make up a poly already.
+ * Indeed it could be that all of a poly's vertices are merged,
+ * but merged to vertices that do not make up a single poly,
+ * in which case the original poly should not be dumped.
+ * Actually this later behavior could apply to the Mirror Modifier as well, but the additional checks are
+ * costly and not necessary in the case of mirror, because each vertex is only merged to its own mirror.
*
- * Note: This function is currently only used by the Mirror modifier, so it
- * skips any faces that have all vertices merged (to avoid creating pairs
- * of faces sharing the same set of vertices). If used elsewhere, it may
- * be necessary to make this functionality optional.
+ * \note #CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces.
*/
-DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap)
+DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap, const int merge_mode)
{
// #define USE_LOOPS
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -2600,7 +2805,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
EdgeHash *ehash = BLI_edgehash_new_ex(__func__, totedge);
int i, j, c;
-
+
+ PolyKey *poly_keys;
+ GSet *poly_gset = NULL;
+
STACK_INIT(oldv, totvert_final);
STACK_INIT(olde, totedge);
STACK_INIT(oldl, totloop);
@@ -2642,10 +2850,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
med = cddm->medge;
c = 0;
for (i = 0; i < totedge; i++, med++) {
-
- if (LIKELY(med->v1 != med->v2)) {
- const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
- const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
+ const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
+ const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
+ if (LIKELY(v1 != v2)) {
void **eh_p = BLI_edgehash_lookup_p(ehash, v1, v2);
if (eh_p) {
@@ -2664,13 +2871,49 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
}
}
+ if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) {
+ /* In this mode, we need to determine, whenever a poly' vertices are all mapped */
+ /* if the targets already make up a poly, in which case the new poly is dropped */
+ /* This poly equality check is rather complex. We use a BLI_ghash to speed it up with a first level check */
+ PolyKey *mpgh;
+ poly_keys = MEM_mallocN(sizeof(PolyKey) * totpoly, __func__);
+ poly_gset = BLI_gset_new_ex(poly_gset_hash_fn, poly_gset_compare_fn, __func__, totpoly);
+ /* Duplicates allowed because our compare function is not pure equality */
+ BLI_gset_flag_set(poly_gset, GHASH_FLAG_ALLOW_DUPES);
+
+ mp = cddm->mpoly;
+ mpgh = poly_keys;
+ for (i = 0; i < totpoly; i++, mp++, mpgh++) {
+ mpgh->poly_index = i;
+ mpgh->totloops = mp->totloop;
+ ml = cddm->mloop + mp->loopstart;
+ mpgh->hash_sum = mpgh->hash_xor = 0;
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ mpgh->hash_sum += ml->v;
+ mpgh->hash_xor ^= ml->v;
+ }
+ BLI_gset_insert(poly_gset, mpgh);
+ }
+
+ if (cddm->pmap) {
+ MEM_freeN(cddm->pmap);
+ MEM_freeN(cddm->pmap_mem);
+ }
+ /* Can we optimise by reusing an old pmap ? How do we know an old pmap is stale ? */
+ /* When called by MOD_array.c, the cddm has just been created, so it has no valid pmap. */
+ BKE_mesh_vert_poly_map_create(&cddm->pmap, &cddm->pmap_mem,
+ cddm->mpoly, cddm->mloop,
+ totvert, totpoly, totloop);
+ } /* done preparing for fast poly compare */
+
+
mp = cddm->mpoly;
for (i = 0; i < totpoly; i++, mp++) {
MPoly *mp_new;
ml = cddm->mloop + mp->loopstart;
- /* skip faces with all vertices merged */
+ /* check faces with all vertices merged */
{
bool all_vertices_merged = true;
@@ -2682,16 +2925,86 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
}
if (UNLIKELY(all_vertices_merged)) {
- continue;
+ if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_MAPPED) {
+ /* In this mode, all vertices merged is enough to dump face */
+ continue;
+ }
+ else if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) {
+ /* Additional condition for face dump: target vertices must make up an identical face */
+ /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */
+ /* (2) second step is thorough but more costly poly compare */
+ int i_poly, v_target, v_prev;
+ bool found = false;
+ PolyKey pkey;
+
+ /* Use poly_gset for fast (although not 100% certain) identification of same poly */
+ /* First, make up a poly_summary structure */
+ ml = cddm->mloop + mp->loopstart;
+ pkey.hash_sum = pkey.hash_xor = 0;
+ pkey.totloops = 0;
+ v_prev = vtargetmap[(ml + mp->totloop -1)->v]; /* since it loops around, the prev of first is the last */
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */
+ if (v_target == v_prev) {
+ /* consecutive vertices in loop map to the same target: discard */
+ /* but what about last to first ? */
+ continue;
+ }
+ pkey.hash_sum += v_target;
+ pkey.hash_xor ^= v_target;
+ pkey.totloops++;
+ v_prev = v_target;
+ }
+ if (BLI_gset_haskey(poly_gset, &pkey)) {
+
+ /* There might be a poly that matches this one.
+ * We could just leave it there and say there is, and do a "continue".
+ * ... but we are checking whether there is an exact poly match.
+ * It's not so costly in terms of CPU since it's very rare, just a lot of complex code.
+ */
+
+ /* Consider current loop again */
+ ml = cddm->mloop + mp->loopstart;
+ /* Consider the target of the loop's first vert */
+ v_target = vtargetmap[ml->v];
+ /* Now see if v_target belongs to a poly that shares all vertices with source poly,
+ * in same order, or reverse order */
+
+ for (i_poly = 0; i_poly < cddm->pmap[v_target].count; i_poly++) {
+ MPoly *target_poly = cddm->mpoly + *(cddm->pmap[v_target].indices + i_poly);
+
+ if (cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, +1) ||
+ cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ /* Current poly's vertices are mapped to a poly that is strictly identical */
+ /* Current poly is dumped */
+ continue;
+ }
+ }
+ }
}
}
+
+ /* Here either the poly's vertices were not all merged
+ * or they were all merged, but targets do not make up an identical poly,
+ * the poly is retained.
+ */
ml = cddm->mloop + mp->loopstart;
c = 0;
for (j = 0; j < mp->totloop; j++, ml++) {
+ unsigned int v1, v2;
+
med = cddm->medge + ml->e;
- if (LIKELY(med->v1 != med->v2)) {
+ v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
+ v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
+ if (LIKELY(v1 != v2)) {
#ifdef USE_LOOPS
newl[j + mp->loopstart] = STACK_SIZE(mloop);
#endif
@@ -2711,6 +3024,14 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
mp_new->loopstart = STACK_SIZE(mloop) - c;
STACK_PUSH(oldp, i);
+ } /* end of the loop that tests polys */
+
+
+ if (poly_gset) {
+ // printf("hash quality %.6f\n", BLI_gset_calc_quality(poly_gset));
+
+ BLI_gset_free(poly_gset, NULL);
+ MEM_freeN(poly_keys);
}
/*create new cddm*/
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index b27655c8c19..d80529ee780 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -3375,7 +3375,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
unit_m4(ct->matrix);
if (target != NULL) {
- space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat);
+ BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->obmat);
switch (scon->shrinkType) {
case MOD_SHRINKWRAP_NEAREST_SURFACE:
@@ -3397,7 +3397,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
break;
}
- space_transform_apply(&transform, co);
+ BLI_space_transform_apply(&transform, co);
BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
@@ -3405,7 +3405,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
if (dist != 0.0f) {
interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist) / dist); /* linear interpolation */
}
- space_transform_invert(&transform, co);
+ BLI_space_transform_invert(&transform, co);
break;
}
case MOD_SHRINKWRAP_PROJECT:
@@ -3909,7 +3909,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, imat);
invert_m4(imat);
- mul_serie_m4(cob->matrix, obmat, mat, imat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(cob->matrix, obmat, mat, imat);
translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
}
else {
@@ -3943,19 +3943,31 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
if (len > FLT_EPSILON) {
CameraParams params;
+ int width, height;
float pos[2], rmat[4][4];
+ BKE_movieclip_get_size(clip, NULL, &width, &height);
+
marker = BKE_tracking_marker_get(track, framenr);
add_v2_v2v2(pos, marker->pos, track->offset);
+ if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) {
+ /* Undistortion need to happen in pixel space. */
+ pos[0] *= width;
+ pos[1] *= height;
+
+ BKE_tracking_undistort_v2(tracking, pos, pos);
+
+ /* Normalize pixel coordinates back. */
+ pos[0] /= width;
+ pos[1] /= height;
+ }
+
/* aspect correction */
if (data->frame_method != FOLLOWTRACK_FRAME_STRETCH) {
- int width, height;
float w_src, h_src, w_dst, h_dst, asp_src, asp_dst;
- BKE_movieclip_get_size(clip, NULL, &width, &height);
-
/* apply clip display aspect */
w_src = width * clip->aspx;
h_src = height * clip->aspy;
@@ -4187,7 +4199,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
invert_m4_m4(imat, mat);
- mul_serie_m4(cob->matrix, cammat, imat, camimat, parmat, obmat, NULL, NULL, NULL);
+ mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat);
}
}
}
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 47b29b49689..de285f87444 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -48,7 +48,6 @@
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_screen.h"
-#include "BKE_freestyle.h"
#include "RNA_access.h"
@@ -1091,16 +1090,3 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
{
return ctx_data_collection_get(C, "visible_pose_bones", list);
}
-
-FreestyleLineStyle *CTX_data_linestyle_from_scene(Scene *scene)
-{
- SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleConfig *config = &actsrl->freestyleConfig;
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
-
- if (lineset) {
- return lineset->linestyle;
- }
-
- return NULL;
-}
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 7ca5d6b4f28..911bb19a594 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -40,7 +40,6 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLI_bitmap.h"
#include "BKE_crazyspace.h"
#include "BKE_DerivedMesh.h"
@@ -49,11 +48,6 @@
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
-typedef struct {
- float (*vertexcos)[3];
- BLI_bitmap *vertex_visit;
-} MappedUserData;
-
BLI_INLINE void tan_calc_quat_v3(
float r_quat[4],
const float co_1[3], const float co_2[3], const float co_3[3])
@@ -88,20 +82,6 @@ static void set_crazy_vertex_quat(
sub_qt_qtqt(r_quat, q2, q1);
}
-static void make_vertexcos__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
-{
- MappedUserData *mappedData = (MappedUserData *)userData;
-
- if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) {
- /* we need coord from prototype vertex, not from copies,
- * assume they stored in the beginning of vertex array stored in DM
- * (mirror modifier for eg does this) */
- copy_v3_v3(mappedData->vertexcos[index], co);
- BLI_BITMAP_ENABLE(mappedData->vertex_visit, index);
- }
-}
-
static int modifiers_disable_subsurf_temporary(Object *ob)
{
ModifierData *md;
@@ -124,8 +104,6 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
DerivedMesh *dm;
float (*vertexcos)[3];
int nverts = me->edit_btmesh->bm->totvert;
- BLI_bitmap *vertex_visit;
- MappedUserData userData;
/* disable subsurf temporal, get mapped cos, and enable it */
if (modifiers_disable_subsurf_temporary(obedit)) {
@@ -134,22 +112,17 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
}
/* now get the cage */
- dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
+ vertexcos = MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map");
- vertexcos = MEM_callocN(sizeof(*vertexcos) * nverts, "vertexcos map");
- vertex_visit = BLI_BITMAP_NEW(nverts, "vertexcos flags");
+ dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
- userData.vertexcos = vertexcos;
- userData.vertex_visit = vertex_visit;
- dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP);
+ mesh_get_mapped_verts_coords(dm, vertexcos, nverts);
dm->release(dm);
/* set back the flag, no new cage needs to be built, transform does it */
modifiers_disable_subsurf_temporary(obedit);
- MEM_freeN(vertex_visit);
-
return vertexcos;
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 0abe956b599..9275b626b49 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -52,6 +52,7 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_font.h"
#include "BKE_global.h"
@@ -642,8 +643,9 @@ void BKE_nurb_test2D(Nurb *nu)
}
}
-/* if use_radius is truth, minmax will take points' radius into account,
- * which will make boundbox closer to bevelled curve.
+/**
+ * if use_radius is truth, minmax will take points' radius into account,
+ * which will make boundbox closer to beveled curve.
*/
void BKE_nurb_minmax(Nurb *nu, bool use_radius, float min[3], float max[3])
{
@@ -2498,6 +2500,22 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl)
}
}
+void BKE_curve_bevelList_free(ListBase *bev)
+{
+ BevList *bl, *blnext;
+ for (bl = bev->first; bl != NULL; bl = blnext) {
+ blnext = bl->next;
+ if (bl->seglen != NULL) {
+ MEM_freeN(bl->seglen);
+ }
+ if (bl->segbevcount != NULL) {
+ MEM_freeN(bl->segbevcount);
+ }
+ MEM_freeN(bl);
+ }
+ bev->first = bev->last = NULL;
+}
+
void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
{
/*
@@ -2506,21 +2524,29 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
* - separate in individual blocks with BoundBox
* - AutoHole detection
*/
- Curve *cu;
+
+ /* this function needs an object, because of tflag and upflag */
+ Curve *cu = ob->data;
Nurb *nu;
BezTriple *bezt, *prevbezt;
BPoint *bp;
BevList *bl, *blnew, *blnext;
BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
+ const float treshold = 0.00001f;
float min, inp;
+ float *seglen;
struct BevelSort *sortdata, *sd, *sd1;
- int a, b, nr, poly, resolu = 0, len = 0;
+ int a, b, nr, poly, resolu = 0, len = 0, segcount;
+ int *segbevcount;
bool do_tilt, do_radius, do_weight;
bool is_editmode = false;
ListBase *bev;
- /* this function needs an object, because of tflag and upflag */
- cu = ob->data;
+ /* segbevcount alsp requires seglen. */
+ const bool need_seglen =
+ ELEM(cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) ||
+ ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE);
+
bev = &ob->curve_cache->bev;
@@ -2529,7 +2555,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
/* STEP 1: MAKE POLYS */
- BLI_freelistN(&(ob->curve_cache->bev));
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
nu = nurbs->first;
if (cu->editnurb && ob->type != OB_FONT) {
is_editmode = 1;
@@ -2559,9 +2585,15 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
else
resolu = nu->resolu;
+ segcount = SEGMENTSU(nu);
+
if (nu->type == CU_POLY) {
len = nu->pntsu;
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2");
+ if (need_seglen) {
+ bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList2_seglen");
+ bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList2_segbevcount");
+ }
BLI_addtail(bev, bl);
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
@@ -2569,7 +2601,11 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bl->dupe_nr = 0;
bl->charidx = nu->charidx;
bevp = bl->bevpoints;
+ bevp->offset = 0;
bp = nu->bp;
+ seglen = bl->seglen;
+ segbevcount = bl->segbevcount;
+ BLI_assert(segcount >= len);
while (len--) {
copy_v3_v3(bevp->vec, bp->vec);
@@ -2577,23 +2613,53 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp->radius = bp->radius;
bevp->weight = bp->weight;
bevp->split_tag = true;
- bevp++;
bp++;
+ if (seglen != NULL) {
+ *seglen = len_v3v3(bevp->vec, bp->vec);
+ bevp++;
+ bevp->offset = *seglen;
+ if (*seglen > treshold) *segbevcount = 1;
+ else *segbevcount = 0;
+ seglen++;
+ segbevcount++;
+ }
+ else {
+ bevp++;
+ }
}
if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
bevlist_firstlast_direction_calc_from_bpoint(nu, bl);
+ if (seglen != NULL) {
+ *seglen = len_v3v3(bevp->vec, nu->bp->vec);
+ bl->bevpoints->offset = *seglen;
+ *segbevcount = 1;
+ }
}
}
else if (nu->type == CU_BEZIER) {
/* in case last point is not cyclic */
- len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1;
+ len = segcount * resolu + 1;
+
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints");
+ if (need_seglen) {
+ bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelBPoints_seglen");
+ bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelBPoints_segbevcount");
+ }
BLI_addtail(bev, bl);
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
bl->charidx = nu->charidx;
+
bevp = bl->bevpoints;
+ seglen = bl->seglen;
+ segbevcount = bl->segbevcount;
+
+ bevp->offset = 0;
+ if (seglen != NULL) {
+ *seglen = 0;
+ *segbevcount = 0;
+ }
a = nu->pntsu - 1;
bezt = nu->bezt;
@@ -2609,6 +2675,8 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
sub_v3_v3v3(bevp->dir, prevbezt->vec[2], prevbezt->vec[1]);
normalize_v3(bevp->dir);
+ BLI_assert(segcount >= a);
+
while (a--) {
if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
@@ -2621,6 +2689,14 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp++;
bl->nr++;
bl->dupe_nr = 1;
+ if (seglen != NULL) {
+ *seglen = len_v3v3(prevbezt->vec[1], bezt->vec[1]);
+ bevp->offset = *seglen;
+ seglen++;
+ /* match segbevcount to the cleaned up bevel lists (see STEP 2) */
+ if (bevp->offset > treshold) *segbevcount = 1;
+ segbevcount++;
+ }
}
else {
/* always do all three, to prevent data hanging around */
@@ -2658,8 +2734,28 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
else if (prevbezt->h2 == 0 || prevbezt->h2 == HD_VECT)
bevp->split_tag = true;
}
+
+ /* seglen */
+ if (seglen != NULL) {
+ *seglen = 0;
+ *segbevcount = 0;
+ for (j = 0; j < resolu; j++) {
+ bevp0 = bevp;
+ bevp++;
+ bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
+ /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
+ if (bevp->offset > treshold) {
+ *seglen += bevp->offset;
+ *segbevcount += 1;
+ }
+ }
+ seglen++;
+ segbevcount++;
+ }
+ else {
+ bevp += resolu;
+ }
bl->nr += resolu;
- bevp += resolu;
}
prevbezt = bezt;
bezt++;
@@ -2679,15 +2775,22 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
}
else if (nu->type == CU_NURBS) {
if (nu->pntsv == 1) {
- len = (resolu * SEGMENTSU(nu));
+ len = (resolu * segcount);
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3");
+ if (need_seglen) {
+ bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList3_seglen");
+ bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList3_segbevcount");
+ }
BLI_addtail(bev, bl);
bl->nr = len;
bl->dupe_nr = 0;
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
bl->charidx = nu->charidx;
+
bevp = bl->bevpoints;
+ seglen = bl->seglen;
+ segbevcount = bl->segbevcount;
BKE_nurb_makeCurve(nu, &bevp->vec[0],
do_tilt ? &bevp->alfa : NULL,
@@ -2695,6 +2798,31 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
do_weight ? &bevp->weight : NULL,
resolu, sizeof(BevPoint));
+ /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
+ if (seglen != NULL) {
+ nr = segcount;
+ bevp0 = bevp;
+ bevp++;
+ while (nr) {
+ int j;
+ *seglen = 0;
+ *segbevcount = 0;
+ /* We keep last bevel segment zero-length. */
+ for (j = 0; j < ((nr == 1) ? (resolu - 1) : resolu); j++) {
+ bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
+ if (bevp->offset > treshold) {
+ *seglen += bevp->offset;
+ *segbevcount += 1;
+ }
+ bevp0 = bevp;
+ bevp++;
+ }
+ seglen++;
+ segbevcount++;
+ nr--;
+ }
+ }
+
if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
bevlist_firstlast_direction_calc_from_bpoint(nu, bl);
}
@@ -2715,15 +2843,24 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
}
else {
bevp0 = bl->bevpoints;
+ bevp0->offset = 0;
bevp1 = bevp0 + 1;
}
nr--;
while (nr--) {
- if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) {
- if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) {
- if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) {
- bevp0->dupe_tag = true;
- bl->dupe_nr++;
+ if (seglen != NULL) {
+ if (fabsf(bevp1->offset) < treshold) {
+ bevp0->dupe_tag = true;
+ bl->dupe_nr++;
+ }
+ }
+ else {
+ if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) {
+ if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) {
+ if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) {
+ bevp0->dupe_tag = true;
+ bl->dupe_nr++;
+ }
}
}
}
@@ -2740,6 +2877,8 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */
blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4");
memcpy(blnew, bl, sizeof(BevList));
+ blnew->segbevcount = bl->segbevcount;
+ blnew->seglen = bl->seglen;
blnew->nr = 0;
BLI_remlink(bev, bl);
BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */
@@ -3070,7 +3209,13 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n
madd_v3_v3v3fl(p2_h2, p2, dvec_b, 1.0f / 3.0f);
}
- if (skip_align || (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) {
+ if (skip_align ||
+ /* when one handle is free, alignming makes no sense, see: T35952 */
+ (ELEM(HD_FREE, bezt->h1, bezt->h2)) ||
+ /* also when no handles are aligned, skip this step */
+ (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) &&
+ !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2)))
+ {
/* handles need to be updated during animation and applying stuff like hooks,
* but in such situations it's quite difficult to distinguish in which order
* align handles should be aligned so skip them for now */
@@ -3168,6 +3313,31 @@ void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */
calchandlesNurb_intern(nu, false);
}
+/**
+ * Workaround #BKE_nurb_handles_calc logic
+ * that makes unselected align to the selected handle.
+ */
+static void nurbList_handles_swap_select(Nurb *nu)
+{
+ BezTriple *bezt;
+ int i;
+
+ for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+ if ((bezt->f1 & SELECT) != (bezt->f3 & SELECT)) {
+ bezt->f1 ^= SELECT;
+ bezt->f3 ^= SELECT;
+ }
+ }
+}
+
+/* internal use only (weak) */
+static void nurb_handles_calc__align_selected(Nurb *nu)
+{
+ nurbList_handles_swap_select(nu);
+ BKE_nurb_handles_calc(nu);
+ nurbList_handles_swap_select(nu);
+}
+
/* similar to BKE_nurb_handle_calc but for curves and
* figures out the previous and next for us */
void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
@@ -3365,7 +3535,9 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
}
bezt++;
}
- BKE_nurb_handles_calc(nu);
+
+ /* like BKE_nurb_handles_calc but moves selected */
+ nurb_handles_calc__align_selected(nu);
}
nu = nu->next;
}
@@ -3409,7 +3581,9 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
bezt++;
}
- BKE_nurb_handles_calc(nu);
+
+ /* like BKE_nurb_handles_calc but moves selected */
+ nurb_handles_calc__align_selected(nu);
}
}
}
@@ -4143,7 +4317,50 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3])
return false;
}
-void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys)
+
+void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit_scale)
+{
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int i;
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ i = nu->pntsu;
+ for (bezt = nu->bezt; i--; bezt++) {
+ mul_m4_v3(mat, bezt->vec[0]);
+ mul_m4_v3(mat, bezt->vec[1]);
+ mul_m4_v3(mat, bezt->vec[2]);
+ bezt->radius *= unit_scale;
+ }
+ BKE_nurb_handles_calc(nu);
+ }
+ else {
+ i = nu->pntsu * nu->pntsv;
+ for (bp = nu->bp; i--; bp++)
+ mul_m4_v3(mat, bp->vec);
+ }
+ }
+
+ if (do_keys && cu->key) {
+ KeyBlock *kb;
+ for (kb = cu->key->block.first; kb; kb = kb->next) {
+ float *fp = kb->data;
+ for (i = kb->totelem; i--; fp += 3) {
+ mul_m4_v3(mat, fp);
+ }
+ }
+ }
+}
+
+void BKE_curve_transform(Curve *cu, float mat[4][4], bool do_keys)
+{
+ float unit_scale = mat4_to_scale(mat);
+ BKE_curve_transform_ex(cu, mat, do_keys, unit_scale);
+}
+
+void BKE_curve_translate(Curve *cu, float offset[3], bool do_keys)
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
Nurb *nu;
@@ -4230,6 +4447,45 @@ void BKE_curve_material_index_clear(Curve *cu)
}
}
+int BKE_curve_material_index_validate(Curve *cu)
+{
+ const int curvetype = BKE_curve_type_get(cu);
+ bool is_valid = true;
+
+ if (curvetype == OB_FONT) {
+ CharInfo *info = cu->strinfo;
+ const int max_idx = max_ii(0, cu->totcol); /* OB_FONT use 1 as first mat index, not 0!!! */
+ int i;
+ for (i = cu->len_wchar - 1; i >= 0; i--, info++) {
+ if (info->mat_nr > max_idx) {
+ info->mat_nr = 0;
+ is_valid = false;
+ }
+ }
+ }
+ else {
+ Nurb *nu;
+ const int max_idx = max_ii(0, cu->totcol - 1);
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->mat_nr > max_idx) {
+ nu->mat_nr = 0;
+ if (curvetype == OB_CURVE) {
+ nu->charidx = 0;
+ }
+ is_valid = false;
+ }
+ }
+ }
+
+ if (!is_valid) {
+ DAG_id_tag_update(&cu->id, OB_RECALC_DATA);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect)
{
r_rect->xmin = cu->xof + tb->x;
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index d072088ac8e..528ff2d7b19 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -559,7 +559,7 @@ void defgroup_unique_name(bDeformGroup *dg, Object *ob)
static bool is_char_sep(const char c)
{
- return ELEM4(c, '.', ' ', '-', '_');
+ return ELEM(c, '.', ' ', '-', '_');
}
/* based on BLI_split_dirfile() / os.path.splitext(), "a.b.c" -> ("a.b", ".c") */
@@ -614,6 +614,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
char replace[MAX_VGROUP_NAME] = ""; /* The replacement string */
char number[MAX_VGROUP_NAME] = ""; /* The number extension string */
char *index = NULL;
+ bool is_set = false;
/* always copy the name, since this can be called with an uninitialized string */
BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
@@ -640,6 +641,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
/* first case; separator . - _ with extensions r R l L */
if (is_char_sep(name[len - 2])) {
+ is_set = true;
switch (name[len - 1]) {
case 'l':
prefix[len - 1] = 0;
@@ -657,10 +659,14 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
prefix[len - 1] = 0;
strcpy(replace, "L");
break;
+ default:
+ is_set = false;
}
}
+
/* case; beginning with r R l L, with separator after it */
- else if (is_char_sep(name[1])) {
+ if (!is_set && is_char_sep(name[1])) {
+ is_set = true;
switch (name[0]) {
case 'l':
strcpy(replace, "r");
@@ -682,40 +688,43 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[
BLI_strncpy(suffix, name + 1, sizeof(suffix));
prefix[0] = 0;
break;
+ default:
+ is_set = false;
}
}
- else if (len > 5) {
+
+ if (!is_set && len > 5) {
/* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
- index = BLI_strcasestr(prefix, "right");
- if (index == prefix || index == prefix + len - 5) {
- if (index[0] == 'r')
+ if (((index = BLI_strcasestr(prefix, "right")) == prefix) ||
+ (index == prefix + len - 5))
+ {
+ is_set = true;
+ if (index[0] == 'r') {
strcpy(replace, "left");
+ }
else {
- if (index[1] == 'I')
- strcpy(replace, "LEFT");
- else
- strcpy(replace, "Left");
+ strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left");
}
*index = 0;
BLI_strncpy(suffix, index + 5, sizeof(suffix));
}
- else {
- index = BLI_strcasestr(prefix, "left");
- if (index == prefix || index == prefix + len - 4) {
- if (index[0] == 'l')
- strcpy(replace, "right");
- else {
- if (index[1] == 'E')
- strcpy(replace, "RIGHT");
- else
- strcpy(replace, "Right");
- }
- *index = 0;
- BLI_strncpy(suffix, index + 4, sizeof(suffix));
+ else if (((index = BLI_strcasestr(prefix, "left")) == prefix) ||
+ (index == prefix + len - 4))
+ {
+ is_set = true;
+ if (index[0] == 'l') {
+ strcpy(replace, "right");
+ }
+ else {
+ strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right");
}
+ *index = 0;
+ BLI_strncpy(suffix, index + 4, sizeof(suffix));
}
}
+ (void)is_set; /* quiet warning */
+
BLI_snprintf(name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 24b580672d1..93bb4849718 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -59,8 +59,10 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
+#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
@@ -79,6 +81,8 @@
#include "BKE_screen.h"
#include "BKE_tracking.h"
+#include "GPU_buffers.h"
+
#include "atomic_ops.h"
#include "depsgraph_private.h"
@@ -524,7 +528,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if (ct->tar->type == OB_MESH)
node3->customdata_mask |= CD_MASK_MDEFORMVERT;
}
- else if (ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))
+ else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))
dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name);
else
dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name);
@@ -688,6 +692,29 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper");
}
if (ob->type == OB_FONT) {
+ /* Really rather dirty hack. needs to support font family to work
+ * reliably on render export.
+ *
+ * This totally mimics behavior of regular verts duplication with
+ * parenting. The only tricky thing here is to get list of objects
+ * used for the custom "font".
+ *
+ * This shouldn't harm so much because this code only runs on DAG
+ * rebuild and this feature is not that commonly used.
+ *
+ * - sergey -
+ */
+ if (cu->family[0] != '\n') {
+ ListBase *duplilist;
+ DupliObject *dob;
+ duplilist = object_duplilist(G.main->eval_ctx, scene, ob);
+ for (dob = duplilist->first; dob; dob = dob->next) {
+ node2 = dag_get_node(dag, dob->ob);
+ dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font");
+ }
+ free_object_duplilist(duplilist);
+ }
+
if (cu->textoncurve) {
node2 = dag_get_node(dag, cu->textoncurve);
/* Text on curve requires path to be evaluated for the target curve. */
@@ -803,7 +830,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
continue;
/* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
int depends_on_camera = 0;
if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
@@ -843,7 +870,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
else {
- if (ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
+ if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
if (obt->type == OB_MESH)
node2->customdata_mask |= CD_MASK_MDEFORMVERT;
@@ -1386,7 +1413,7 @@ static bool check_object_needs_evaluation(Object *object)
if (object->type == OB_MESH) {
return object->derivedFinal == NULL;
}
- else if (ELEM5(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
return object->curve_cache == NULL;
}
@@ -1400,7 +1427,7 @@ static bool check_object_tagged_for_update(Object *object)
return true;
}
- if (ELEM6(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
ID *data_id = object->data;
return (data_id->flag & (LIB_ID_RECALC_DATA | LIB_ID_RECALC)) != 0;
}
@@ -1747,7 +1774,8 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
}
/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, int curtime, int reset)
+static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node,
+ int curtime, unsigned int lay, bool reset)
{
DagAdjList *itA;
Object *ob;
@@ -1761,14 +1789,17 @@ static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, int
if (reset || (ob->recalc & OB_RECALC_ALL)) {
if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
+ /* Don't tag nodes which are on invisible layer. */
+ if (itA->node->lay & lay) {
+ ob->recalc |= OB_RECALC_DATA;
+ lib_id_recalc_data_tag(bmain, &ob->id);
+ }
}
- flush_pointcache_reset(bmain, scene, itA->node, curtime, 1);
+ flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true);
}
else
- flush_pointcache_reset(bmain, scene, itA->node, curtime, 0);
+ flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false);
}
}
}
@@ -1885,10 +1916,12 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
lib_id_recalc_data_tag(bmain, &ob->id);
}
- flush_pointcache_reset(bmain, sce, itA->node, lasttime, 1);
+ flush_pointcache_reset(bmain, sce, itA->node, lasttime,
+ lay, true);
}
else
- flush_pointcache_reset(bmain, sce, itA->node, lasttime, 0);
+ flush_pointcache_reset(bmain, sce, itA->node, lasttime,
+ lay, false);
}
}
}
@@ -1983,7 +2016,7 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
if (cti) {
/* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
ob->recalc |= OB_RECALC_OB;
}
else if (cti->get_constraint_targets) {
@@ -2272,7 +2305,7 @@ static void dag_group_on_visible_update(Group *group)
group->id.flag |= LIB_DOIT;
for (go = group->gobject.first; go; go = go->next) {
- if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
go->ob->recalc |= OB_RECALC_DATA;
go->ob->id.flag |= LIB_DOIT;
lib_id_recalc_tag(G.main, &go->ob->id);
@@ -2319,7 +2352,7 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
oblay = (node) ? node->lay : ob->lay;
if ((oblay & lay) & ~scene->lay_updated) {
- if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
ob->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
}
@@ -2472,6 +2505,14 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
}
+ if (ELEM(idtype, ID_MA, ID_TE)) {
+ obt = sce->basact ? sce->basact->object : NULL;
+ if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
+ BKE_texpaint_slots_refresh_object(sce, obt);
+ GPU_drawobject_free(obt->derivedFinal);
+ }
+ }
+
if (idtype == ID_MC) {
MovieClip *clip = (MovieClip *) id;
@@ -2481,7 +2522,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
bConstraint *con;
for (con = obt->constraints.first; con; con = con->next) {
bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
CONSTRAINT_TYPE_OBJECTSOLVER))
{
obt->recalc |= OB_RECALC_OB;
@@ -2502,6 +2543,23 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
}
}
+ /* Not pretty to iterate all the nodes here, but it's as good as it
+ * could be with the current depsgraph design/
+ */
+ if (idtype == ID_IM) {
+ FOREACH_NODETREE(bmain, ntree, parent_id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->id == id) {
+ lib_id_recalc_tag(bmain, &ntree->id);
+ break;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
if (idtype == ID_MSK) {
if (sce->nodetree) {
bNode *node;
@@ -2742,7 +2800,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
if (ob->type == OB_FONT) {
Curve *cu = ob->data;
- if (ELEM4((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) {
+ if (ELEM((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) {
ob->recalc |= (flag & OB_RECALC_ALL);
}
}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index cf894e72324..98f0025921d 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -122,7 +122,7 @@ bool BKE_displist_has_faces(ListBase *lb)
DispList *dl;
for (dl = lb->first; dl; dl = dl->next) {
- if (ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
return true;
}
}
@@ -653,8 +653,8 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
bevels_to_filledpoly(cu, dispbase);
}
else {
- /* TODO, investigate passing zup instead of NULL */
- BKE_displist_fill(dispbase, dispbase, NULL, false);
+ const float z_up[3] = {0.0f, 0.0f, 1.0f};
+ BKE_displist_fill(dispbase, dispbase, z_up, false);
}
}
@@ -715,21 +715,20 @@ void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *
if (!ob || ob->type != OB_MBALL)
return;
- if (ob->curve_cache) {
- BKE_displist_free(&(ob->curve_cache->disp));
- }
- else {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
- }
+ if (ob == BKE_mball_basis_find(scene, ob)) {
+ if (ob->curve_cache) {
+ BKE_displist_free(&(ob->curve_cache->disp));
+ }
+ else {
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ }
- if (ob->type == OB_MBALL) {
- if (ob == BKE_mball_basis_find(scene, ob)) {
- BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp);
- BKE_mball_texspace_calc(ob);
+ BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp);
+ BKE_mball_texspace_calc(ob);
- object_deform_mball(ob, &ob->curve_cache->disp);
- }
+ object_deform_mball(ob, &ob->curve_cache->disp);
+ /* NOP for MBALLs anyway... */
boundbox_displist_object(ob);
}
}
@@ -767,7 +766,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob,
if (mti->type == eModifierTypeType_Constructive)
return pretessellatePoint;
- if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
+ if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
pretessellatePoint = md;
/* this modifiers are moving point of tessellation automatically
@@ -1357,31 +1356,57 @@ static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *disp
BLI_addtail(dispbase, dl);
}
+static void calc_bevfac_segment_mapping(BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
+{
+ float normlen, normsum = 0.0f;
+ float *seglen = bl->seglen;
+ int *segbevcount = bl->segbevcount;
+ int bevcount = 0, nr = bl->nr;
+
+ float bev_fl = bevfac * (bl->nr - 1);
+ *r_bev = (int)bev_fl;
+
+ while (bevcount < nr - 1) {
+ normlen = *seglen / spline_length;
+ if (normsum + normlen > bevfac) {
+ bev_fl = bevcount + (bevfac - normsum) / normlen * *segbevcount;
+ *r_bev = (int) bev_fl;
+ *r_blend = bev_fl - *r_bev;
+ break;
+ }
+ normsum += normlen;
+ bevcount += *segbevcount;
+ segbevcount++;
+ seglen++;
+ }
+}
-static void calc_bevfac_spline_mapping(BevList *bl, float bevfac, float spline_length, const float *bevp_array,
+static void calc_bevfac_spline_mapping(BevList *bl, float bevfac,
+ float spline_length,
int *r_bev, float *r_blend)
{
const float len_target = bevfac * spline_length;
- float len = 0.0f;
- float len_step = 0.0f;
- int i;
- for (i = 0; i < bl->nr - 1; i++) {
- float len_next;
- len_step = bevp_array[i];
- len_next = len + len_step;
+ BevPoint *bevp = bl->bevpoints;
+ float len_next = 0.0f, len = 0.0f;
+ int i = 0, nr = bl->nr;
+
+ while (nr--) {
+ bevp++;
+ len_next = len + bevp->offset;
if (len_next > len_target) {
break;
}
len = len_next;
+ i++;
}
*r_bev = i;
- *r_blend = (len_target - len) / len_step;
+ *r_blend = (len_target - len) / bevp->offset;
}
-static void calc_bevfac_mapping_default(
- BevList *bl,
- int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
+static void calc_bevfac_mapping_default(BevList *bl,
+ int *r_start, float *r_firstblend,
+ int *r_steps, float *r_lastblend)
{
*r_start = 0;
*r_steps = bl->nr;
@@ -1389,19 +1414,11 @@ static void calc_bevfac_mapping_default(
*r_lastblend = 1.0f;
}
-static void calc_bevfac_mapping(
- Curve *cu, BevList *bl, Nurb *nu, const bool use_render_resolution,
+static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu,
int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
{
- const int resolu = (nu->type == CU_POLY) ?
- 1 : (use_render_resolution && (cu->resolu_ren != 0)) ?
- cu->resolu_ren : cu->resolu;
- const int segcount = ((nu->type == CU_POLY) ? bl->nr : nu->pntsu) - 1;
-
- float l, startf, endf, tmpf, total_length = 0.0f;
- float *bevp_array = NULL;
- float *segments = NULL;
- int end = 0, i, j;
+ float tmpf, total_length = 0.0f;
+ int end = 0, i;
if ((BKE_nurb_check_valid_u(nu) == false) ||
/* not essential, but skips unnecessary calculation */
@@ -1412,57 +1429,12 @@ static void calc_bevfac_mapping(
return;
}
- if ((cu->bevfac1_mapping != CU_BEVFAC_MAP_RESOLU) ||
- (cu->bevfac2_mapping != CU_BEVFAC_MAP_RESOLU))
+ if (ELEM(cu->bevfac1_mapping,
+ CU_BEVFAC_MAP_SEGMENT,
+ CU_BEVFAC_MAP_SPLINE))
{
- BezTriple *bezt, *bezt_prev;
- BevPoint *bevp, *bevp_prev;
- int bevp_i;
-
- bevp_array = MEM_mallocN(sizeof(*bevp_array) * (bl->nr - 1), "bevp_dists");
- segments = MEM_callocN(sizeof(*segments) * segcount, "bevp_segmentlengths");
- bevp_prev = bl->bevpoints;
- bevp = bevp_prev + 1;
-
- if (nu->type == CU_BEZIER) {
- bezt_prev = nu->bezt;
- bezt = bezt_prev + 1;
- for (i = 0, bevp_i = 0; i < segcount; i++, bezt_prev++, bezt++) {
- float seglen = 0.0f;
- if (bezt_prev->h2 == HD_VECT && bezt->h1 == HD_VECT) {
- seglen = len_v3v3(bevp->vec, bevp_prev->vec);
- BLI_assert(bevp_i < bl->nr - 1);
- bevp_array[bevp_i++] = seglen;
-
- bevp_prev = bevp++;
- }
- else {
- for (j = 0; j < resolu; j++, bevp_prev = bevp++) {
- l = len_v3v3(bevp->vec, bevp_prev->vec);
- seglen += l;
- BLI_assert(bevp_i < bl->nr - 1);
- bevp_array[bevp_i++] = l;
- }
- }
- BLI_assert(i < segcount);
- segments[i] = seglen;
- total_length += seglen;
- seglen = 0.0f;
- }
- }
- else {
- float seglen = 0.0f;
- for (i = 1, j = 0; i < bl->nr; i++, bevp_prev = bevp++) {
- BLI_assert(i - 1 < bl->nr);
- bevp_array[i - 1] = len_v3v3(bevp->vec, bevp_prev->vec);
- total_length += bevp_array[i - 1];
- seglen += bevp_array[i - 1];
- if ((i % resolu) == 0 || (bl->nr - 1) == i) {
- BLI_assert(j < segcount);
- segments[j++] = seglen;
- seglen = 0.0f;
- }
- }
+ for (i = 0; i < SEGMENTSU(nu); i++) {
+ total_length += bl->seglen[i];
}
}
@@ -1471,31 +1443,18 @@ static void calc_bevfac_mapping(
{
const float start_fl = cu->bevfac1 * (bl->nr - 1);
*r_start = (int)start_fl;
-
*r_firstblend = 1.0f - (start_fl - (*r_start));
break;
}
case CU_BEVFAC_MAP_SEGMENT:
{
- float sum = 0.0f;
- const float start_fl = cu->bevfac1 * (bl->nr - 1);
- *r_start = (int)start_fl;
-
- for (i = 0; i < segcount; i++) {
- l = segments[i] / total_length;
- if (sum + l > cu->bevfac1) {
- startf = i * resolu + (cu->bevfac1 - sum) / l * resolu;
- *r_start = (int) startf;
- *r_firstblend = 1.0f - (startf - *r_start);
- break;
- }
- sum += l;
- }
+ calc_bevfac_segment_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
+ *r_firstblend = 1.0f - *r_firstblend;
break;
}
case CU_BEVFAC_MAP_SPLINE:
{
- calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, bevp_array, r_start, r_firstblend);
+ calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
*r_firstblend = 1.0f - *r_firstblend;
break;
}
@@ -1513,27 +1472,13 @@ static void calc_bevfac_mapping(
}
case CU_BEVFAC_MAP_SEGMENT:
{
- float sum = 0.0f;
- const float end_fl = cu->bevfac2 * (bl->nr - 1);
- end = (int)end_fl;
-
+ calc_bevfac_segment_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
*r_steps = end - *r_start + 2;
- for (i = 0; i < segcount; i++) {
- l = segments[i] / total_length;
- if (sum + l > cu->bevfac2) {
- endf = i * resolu + (cu->bevfac2 - sum) / l * resolu;
- end = (int)endf;
- *r_lastblend = (endf - end);
- *r_steps = end - *r_start + 2;
- break;
- }
- sum += l;
- }
break;
}
case CU_BEVFAC_MAP_SPLINE:
{
- calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, bevp_array, &end, r_lastblend);
+ calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
*r_steps = end - *r_start + 2;
break;
}
@@ -1551,13 +1496,6 @@ static void calc_bevfac_mapping(
*r_steps = bl->nr - *r_start;
*r_lastblend = 1.0f;
}
-
- if (bevp_array) {
- MEM_freeN(bevp_array);
- }
- if (segments) {
- MEM_freeN(segments);
- }
}
static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
@@ -1567,7 +1505,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
Curve *cu = ob->data;
/* we do allow duplis... this is only displist on curve level */
- if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
+ if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
if (ob->type == OB_SURF) {
BKE_displist_make_surf(scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution);
@@ -1576,7 +1514,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
ListBase dlbev;
ListBase nubase = {NULL, NULL};
- BLI_freelistN(&(ob->curve_cache->bev));
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
/* We only re-evlauate path if evaluation is not happening for orco.
* If the calculation happens for orco, we should never free data which
@@ -1668,8 +1606,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
continue;
}
- calc_bevfac_mapping(cu, bl, nu, use_render_resolution,
- &start, &firstblend, &steps, &lastblend);
+ calc_bevfac_mapping(cu, bl, nu, &start, &firstblend, &steps, &lastblend);
}
for (dlb = dlbev.first; dlb; dlb = dlb->next) {
@@ -1810,7 +1747,7 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco)
/* The same check for duplis as in do_makeDispListCurveTypes.
* Happens when curve used for constraint/bevel was converted to mesh.
* check there is still needed for render displist and orco displists. */
- if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT))
+ if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT))
return;
BKE_object_free_derived_caches(ob);
@@ -1831,7 +1768,7 @@ void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *
const bool use_render_resolution)
{
if (ob->curve_cache == NULL) {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
do_makeDispListCurveTypes(scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution);
@@ -1840,7 +1777,7 @@ void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *
void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
{
if (ob->curve_cache == NULL) {
- ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1);
@@ -1895,8 +1832,8 @@ void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
/* this is confusing, there's also min_max_object, appplying the obmat... */
static void boundbox_displist_object(Object *ob)
{
- if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- /* Curver's BB is already calculated as a part of modifier stack,
+ if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ /* Curve's BB is already calculated as a part of modifier stack,
* here we only calculate object BB based on final display list.
*/
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 11737bccef2..4719013e2f8 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2942,9 +2942,10 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float c
do {
float nearest_tmp[3], dist_sq;
- int vertex, edge;
-
- dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
+
+ closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
+ dist_sq = len_squared_v3v3(co, nearest_tmp);
+
if (dist_sq < nearest->dist_sq) {
nearest->index = index;
nearest->dist_sq = dist_sq;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index e74adea529b..ce7804d9878 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -910,7 +910,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
static void emDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
}
@@ -918,7 +918,7 @@ static void emDM_drawFacesTex(DerivedMesh *dm,
static void emDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
}
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 76ea340ecbd..442ab26ffc8 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -53,13 +53,17 @@ struct BMBVHTree {
int flag;
};
-BMBVHTree *BKE_bmbvh_new_from_editmesh(BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free)
+BMBVHTree *BKE_bmbvh_new_from_editmesh(
+ BMEditMesh *em, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free)
{
return BKE_bmbvh_new(em->bm, em->looptris, em->tottri, flag, cos_cage, cos_cage_free);
}
-BMBVHTree *BKE_bmbvh_new(BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, const float (*cos_cage)[3],
-const bool cos_cage_free)
+BMBVHTree *BKE_bmbvh_new_ex(
+ BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free,
+ bool (*test_fn)(BMFace *, void *user_data), void *user_data)
{
/* could become argument */
const float epsilon = FLT_EPSILON * 2.0f;
@@ -69,6 +73,10 @@ const bool cos_cage_free)
int i;
int tottri;
+ /* avoid testing every tri */
+ BMFace *f_test, *f_test_prev;
+ bool test_fn_ret;
+
/* BKE_editmesh_tessface_calc() must be called already */
BLI_assert(looptris_tot != 0 || bm->totface == 0);
@@ -83,18 +91,22 @@ const bool cos_cage_free)
bmtree->cos_cage_free = cos_cage_free;
bmtree->flag = flag;
- if (flag & (BMBVH_RESPECT_SELECT)) {
+ if (test_fn) {
+ /* callback must do... */
+ BLI_assert(!(flag & (BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN)));
+
+ f_test_prev = NULL;
+ test_fn_ret = false;
+
tottri = 0;
for (i = 0; i < looptris_tot; i++) {
- if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) {
- tottri++;
+ f_test = looptris[i][0]->f;
+ if (f_test != f_test_prev) {
+ test_fn_ret = test_fn(f_test, user_data);
+ f_test_prev = f_test;
}
- }
- }
- else if (flag & (BMBVH_RESPECT_HIDDEN)) {
- tottri = 0;
- for (i = 0; i < looptris_tot; i++) {
- if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
+
+ if (test_fn_ret) {
tottri++;
}
}
@@ -105,17 +117,19 @@ const bool cos_cage_free)
bmtree->tree = BLI_bvhtree_new(tottri, epsilon, 8, 8);
- for (i = 0; i < looptris_tot; i++) {
+ f_test_prev = NULL;
+ test_fn_ret = false;
- if (flag & BMBVH_RESPECT_SELECT) {
+ for (i = 0; i < looptris_tot; i++) {
+ if (test_fn) {
/* note, the arrays wont align now! take care */
- if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) {
- continue;
+ f_test = looptris[i][0]->f;
+ if (f_test != f_test_prev) {
+ test_fn_ret = test_fn(f_test, user_data);
+ f_test_prev = f_test;
}
- }
- else if (flag & BMBVH_RESPECT_HIDDEN) {
- /* note, the arrays wont align now! take care */
- if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
+
+ if (!test_fn_ret) {
continue;
}
}
@@ -139,6 +153,38 @@ const bool cos_cage_free)
return bmtree;
}
+static bool bm_face_is_select(BMFace *f, void *UNUSED(user_data))
+{
+ return (BM_elem_flag_test(f, BM_ELEM_SELECT) != 0);
+}
+
+static bool bm_face_is_not_hidden(BMFace *f, void *UNUSED(user_data))
+{
+ return (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == 0);
+}
+
+BMBVHTree *BKE_bmbvh_new(
+ BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free)
+{
+ bool (*test_fn)(BMFace *, void *user_data);
+
+ if (flag & BMBVH_RESPECT_SELECT) {
+ test_fn = bm_face_is_select;
+ }
+ else if (flag & BMBVH_RESPECT_HIDDEN) {
+ test_fn = bm_face_is_not_hidden;
+ }
+ else {
+ test_fn = NULL;
+ }
+
+ flag &= ~(BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN);
+
+ return BKE_bmbvh_new_ex(bm, looptris, looptris_tot, flag, cos_cage, cos_cage_free, test_fn, NULL);
+}
+
+
void BKE_bmbvh_free(BMBVHTree *bmtree)
{
BLI_bvhtree_free(bmtree->tree);
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index e28152dbc1a..4859aa8f791 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -935,7 +935,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected
if (pd->flag & PFIELD_DO_LOCATION) {
madd_v3_v3fl(total_force, force, 1.0f/point->vel_to_sec);
- if (ELEM3(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) {
+ if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) {
madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff);
}
}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index a8de9b69fbe..09c1dcf701d 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -276,7 +276,7 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix,
int matches = 0;
/* sanity checks */
- if (ELEM4(NULL, dst, src, dataPrefix, dataName))
+ if (ELEM(NULL, dst, src, dataPrefix, dataName))
return 0;
else if ((dataPrefix[0] == 0) || (dataName[0] == 0))
return 0;
@@ -522,17 +522,28 @@ bool calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, floa
/* only loop over keyframes to find extents for values if needed */
if (ymin || ymax) {
- BezTriple *bezt;
+ BezTriple *bezt, *prevbezt = NULL;
- for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
- if ((do_sel_only == false) || BEZSELECTED(bezt)) {
+ for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) {
+ if ((do_sel_only == false) || BEZSELECTED(bezt)) {
+ /* keyframe itself */
+ yminv = min_ff(yminv, bezt->vec[1][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[1][1]);
+
if (include_handles) {
- yminv = min_ffff(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
- ymaxv = max_ffff(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
- }
- else {
- yminv = min_ff(yminv, bezt->vec[1][1]);
- ymaxv = max_ff(ymaxv, bezt->vec[1][1]);
+ /* left handle - only if applicable
+ * NOTE: for the very first keyframe, the left handle actually has no bearings on anything
+ */
+ if (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)) {
+ yminv = min_ff(yminv, bezt->vec[0][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[0][1]);
+ }
+
+ /* right handle - only if applicable */
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ yminv = min_ff(yminv, bezt->vec[2][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[2][1]);
+ }
}
foundvert = true;
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 445acc850e6..4aa1b49ea13 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -187,7 +187,7 @@ FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char
BLI_addtail(&config->linesets, (void *)lineset);
BKE_freestyle_lineset_set_active_index(config, lineset_index);
- lineset->linestyle = BKE_new_linestyle("LineStyle", NULL);
+ lineset->linestyle = BKE_linestyle_new("LineStyle", NULL);
lineset->flags |= FREESTYLE_LINESET_ENABLED;
lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES | FREESTYLE_SEL_IMAGE_BORDER;
lineset->qi = FREESTYLE_QI_VISIBLE;
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index c381084cfd2..e226e9d9797 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -506,7 +506,7 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
bGPDlayer *gpl;
/* error checking */
- if (ELEM3(NULL, gpd, gpd->layers.first, active))
+ if (ELEM(NULL, gpd, gpd->layers.first, active))
return;
/* loop over layers deactivating all */
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 2e201a0b8e8..1b7a03ec80e 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -73,6 +73,8 @@ static IDType idtypes[] = {
{ ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE },
{ ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE },
{ ID_PA, "ParticleSettings", "particles", 0 },
+ { ID_PAL, "Palettes", "palettes", IDTYPE_FLAGS_ISLINKABLE },
+ { ID_PC, "PaintCurve", "paint_curves", IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCR, "Screen", "screens", 0 },
{ ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 3188676fb6c..4dbd15a3774 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -64,7 +64,7 @@ static char idp_size_table[] = {
/** \name IDP Array API
* \{ */
-#define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i))
+#define GETPROP(prop, i) &(IDP_IDPArray(prop)[i])
/* --------- property array type -------------*/
@@ -251,7 +251,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
newsize = newlen;
- newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;\
+ newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
if (is_grow == false)
idp_resize_group_array(prop, newlen, prop->data.pointer);
@@ -821,7 +821,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
case IDP_INT:
return (IDP_Int(prop1) == IDP_Int(prop2));
case IDP_FLOAT:
-#if defined(DEBUG) && defined(WITH_PYTHON)
+#if !defined(NDEBUG) && defined(WITH_PYTHON)
{
float p1 = IDP_Float(prop1);
float p2 = IDP_Float(prop2);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index db5c212d1db..805c1250c5d 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1257,7 +1257,7 @@ static bool do_add_image_extension(char *string, const char imtype, const ImageF
extension = extension_test;
}
#endif
- else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
+ else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
if (!BLI_testextensie(string, extension_test = ".png"))
extension = extension_test;
}
@@ -1900,7 +1900,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
ibuf->ftype = RADHDR;
}
#endif
- else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
+ else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
ibuf->ftype = PNG;
if (imtype == R_IMF_IMTYPE_PNG) {
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 6682b1a9b2d..4d80256426d 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1804,6 +1804,7 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo
return 1;
}
+
int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
{
unsigned int i=0;
@@ -1888,10 +1889,8 @@ int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase *
//if (do_extra_solve)
// cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
- for (i = 0; i < numverts; i++) {
-
- if (do_extra_solve) {
-
+ if (do_extra_solve) {
+ for (i = 0; i < numverts; i++) {
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED))
continue;
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 7385322ddeb..51cf26063c7 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1308,8 +1308,8 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i
* - they were degrees/10
* - we need radians for RNA to do the right thing
*/
- if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) ||
- ((icu->blocktype == ID_PO) && ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) )
+ if ( ((icu->blocktype == ID_OB) && ELEM(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) ||
+ ((icu->blocktype == ID_PO) && ELEM(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) )
{
const float fac = (float)M_PI / 18.0f; //10.0f * M_PI/180.0f;
@@ -1341,7 +1341,7 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i
DriverVar *dvar = fcu->driver->variables.first;
DriverTarget *dtar = &dvar->targets[0];
- if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
+ if (ELEM(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
const float fac = (float)M_PI / 18.0f;
dst->vec[0][0] *= fac;
@@ -1388,7 +1388,7 @@ static void ipo_to_animato(ID *id, Ipo *ipo, char actname[], char constname[], S
IpoCurve *icu;
/* sanity check */
- if (ELEM3(NULL, ipo, anim, drivers))
+ if (ELEM(NULL, ipo, anim, drivers))
return;
if (G.debug & G_DEBUG) printf("ipo_to_animato\n");
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index ea55f32ea05..3f12e3efcc7 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -729,7 +729,8 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh
Curve *cu;
int a;
CurveDeform cd;
- int use_vgroups;
+ MDeformVert *dvert = NULL;
+ int defgrp_index = -1;
const bool is_neg_axis = (defaxis > 2);
if (cuOb->type != OB_CURVE)
@@ -750,75 +751,63 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh
cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f;
}
- /* check whether to use vertex groups (only possible if target is a Mesh)
- * we want either a Mesh with no derived data, or derived data with
- * deformverts
+ /* Check whether to use vertex groups (only possible if target is a Mesh or Lattice).
+ * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
*/
- if (target->type == OB_MESH) {
- /* if there's derived data without deformverts, don't use vgroups */
- if (dm) {
- use_vgroups = (dm->getVertData(dm, 0, CD_MDEFORMVERT) != NULL);
- }
- else {
- Mesh *me = target->data;
- use_vgroups = (me->dvert != NULL);
+ if (vgroup && vgroup[0] && ELEM(target->type, OB_MESH, OB_LATTICE)) {
+ defgrp_index = defgroup_name_index(target, vgroup);
+
+ if (defgrp_index != -1) {
+ /* if there's derived data without deformverts, don't use vgroups */
+ if (dm) {
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+ }
+ else if (target->type == OB_LATTICE) {
+ dvert = ((Lattice *)target->data)->dvert;
+ }
+ else {
+ dvert = ((Mesh *)target->data)->dvert;
+ }
}
}
- else {
- use_vgroups = false;
- }
-
- if (vgroup && vgroup[0] && use_vgroups) {
- Mesh *me = target->data;
- const int defgrp_index = defgroup_name_index(target, vgroup);
- if (defgrp_index != -1 && (me->dvert || dm)) {
- MDeformVert *dvert = me->dvert;
- float vec[3];
- float weight;
-
+ if (dvert) {
+ MDeformVert *dvert_iter;
+ float vec[3];
- if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
- dvert = me->dvert;
- for (a = 0; a < numVerts; a++, dvert++) {
- if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
- weight = defvert_find_weight(dvert, defgrp_index);
-
- if (weight > 0.0f) {
- mul_m4_v3(cd.curvespace, vertexCos[a]);
- copy_v3_v3(vec, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
- mul_m4_v3(cd.objectspace, vertexCos[a]);
- }
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+ for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
+ const float weight = defvert_find_weight(dvert_iter, defgrp_index);
+
+ if (weight > 0.0f) {
+ mul_m4_v3(cd.curvespace, vertexCos[a]);
+ copy_v3_v3(vec, vertexCos[a]);
+ calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
+ interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
+ mul_m4_v3(cd.objectspace, vertexCos[a]);
}
}
- else {
- /* set mesh min/max bounds */
- INIT_MINMAX(cd.dmin, cd.dmax);
-
- for (a = 0; a < numVerts; a++, dvert++) {
- if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
-
- if (defvert_find_weight(dvert, defgrp_index) > 0.0f) {
- mul_m4_v3(cd.curvespace, vertexCos[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
- }
+ }
+ else {
+ /* set mesh min/max bounds */
+ INIT_MINMAX(cd.dmin, cd.dmax);
+
+ for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
+ if (defvert_find_weight(dvert_iter, defgrp_index) > 0.0f) {
+ mul_m4_v3(cd.curvespace, vertexCos[a]);
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
}
-
- dvert = me->dvert;
- for (a = 0; a < numVerts; a++, dvert++) {
- if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
-
- weight = defvert_find_weight(dvert, defgrp_index);
-
- if (weight > 0.0f) {
- /* already in 'cd.curvespace', prev for loop */
- copy_v3_v3(vec, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
- mul_m4_v3(cd.objectspace, vertexCos[a]);
- }
+ }
+
+ for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
+ const float weight = defvert_find_weight(dvert_iter, defgrp_index);
+
+ if (weight > 0.0f) {
+ /* already in 'cd.curvespace', prev for loop */
+ copy_v3_v3(vec, vertexCos[a]);
+ calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
+ interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
+ mul_m4_v3(cd.objectspace, vertexCos[a]);
}
}
}
@@ -1166,6 +1155,28 @@ void BKE_lattice_center_bounds(Lattice *lt, float cent[3])
mid_v3_v3v3(cent, min, max);
}
+void BKE_lattice_transform(Lattice *lt, float mat[4][4], bool do_keys)
+{
+ BPoint *bp = lt->def;
+ int i = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ while (i--) {
+ mul_m4_v3(mat, bp->vec);
+ bp++;
+ }
+
+ if (do_keys && lt->key) {
+ KeyBlock *kb;
+
+ for (kb = lt->key->block.first; kb; kb = kb->next) {
+ float *fp = kb->data;
+ for (i = kb->totelem; i--; fp += 3) {
+ mul_m4_v3(mat, fp);
+ }
+ }
+ }
+}
+
void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys)
{
int i, numVerts;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 1f3327b0dc4..515287de336 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -104,6 +104,7 @@
#include "BKE_mask.h"
#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_packedFile.h"
#include "BKE_speaker.h"
@@ -382,7 +383,7 @@ bool id_copy(ID *id, ID **newid, bool test)
if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id);
return true;
case ID_LS:
- if (!test) *newid = (ID *)BKE_copy_linestyle((FreestyleLineStyle *)id);
+ if (!test) *newid = (ID *)BKE_linestyle_copy((FreestyleLineStyle *)id);
return true;
}
@@ -515,6 +516,10 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->mask);
case ID_LS:
return &(mainlib->linestyle);
+ case ID_PAL:
+ return &(mainlib->palettes);
+ case ID_PC:
+ return &(mainlib->paintcurves);
}
return NULL;
}
@@ -596,6 +601,8 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[a++] = &(main->text);
lb[a++] = &(main->sound);
lb[a++] = &(main->group);
+ lb[a++] = &(main->palettes);
+ lb[a++] = &(main->paintcurves);
lb[a++] = &(main->brush);
lb[a++] = &(main->script);
lb[a++] = &(main->particle);
@@ -731,6 +738,12 @@ static ID *alloc_libblock_notest(short type)
case ID_LS:
id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style");
break;
+ case ID_PAL:
+ id = MEM_callocN(sizeof(Palette), "Palette");
+ break;
+ case ID_PC:
+ id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
+ break;
}
return id;
}
@@ -1005,7 +1018,13 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
BKE_mask_free(bmain, (Mask *)id);
break;
case ID_LS:
- BKE_free_linestyle((FreestyleLineStyle *)id);
+ BKE_linestyle_free((FreestyleLineStyle *)id);
+ break;
+ case ID_PAL:
+ BKE_palette_free((Palette *)id);
+ break;
+ case ID_PC:
+ BKE_paint_curve_free((PaintCurve *)id);
break;
}
@@ -1131,14 +1150,17 @@ void BKE_main_unlock(struct Main *bmain)
}
/* ***************** ID ************************ */
-
-
-ID *BKE_libblock_find_name(const short type, const char *name) /* type: "OB" or "MA" etc */
+ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name)
{
- ListBase *lb = which_libbase(G.main, type);
+ ListBase *lb = which_libbase(bmain, type);
BLI_assert(lb != NULL);
return BLI_findstring(lb, name, offsetof(ID, name) + 2);
}
+ID *BKE_libblock_find_name(const short type, const char *name)
+{
+ return BKE_libblock_find_name_ex(G.main, type, name);
+}
+
void id_sort_by_name(ListBase *lb, ID *id)
{
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index d92fa328e87..45695844101 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -43,6 +43,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
@@ -51,6 +53,8 @@
#include "BKE_colortools.h"
#include "BKE_animsys.h"
+#include "RNA_access.h"
+
static const char *modifier_name[LS_MODIFIER_NUM] = {
NULL,
"Along Stroke",
@@ -99,12 +103,12 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
BLI_listbase_clear(&linestyle->thickness_modifiers);
BLI_listbase_clear(&linestyle->geometry_modifiers);
- BKE_add_linestyle_geometry_modifier(linestyle, NULL, LS_MODIFIER_SAMPLING);
+ BKE_linestyle_geometry_modifier_add(linestyle, NULL, LS_MODIFIER_SAMPLING);
linestyle->caps = LS_CAPS_BUTT;
}
-FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main)
+FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main)
{
FreestyleLineStyle *linestyle;
@@ -118,7 +122,7 @@ FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main)
return linestyle;
}
-void BKE_free_linestyle(FreestyleLineStyle *linestyle)
+void BKE_linestyle_free(FreestyleLineStyle *linestyle)
{
LineStyleModifier *m;
@@ -137,33 +141,33 @@ void BKE_free_linestyle(FreestyleLineStyle *linestyle)
BKE_free_animdata(&linestyle->id);
while ((m = (LineStyleModifier *)linestyle->color_modifiers.first))
- BKE_remove_linestyle_color_modifier(linestyle, m);
+ BKE_linestyle_color_modifier_remove(linestyle, m);
while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first))
- BKE_remove_linestyle_alpha_modifier(linestyle, m);
+ BKE_linestyle_alpha_modifier_remove(linestyle, m);
while ((m = (LineStyleModifier *)linestyle->thickness_modifiers.first))
- BKE_remove_linestyle_thickness_modifier(linestyle, m);
+ BKE_linestyle_thickness_modifier_remove(linestyle, m);
while ((m = (LineStyleModifier *)linestyle->geometry_modifiers.first))
- BKE_remove_linestyle_geometry_modifier(linestyle, m);
+ BKE_linestyle_geometry_modifier_remove(linestyle, m);
}
-FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle)
+FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle)
{
FreestyleLineStyle *new_linestyle;
LineStyleModifier *m;
int a;
- new_linestyle = BKE_new_linestyle(linestyle->id.name + 2, NULL);
- BKE_free_linestyle(new_linestyle);
+ new_linestyle = BKE_linestyle_new(linestyle->id.name + 2, NULL);
+ BKE_linestyle_free(new_linestyle);
for (a = 0; a < MAX_MTEX; a++) {
if (linestyle->mtex[a]) {
- new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_copy_linestyle");
+ new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_linestyle_copy");
memcpy(new_linestyle->mtex[a], linestyle->mtex[a], sizeof(MTex));
id_us_plus((ID *)new_linestyle->mtex[a]->tex);
}
}
if (linestyle->nodetree) {
- linestyle->nodetree = ntreeCopyTree(linestyle->nodetree);
+ new_linestyle->nodetree = ntreeCopyTree(linestyle->nodetree);
}
new_linestyle->r = linestyle->r;
@@ -198,17 +202,29 @@ FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle)
new_linestyle->texstep = linestyle->texstep;
new_linestyle->pr_texture = linestyle->pr_texture;
for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next)
- BKE_copy_linestyle_color_modifier(new_linestyle, m);
+ BKE_linestyle_color_modifier_copy(new_linestyle, m);
for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next)
- BKE_copy_linestyle_alpha_modifier(new_linestyle, m);
+ BKE_linestyle_alpha_modifier_copy(new_linestyle, m);
for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next)
- BKE_copy_linestyle_thickness_modifier(new_linestyle, m);
+ BKE_linestyle_thickness_modifier_copy(new_linestyle, m);
for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next)
- BKE_copy_linestyle_geometry_modifier(new_linestyle, m);
+ BKE_linestyle_geometry_modifier_copy(new_linestyle, m);
return new_linestyle;
}
+FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene)
+{
+ SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ FreestyleConfig *config = &actsrl->freestyleConfig;
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+
+ if (lineset) {
+ return lineset->linestyle;
+ }
+ return NULL;
+}
+
static LineStyleModifier *new_modifier(const char *name, int type, size_t size)
{
LineStyleModifier *m;
@@ -255,7 +271,7 @@ static LineStyleModifier *alloc_color_modifier(const char *name, int type)
return new_modifier(name, type, size);
}
-LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, const char *name, int type)
+LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
{
LineStyleModifier *m;
@@ -289,7 +305,7 @@ LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyl
return m;
}
-LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -344,7 +360,7 @@ LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linesty
return new_m;
}
-int BKE_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
if (BLI_findindex(&linestyle->color_modifiers, m) == -1)
return -1;
@@ -389,7 +405,7 @@ static LineStyleModifier *alloc_alpha_modifier(const char *name, int type)
return new_modifier(name, type, size);
}
-LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, const char *name, int type)
+LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
{
LineStyleModifier *m;
@@ -435,7 +451,7 @@ LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyl
return m;
}
-LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -493,7 +509,7 @@ LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linesty
return new_m;
}
-int BKE_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
if (BLI_findindex(&linestyle->alpha_modifiers, m) == -1)
return -1;
@@ -542,7 +558,7 @@ static LineStyleModifier *alloc_thickness_modifier(const char *name, int type)
return new_modifier(name, type, size);
}
-LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, const char *name, int type)
+LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
{
LineStyleModifier *m;
@@ -604,7 +620,7 @@ LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *line
return m;
}
-LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -681,7 +697,7 @@ LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *lin
return new_m;
}
-int BKE_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
if (BLI_findindex(&linestyle->thickness_modifiers, m) == -1)
return -1;
@@ -756,7 +772,7 @@ static LineStyleModifier *alloc_geometry_modifier(const char *name, int type)
return new_modifier(name, type, size);
}
-LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, const char *name, int type)
+LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type)
{
LineStyleModifier *m;
@@ -874,7 +890,7 @@ LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *lines
return m;
}
-LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -1008,7 +1024,7 @@ LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *line
return new_m;
}
-int BKE_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+int BKE_linestyle_geometry_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m)
{
if (BLI_findindex(&linestyle->geometry_modifiers, m) == -1)
return -1;
@@ -1025,27 +1041,27 @@ static void move_modifier(ListBase *lb, LineStyleModifier *modifier, int directi
BLI_insertlinkafter(lb, modifier->next, modifier);
}
-void BKE_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+void BKE_linestyle_color_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
{
move_modifier(&linestyle->color_modifiers, modifier, direction);
}
-void BKE_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+void BKE_linestyle_alpha_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
{
move_modifier(&linestyle->alpha_modifiers, modifier, direction);
}
-void BKE_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+void BKE_linestyle_thickness_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
{
move_modifier(&linestyle->thickness_modifiers, modifier, direction);
}
-void BKE_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+void BKE_linestyle_geometry_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
{
move_modifier(&linestyle->geometry_modifiers, modifier, direction);
}
-void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase)
+void BKE_linestyle_modifier_list_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase)
{
LineStyleModifier *m;
ColorBand *color_ramp;
@@ -1076,7 +1092,7 @@ void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *list
}
}
-char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp)
+char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp)
{
LineStyleModifier *m;
bool found = false;
@@ -1107,11 +1123,11 @@ char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *c
return BLI_sprintfN("color_modifiers[\"%s\"].color_ramp", name_esc);
}
}
- printf("BKE_path_from_ID_to_color_ramp: No color ramps correspond to the given pointer.\n");
+ printf("BKE_linestyle_path_to_color_ramp: No color ramps correspond to the given pointer.\n");
return NULL;
}
-void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob)
+void BKE_linestyle_target_object_unlink(FreestyleLineStyle *linestyle, struct Object *ob)
{
LineStyleModifier *m;
@@ -1137,3 +1153,64 @@ void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Ob
}
}
}
+
+bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_shading_nodes)
+{
+ if (use_shading_nodes) {
+ if (linestyle && linestyle->use_nodes && linestyle->nodetree) {
+ bNode *node;
+
+ for (node = linestyle->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
+ return true;
+ }
+ }
+ }
+ }
+ else {
+ if (linestyle && (linestyle->flag & LS_TEXTURE)) {
+ return (linestyle->mtex[0] != NULL);
+ }
+ }
+ return false;
+}
+
+void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linestyle)
+{
+ bNode *uv_along_stroke, *input_texure, *output_linestyle;
+ bNodeSocket *fromsock, *tosock;
+ bNodeTree *ntree;
+
+ BLI_assert(linestyle->nodetree == NULL);
+
+ ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree");
+
+ linestyle->nodetree = ntree;
+
+ uv_along_stroke = nodeAddStaticNode(C, ntree, SH_NODE_UVALONGSTROKE);
+ uv_along_stroke->locx = 0.0f;
+ uv_along_stroke->locy = 300.0f;
+ uv_along_stroke->custom1 = 0; // use_tips
+
+ input_texure = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
+ input_texure->locx = 200.0f;
+ input_texure->locy = 300.0f;
+
+ output_linestyle = nodeAddStaticNode(C, ntree, SH_NODE_OUTPUT_LINESTYLE);
+ output_linestyle->locx = 400.0f;
+ output_linestyle->locy = 300.0f;
+ output_linestyle->custom1 = MA_RAMP_BLEND;
+ output_linestyle->custom2 = 0; // use_clamp
+
+ nodeSetActive(ntree, input_texure);
+
+ fromsock = BLI_findlink(&uv_along_stroke->outputs, 0); // UV
+ tosock = BLI_findlink(&input_texure->inputs, 0); // UV
+ nodeAddLink(ntree, uv_along_stroke, fromsock, input_texure, tosock);
+
+ fromsock = BLI_findlink(&input_texure->outputs, 0); // Color
+ tosock = BLI_findlink(&output_linestyle->inputs, 0); // Color
+ nodeAddLink(ntree, input_texure, fromsock, output_linestyle, tosock);
+
+ ntreeUpdateTree(CTX_data_main(C), ntree);
+}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 4147750c356..1c40446c217 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -1212,7 +1212,7 @@ void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float
}
invert_m3_m3(mask_to_clip_matrix, mask_from_clip_matrix);
- mul_serie_m3(parent_matrix, mask_to_clip_matrix, H, mask_from_clip_matrix, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(parent_matrix, mask_from_clip_matrix, H, mask_to_clip_matrix);
}
}
}
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 35207595103..4dc8ed21463 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -326,7 +326,7 @@ static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather
* are to any of the triangle edges.
*/
static bool layer_bucket_isect_test(
- MaskRasterLayer *layer, unsigned int face_index,
+ const MaskRasterLayer *layer, unsigned int face_index,
const unsigned int bucket_x, const unsigned int bucket_y,
const float bucket_size_x, const float bucket_size_y,
const float bucket_max_rad_squared)
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 971db1997de..eeca60f7ef4 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -63,6 +63,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
+#include "BKE_scene.h"
#include "BKE_node.h"
#include "BKE_curve.h"
@@ -111,6 +112,9 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
MEM_freeN(ma->nodetree);
}
+ if (ma->texpaintslot)
+ MEM_freeN(ma->texpaintslot);
+
if (ma->gpumaterial.first)
GPU_material_free(ma);
}
@@ -269,7 +273,8 @@ Material *localize_material(Material *ma)
if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
-
+
+ man->texpaintslot = NULL;
man->preview = NULL;
if (ma->nodetree)
@@ -467,7 +472,7 @@ Material ***give_matarar(Object *ob)
me = ob->data;
return &(me->mat);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
cu = ob->data;
return &(cu->mat);
}
@@ -488,7 +493,7 @@ short *give_totcolp(Object *ob)
me = ob->data;
return &(me->totcol);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
cu = ob->data;
return &(cu->totcol);
}
@@ -1291,7 +1296,7 @@ bool object_remove_material_slot(Object *ob)
}
/* check indices from mesh */
- if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
material_data_index_remove_id((ID *)ob->data, actcol - 1);
if (ob->curve_cache) {
BKE_displist_free(&ob->curve_cache->disp);
@@ -1301,6 +1306,124 @@ bool object_remove_material_slot(Object *ob)
return true;
}
+static bool get_mtex_slot_valid_texpaint(struct MTex *mtex)
+{
+ return (mtex && (mtex->texco == TEXCO_UV) &&
+ mtex->tex && (mtex->tex->type == TEX_IMAGE) &&
+ mtex->tex->ima);
+}
+
+void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
+{
+ MTex **mtex;
+ short count = 0;
+ short index = 0, i;
+
+ bool use_nodes = BKE_scene_use_new_shading_nodes(scene);
+ bool is_bi = BKE_scene_uses_blender_internal(scene);
+
+ if (!ma)
+ return;
+
+ if (ma->texpaintslot) {
+ MEM_freeN(ma->texpaintslot);
+ ma->tot_slots = 0;
+ ma->texpaintslot = NULL;
+ }
+
+ if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+
+ if (use_nodes || ma->use_nodes) {
+ bNode *node, *active_node;
+
+ if (!(ma->nodetree)) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+
+ for (node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id)
+ count++;
+ }
+
+ if (count == 0) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+ ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
+
+ active_node = nodeGetActiveTexture(ma->nodetree);
+
+ for (node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
+ if (active_node == node)
+ ma->paint_active_slot = index;
+ ma->texpaintslot[index++].ima = (Image *)node->id;
+ }
+ }
+ }
+ else if (is_bi) {
+ for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
+ if (get_mtex_slot_valid_texpaint(*mtex)) {
+ count++;
+ }
+ }
+
+ if (count == 0) {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+
+ ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
+
+ for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
+ if (get_mtex_slot_valid_texpaint(*mtex)) {
+ ma->texpaintslot[index].ima = (*mtex)->tex->ima;
+ ma->texpaintslot[index].uvname = (*mtex)->uvname;
+ ma->texpaintslot[index].index = i;
+
+ index++;
+ }
+ }
+ }
+ else {
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+ return;
+ }
+
+
+ ma->tot_slots = count;
+
+
+ if (ma->paint_active_slot >= count) {
+ ma->paint_active_slot = count - 1;
+ }
+
+ if (ma->paint_clone_slot >= count) {
+ ma->paint_clone_slot = count - 1;
+ }
+
+ return;
+}
+
+void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob)
+{
+ int i;
+
+ for (i = 1; i < ob->totcol + 1; i++) {
+ Material *ma = give_current_material(ob, i);
+ BKE_texpaint_slot_refresh_cache(scene, ma);
+ }
+}
+
/* r_col = current value, col = new value, (fac == 0) is no change */
void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
@@ -1573,7 +1696,7 @@ void copy_matcopybuf(Material *ma)
matcopybuf.mtex[a] = MEM_dupallocN(mtex);
}
}
- matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, false);
+ matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false);
matcopybuf.preview = NULL;
BLI_listbase_clear(&matcopybuf.gpumaterial);
matcopied = 1;
@@ -1626,7 +1749,7 @@ void paste_matcopybuf(Material *ma)
}
}
- ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, false);
+ ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, G.main, false);
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 43b19f0c869..453c6df6e3b 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -491,10 +491,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob != active_object) {
@@ -537,23 +534,17 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis)
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return NULL;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
- if (ob->type == OB_MBALL) {
+ if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
if (ob != bob) {
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
- /* object ob has to be in same "group" ... it means, that it has to have
- * same base of its name */
+ /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
if (strcmp(obname, basisname) == 0) {
if (obnr < basisnr) {
- if (!(ob->flag & OB_FROMDUPLI)) {
- basis = ob;
- basisnr = obnr;
- }
+ basis = ob;
+ basisnr = obnr;
}
}
}
@@ -2227,10 +2218,7 @@ static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *sc
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
process->totelem = 0;
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob == bob) {
@@ -2454,6 +2442,30 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3])
return 0;
}
+void BKE_mball_transform(MetaBall *mb, float mat[4][4])
+{
+ MetaElem *me;
+ float quat[4];
+ const float scale = mat4_to_scale(mat);
+ const float scale_sqrt = sqrtf(scale);
+
+ mat4_to_quat(quat, mat);
+
+ for (me = mb->elems.first; me; me = me->next) {
+ mul_m4_v3(mat, &me->x);
+ mul_qt_qtqt(me->quat, quat, me->quat);
+ me->rad *= scale;
+ /* hrmf, probably elems shouldn't be
+ * treating scale differently - campbell */
+ if (!MB_TYPE_SIZE_SQUARED(me->type)) {
+ mul_v3_fl(&me->expx, scale);
+ }
+ else {
+ mul_v3_fl(&me->expx, scale_sqrt);
+ }
+ }
+}
+
void BKE_mball_translate(MetaBall *mb, const float offset[3])
{
MetaElem *ml;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 2bf33b97a70..2e80379522c 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -115,16 +115,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
int i, i1 = 0, i2 = 0, tot, j;
for (i = 0; i < c1->totlayer; i++) {
- if (ELEM7(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i1++;
}
}
for (i = 0; i < c2->totlayer; i++) {
- if (ELEM7(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i2++;
}
@@ -135,16 +135,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
l1 = c1->layers; l2 = c2->layers;
tot = i1;
- i1 = 0; i2 = 0;
+ i1 = 0; i2 = 0;
for (i = 0; i < tot; i++) {
- while (i1 < c1->totlayer && !ELEM7(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i1++, l1++;
}
- while (i2 < c2->totlayer && !ELEM7(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i2++, l2++;
}
@@ -1869,6 +1869,27 @@ bool BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3])
return (me->totvert != 0);
}
+void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys)
+{
+ int i;
+ MVert *mvert = me->mvert;
+
+ for (i = 0; i < me->totvert; i++, mvert++)
+ mul_m4_v3(mat, mvert->co);
+
+ if (do_keys && me->key) {
+ KeyBlock *kb;
+ for (kb = me->key->block.first; kb; kb = kb->next) {
+ float *fp = kb->data;
+ for (i = kb->totelem; i--; fp += 3) {
+ mul_m4_v3(mat, fp);
+ }
+ }
+ }
+
+ /* don't update normals, caller can do this explicitly */
+}
+
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
{
int i = me->totvert;
@@ -2041,7 +2062,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type)
{
int i;
- BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL));
+ BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL));
for (i = 0; i < me->totselect; i++) {
if ((me->mselect[i].index == index) &&
@@ -2059,7 +2080,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type)
*/
int BKE_mesh_mselect_active_get(Mesh *me, int type)
{
- BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL));
+ BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL));
if (me->totselect) {
if (me->mselect[me->totselect - 1].type == type) {
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index cb0386b1203..4c9e44682c3 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -567,6 +567,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
copy_v3_v3(nor, lnor);
}
}
+ else {
+ /* We still have to clear the stack! */
+ while (BLI_SMALLSTACK_POP(normal));
+ }
}
ml_prev = ml_curr;
@@ -574,8 +578,6 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
}
}
- BLI_SMALLSTACK_FREE(normal);
-
MEM_freeN(edge_to_loops);
MEM_freeN(loop_to_poly);
@@ -729,7 +731,7 @@ void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangent
}
BKE_mesh_loop_tangents_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents,
- loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
+ loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
}
/** \} */
@@ -1096,6 +1098,125 @@ bool BKE_mesh_center_centroid(Mesh *me, float cent[3])
/* -------------------------------------------------------------------- */
+/** \name Mesh Volume Calculation
+ * \{ */
+
+static bool mesh_calc_center_centroid_ex(MVert *mverts, int UNUSED(numVerts),
+ MFace *mfaces, int numFaces,
+ float center[3])
+{
+ float totweight;
+ int f;
+
+ zero_v3(center);
+
+ if (numFaces == 0)
+ return false;
+
+ totweight = 0.0f;
+ for (f = 0; f < numFaces; ++f) {
+ MFace *face = &mfaces[f];
+ MVert *v1 = &mverts[face->v1];
+ MVert *v2 = &mverts[face->v2];
+ MVert *v3 = &mverts[face->v3];
+ MVert *v4 = &mverts[face->v4];
+ float area;
+
+ area = area_tri_v3(v1->co, v2->co, v3->co);
+ madd_v3_v3fl(center, v1->co, area);
+ madd_v3_v3fl(center, v2->co, area);
+ madd_v3_v3fl(center, v3->co, area);
+ totweight += area;
+
+ if (face->v4) {
+ area = area_tri_v3(v3->co, v4->co, v1->co);
+ madd_v3_v3fl(center, v3->co, area);
+ madd_v3_v3fl(center, v4->co, area);
+ madd_v3_v3fl(center, v1->co, area);
+ totweight += area;
+ }
+ }
+ if (totweight == 0.0f)
+ return false;
+
+ mul_v3_fl(center, 1.0f / (3.0f * totweight));
+
+ return true;
+}
+
+void BKE_mesh_calc_volume(MVert *mverts, int numVerts,
+ MFace *mfaces, int numFaces,
+ float *r_vol, float *r_com)
+{
+ float center[3];
+ float totvol;
+ int f;
+
+ if (r_vol) *r_vol = 0.0f;
+ if (r_com) zero_v3(r_com);
+
+ if (numFaces == 0)
+ return;
+
+ if (!mesh_calc_center_centroid_ex(mverts, numVerts, mfaces, numFaces, center))
+ return;
+
+ totvol = 0.0f;
+ for (f = 0; f < numFaces; ++f) {
+ MFace *face = &mfaces[f];
+ MVert *v1 = &mverts[face->v1];
+ MVert *v2 = &mverts[face->v2];
+ MVert *v3 = &mverts[face->v3];
+ MVert *v4 = &mverts[face->v4];
+ float vol;
+
+ vol = volume_tetrahedron_signed_v3(center, v1->co, v2->co, v3->co);
+ if (r_vol) {
+ totvol += vol;
+ }
+ if (r_com) {
+ /* averaging factor 1/4 is applied in the end */
+ madd_v3_v3fl(r_com, center, vol); // XXX could extract this
+ madd_v3_v3fl(r_com, v1->co, vol);
+ madd_v3_v3fl(r_com, v2->co, vol);
+ madd_v3_v3fl(r_com, v3->co, vol);
+ }
+
+ if (face->v4) {
+ vol = volume_tetrahedron_signed_v3(center, v3->co, v4->co, v1->co);
+
+ if (r_vol) {
+ totvol += vol;
+ }
+ if (r_com) {
+ /* averaging factor 1/4 is applied in the end */
+ madd_v3_v3fl(r_com, center, vol); // XXX could extract this
+ madd_v3_v3fl(r_com, v3->co, vol);
+ madd_v3_v3fl(r_com, v4->co, vol);
+ madd_v3_v3fl(r_com, v1->co, vol);
+ }
+ }
+ }
+
+ /* Note: Depending on arbitrary centroid position,
+ * totvol can become negative even for a valid mesh.
+ * The true value is always the positive value.
+ */
+ if (r_vol) {
+ *r_vol = fabsf(totvol);
+ }
+ if (r_com) {
+ /* Note: Factor 1/4 is applied once for all vertices here.
+ * This also automatically negates the vector if totvol is negative.
+ */
+ if (totvol != 0.0f)
+ mul_v3_fl(r_com, 0.25f / totvol);
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+
/** \name NGon Tessellation (NGon/Tessface Conversion)
* \{ */
@@ -2110,11 +2231,10 @@ void BKE_mesh_calc_relative_deform(
float tvec[3];
- barycentric_transform(
- tvec, vert_cos_dst[v_curr],
- vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],
- vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]
- );
+ transform_point_by_tri_v3(
+ tvec, vert_cos_dst[v_curr],
+ vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],
+ vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]);
add_v3_v3(vert_cos_new[v_curr], tvec);
vert_accum[v_curr] += 1;
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 65c576dd6a0..82065750791 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -442,7 +442,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
/* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
for (; i--; p++) {
int bit = poly_groups[*p];
- if (!ELEM3(bit, 0, poly_group_id, poly_group_id_overflowed) &&
+ if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
!(bit_poly_group_mask & bit))
{
bit_poly_group_mask |= bit;
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 858fe83b43f..f3a9e894eb3 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -164,16 +164,20 @@ static int search_poly_cmp(const void *v1, const void *v2)
{
const SortPoly *sp1 = v1, *sp2 = v2;
const int max_idx = sp1->numverts > sp2->numverts ? sp2->numverts : sp1->numverts;
- int idx = 0;
+ int idx;
/* Reject all invalid polys at end of list! */
if (sp1->invalid || sp2->invalid)
- return sp1->invalid && sp2->invalid ? 0 : sp1->invalid ? 1 : -1;
- /* Else, sort on first non-egal verts (remember verts of valid polys are sorted). */
- while (idx < max_idx && sp1->verts[idx] == sp2->verts[idx])
- idx++;
- return sp1->verts[idx] > sp2->verts[idx] ? 1 : sp1->verts[idx] < sp2->verts[idx] ? -1 :
- sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0;
+ return sp1->invalid ? (sp2->invalid ? 0 : 1) : -1;
+ /* Else, sort on first non-equal verts (remember verts of valid polys are sorted). */
+ for (idx = 0; idx < max_idx; idx++) {
+ const int v1 = sp1->verts[idx];
+ const int v2 = sp2->verts[idx];
+ if (v1 != v2) {
+ return (v1 > v2) ? 1 : -1;
+ }
+ }
+ return sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0;
}
static int search_polyloop_cmp(const void *v1, const void *v2)
@@ -255,7 +259,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
do_edge_recalc = do_fixes;
}
- for (i = 1; i < totvert; i++, mv++) {
+ for (i = 0; i < totvert; i++, mv++) {
bool fix_normal = true;
for (j = 0; j < 3; j++) {
@@ -498,8 +502,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
PRINT_ERR("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v);
sp->invalid = true;
}
-
- mverts[ml->v].flag |= ME_VERT_TMP_TAG;
+ else {
+ mverts[ml->v].flag |= ME_VERT_TMP_TAG;
+ }
*v = ml->v;
}
@@ -909,8 +914,6 @@ static bool mesh_validate_customdata(CustomData *data, CustomDataMask mask,
return is_valid;
}
-#undef PRINT
-
/**
* \returns is_valid.
*/
@@ -1052,8 +1055,36 @@ void BKE_mesh_cd_validate(Mesh *me)
}
}
}
-/** \} */
+/**
+ * Check all material indices of polygons are valid, invalid ones are set to 0.
+ * \returns is_valid.
+ */
+int BKE_mesh_validate_material_indices(Mesh *me)
+{
+ MPoly *mp;
+ const int max_idx = max_ii(0, me->totcol - 1);
+ const int totpoly = me->totpoly;
+ int i;
+ bool is_valid = true;
+
+ for (mp = me->mpoly, i = 0; i < totpoly; i++, mp++) {
+ if (mp->mat_nr > max_idx) {
+ mp->mat_nr = 0;
+ is_valid = false;
+ }
+ }
+
+ if (!is_valid) {
+ DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 1c42603cf4a..a9e853c873e 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -171,11 +171,14 @@ bool modifier_isPreview(ModifierData *md)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(mti->flags & eModifierTypeFlag_UsesPreview))
+ /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */
+ if (!((mti->flags & eModifierTypeFlag_UsesPreview) || (mti->type == eModifierTypeType_Constructive))) {
return false;
+ }
- if (md->mode & eModifierMode_Realtime)
+ if (md->mode & eModifierMode_Realtime) {
return true;
+ }
return false;
}
@@ -350,6 +353,7 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC
/* Find the last modifier acting on the cage. */
for (i = 0; md; i++, md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ bool supports_mapping;
md->scene = scene;
@@ -357,16 +361,17 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC
if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
if (md->mode & eModifierMode_DisableTemporary) continue;
+ supports_mapping = modifier_supportsMapping(md);
+ if (r_lastPossibleCageIndex && supports_mapping) {
+ *r_lastPossibleCageIndex = i;
+ }
+
if (!(md->mode & eModifierMode_Realtime)) continue;
if (!(md->mode & eModifierMode_Editmode)) continue;
- if (!modifier_supportsMapping(md))
+ if (!supports_mapping)
break;
- if (r_lastPossibleCageIndex) {
- *r_lastPossibleCageIndex = i;
- }
-
if (md->mode & eModifierMode_OnCage)
cageIndex = i;
}
@@ -409,13 +414,12 @@ bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode
md->scene = scene;
- if ((md->mode & required_mode) != required_mode) return 0;
- if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return 0;
- if (md->mode & eModifierMode_DisableTemporary) return 0;
- if (required_mode & eModifierMode_Editmode)
- if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0;
+ if ((md->mode & required_mode) != required_mode) return false;
+ if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return false;
+ if (md->mode & eModifierMode_DisableTemporary) return false;
+ if ((required_mode & eModifierMode_Editmode) && !(mti->flags & eModifierTypeFlag_SupportsEditmode)) return false;
- return 1;
+ return true;
}
CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData *md,
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 1d5bbbe1aeb..246ef8a33f5 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -112,7 +112,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden,
/* assumed to be at hi_level (or
* null) */
- BLI_bitmap *prev_hidden)
+ const BLI_bitmap *prev_hidden)
{
BLI_bitmap *subd;
int hi_gridsize = BKE_ccg_gridsize(hi_level);
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index d0114d52a06..19e45142960 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -430,7 +430,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short
return (strip->end + (strip->actstart * scale - cframe)) / scale;
}
else { /* if (mode == NLATIME_CONVERT_EVAL) */
- if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
+ if (IS_EQF((float)cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) {
/* this case prevents the motion snapping back to the first frame at the end of the strip
* by catching the case where repeats is a whole number, which means that the end of the strip
* could also be interpreted as the end of the start of a repeat
@@ -453,7 +453,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short
return strip->actstart + (cframe - strip->start) / scale;
}
else { /* if (mode == NLATIME_CONVERT_EVAL) */
- if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
+ if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) {
/* this case prevents the motion snapping back to the first frame at the end of the strip
* by catching the case where repeats is a whole number, which means that the end of the strip
* could also be interpreted as the end of the start of a repeat
@@ -1637,7 +1637,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
}
}
- if (ELEM3(NULL, activeTrack, activeStrip, activeStrip->act)) {
+ if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) {
if (G.debug & G_DEBUG) {
printf("NLA tweakmode enter - neither active requirement found\n");
printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip);
@@ -1744,7 +1744,7 @@ static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimDat
* 1) Scene and AnimData must be provided
* 2) there must be tracks to merge...
*/
- if (ELEM3(NULL, scene, adt, adt->nla_tracks.first))
+ if (ELEM(NULL, scene, adt, adt->nla_tracks.first))
return;
/* if animdata currently has an action, 'push down' this onto the stack first */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 56a76a54955..0f86b551092 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1205,13 +1205,13 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_
return newtree;
}
-bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const bool do_id_user)
+bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user)
{
- return ntreeCopyTree_internal(ntree, G.main, do_id_user, true, true);
+ return ntreeCopyTree_internal(ntree, bmain, do_id_user, true, true);
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
- return ntreeCopyTree_ex(ntree, true);
+ return ntreeCopyTree_ex(ntree, G.main, true);
}
/* use when duplicating scenes */
@@ -3406,6 +3406,7 @@ static void registerCompositNodes(void)
register_node_type_cmp_inpaint();
register_node_type_cmp_despeckle();
register_node_type_cmp_defocus();
+ register_node_type_cmp_sunbeams();
register_node_type_cmp_valtorgb();
register_node_type_cmp_rgbtobw();
@@ -3528,10 +3529,12 @@ static void registerShaderNodes(void)
register_node_type_sh_mix_shader();
register_node_type_sh_add_shader();
register_node_type_sh_uvmap();
+ register_node_type_sh_uvalongstroke();
register_node_type_sh_output_lamp();
register_node_type_sh_output_material();
register_node_type_sh_output_world();
+ register_node_type_sh_output_linestyle();
register_node_type_sh_tex_image();
register_node_type_sh_tex_environment();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 3490bb9ffbd..b09016506e3 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -42,6 +42,7 @@
#include "DNA_constraint_types.h"
#include "DNA_group_types.h"
#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_material_types.h"
#include "DNA_meta_types.h"
@@ -180,7 +181,7 @@ void BKE_object_free_curve_cache(Object *ob)
{
if (ob->curve_cache) {
BKE_displist_free(&ob->curve_cache->disp);
- BLI_freelistN(&ob->curve_cache->bev);
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
if (ob->curve_cache->path) {
free_path(ob->curve_cache->path);
}
@@ -246,7 +247,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
ModifierData *md;
BKE_object_free_modifiers(ob_dst);
- if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ if (!ELEM(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
/* only objects listed above can have modifiers and linking them to objects
* which doesn't have modifiers stack is quite silly */
return;
@@ -255,11 +256,11 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
for (md = ob_src->modifiers.first; md; md = md->next) {
ModifierData *nmd = NULL;
- if (ELEM4(md->type,
- eModifierType_Hook,
- eModifierType_Softbody,
- eModifierType_ParticleInstance,
- eModifierType_Collision))
+ if (ELEM(md->type,
+ eModifierType_Hook,
+ eModifierType_Softbody,
+ eModifierType_ParticleInstance,
+ eModifierType_Collision))
{
continue;
}
@@ -296,7 +297,7 @@ void BKE_object_free_derived_caches(Object *ob)
me->bb->flag |= BOUNDBOX_DIRTY;
}
}
- else if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+ else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
Curve *cu = ob->data;
if (cu->bb) {
@@ -322,7 +323,7 @@ void BKE_object_free_derived_caches(Object *ob)
if (ob->curve_cache) {
BKE_displist_free(&ob->curve_cache->disp);
- BLI_freelistN(&ob->curve_cache->bev);
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
if (ob->curve_cache->path) {
free_path(ob->curve_cache->path);
ob->curve_cache->path = NULL;
@@ -408,7 +409,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
/* Free runtime curves data. */
if (ob->curve_cache) {
- BLI_freelistN(&ob->curve_cache->bev);
+ BKE_curve_bevelList_free(&ob->curve_cache->bev);
if (ob->curve_cache->path)
free_path(ob->curve_cache->path);
MEM_freeN(ob->curve_cache);
@@ -709,7 +710,7 @@ void BKE_object_unlink(Object *ob)
lineset; lineset = lineset->next)
{
if (lineset->linestyle) {
- BKE_unlink_linestyle_target_object(lineset->linestyle, ob);
+ BKE_linestyle_target_object_unlink(lineset->linestyle, ob);
}
}
}
@@ -873,9 +874,9 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob)
{
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
- return ( (ob->mode & OB_MODE_WEIGHT_PAINT) &&
- (me->edit_btmesh == NULL) &&
- (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX) );
+ return ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
+ (me->edit_btmesh == NULL) &&
+ (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX));
}
return false;
@@ -977,7 +978,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob->empty_drawtype = OB_PLAINAXES;
ob->empty_drawsize = 1.0;
- if (ELEM3(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
ob->trackflag = OB_NEGZ;
ob->upflag = OB_POSY;
}
@@ -1526,6 +1527,18 @@ Object *BKE_object_copy(Object *ob)
return BKE_object_copy_ex(G.main, ob, false);
}
+static void extern_local_object__modifiersForeachIDLink(
+ void *UNUSED(userData), Object *UNUSED(ob),
+ ID **idpoin)
+{
+ if (*idpoin) {
+ /* intentionally omit ID_OB */
+ if (ELEM(GS((*idpoin)->name), ID_IM, ID_TE)) {
+ id_lib_extern(*idpoin);
+ }
+ }
+}
+
static void extern_local_object(Object *ob)
{
ParticleSystem *psys;
@@ -1539,6 +1552,8 @@ static void extern_local_object(Object *ob)
for (psys = ob->particlesystem.first; psys; psys = psys->next)
id_lib_extern((ID *)psys->part);
+
+ modifiers_foreachIDLink(ob, extern_local_object__modifiersForeachIDLink, NULL);
}
void BKE_object_make_local(Object *ob)
@@ -1778,6 +1793,55 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
ob->dt = target->dt;
}
+/**
+ * Use with newly created objects to set their size
+ * (used to apply scene-scale).
+ */
+void BKE_object_obdata_size_init(struct Object *ob, const float size)
+{
+ /* apply radius as a scale to types that support it */
+ switch (ob->type) {
+ case OB_EMPTY:
+ {
+ ob->empty_drawsize *= size;
+ break;
+ }
+ case OB_FONT:
+ {
+ Curve *cu = ob->data;
+ cu->fsize *= size;
+ break;
+ }
+ case OB_CAMERA:
+ {
+ Camera *cam = ob->data;
+ cam->drawsize *= size;
+ break;
+ }
+ case OB_LAMP:
+ {
+ Lamp *lamp = ob->data;
+ lamp->dist *= size;
+ lamp->area_size *= size;
+ lamp->area_sizey *= size;
+ lamp->area_sizez *= size;
+ break;
+ }
+ /* Only lattice (not mesh, curve, mball...),
+ * because its got data when newly added */
+ case OB_LATTICE:
+ {
+ struct Lattice *lt = ob->data;
+ float mat[4][4];
+
+ unit_m4(mat);
+ scale_m4_fl(mat, size);
+
+ BKE_lattice_transform(lt, (float (*)[4])mat, false);
+ break;
+ }
+ }
+}
/* *************** CALC ****************** */
@@ -1978,7 +2042,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
unit_m4(mat);
cu = par->data;
- if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
+ if (ELEM(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
BKE_displist_make_curveTypes(scene, par, 0);
if (par->curve_cache->path == NULL) return;
@@ -1994,17 +2058,20 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
* we divide the curvetime calculated in the previous step by the length of the path, to get a time
* factor, which then gets clamped to lie within 0.0 - 1.0 range
*/
- if (IS_EQF(cu->pathlen, 0.0f) == 0)
+ if (cu->pathlen) {
ctime = cu->ctime / cu->pathlen;
- else
+ }
+ else {
ctime = cu->ctime;
+ }
CLAMP(ctime, 0.0f, 1.0f);
}
else {
ctime = BKE_scene_frame_get(scene);
- if (IS_EQF(cu->pathlen, 0.0f) == 0)
+ if (cu->pathlen) {
ctime /= cu->pathlen;
+ }
CLAMP(ctime, 0.0f, 1.0f);
}
@@ -2289,7 +2356,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat
int a;
/* include framerate */
- fac1 = (1.0f / (1.0f + fabsf(ob->sf)) );
+ fac1 = (1.0f / (1.0f + fabsf(ob->sf)));
if (fac1 >= 1.0f) return 0;
fac2 = 1.0f - fac1;
@@ -2466,6 +2533,20 @@ void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float
bb->vec[1][2] = bb->vec[2][2] = bb->vec[5][2] = bb->vec[6][2] = max[2];
}
+void BKE_boundbox_calc_center_aabb(const BoundBox *bb, float r_cent[3])
+{
+ r_cent[0] = 0.5f * (bb->vec[0][0] + bb->vec[4][0]);
+ r_cent[1] = 0.5f * (bb->vec[0][1] + bb->vec[2][1]);
+ r_cent[2] = 0.5f * (bb->vec[0][2] + bb->vec[1][2]);
+}
+
+void BKE_boundbox_calc_size_aabb(const BoundBox *bb, float r_size[3])
+{
+ r_size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]);
+ r_size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]);
+ r_size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]);
+}
+
BoundBox *BKE_object_boundbox_get(Object *ob)
{
BoundBox *bb = NULL;
@@ -2473,7 +2554,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
if (ob->type == OB_MESH) {
bb = BKE_mesh_boundbox_get(ob);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
bb = BKE_curve_boundbox_get(ob);
}
else if (ob->type == OB_MBALL) {
@@ -2483,7 +2564,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
}
/* used to temporally disable/enable boundbox */
-void BKE_object_boundbox_flag(Object *ob, int flag, int set)
+void BKE_object_boundbox_flag(Object *ob, int flag, const bool set)
{
BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
@@ -3126,8 +3207,10 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc,
* Test a bounding box for ray intersection
* assumes the ray is already local to the boundbox space
*/
-bool BKE_boundbox_ray_hit_check(struct BoundBox *bb, const float ray_start[3], const float ray_normal[3],
- float *r_lambda)
+bool BKE_boundbox_ray_hit_check(
+ const struct BoundBox *bb,
+ const float ray_start[3], const float ray_normal[3],
+ float *r_lambda)
{
const int triangle_indexes[12][3] = {
{0, 1, 2}, {0, 2, 3},
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 707438bc673..0d82c6e89a1 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -754,14 +754,14 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj
if (orco) {
int j;
- for (j = 0; j < mpoly->totloop; j++) {
+ for (j = 0; j < mp->totloop; j++) {
madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w);
}
}
if (mloopuv) {
int j;
- for (j = 0; j < mpoly->totloop; j++) {
+ for (j = 0; j < mp->totloop; j++) {
madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w);
}
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 9a144b5461a..4382d74f34e 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -45,8 +45,10 @@
#include "BLI_bitmap.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_listbase.h"
#include "BKE_brush.h"
+#include "BKE_main.h"
#include "BKE_context.h"
#include "BKE_crazyspace.h"
#include "BKE_depsgraph.h"
@@ -269,6 +271,105 @@ void BKE_paint_brush_set(Paint *p, Brush *br)
}
}
+void BKE_paint_curve_free(PaintCurve *pc)
+{
+ if (pc->points) {
+ MEM_freeN(pc->points);
+ pc->points = NULL;
+ pc->tot_points = 0;
+ }
+}
+
+PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name)
+{
+ PaintCurve *pc;
+
+ pc = BKE_libblock_alloc(bmain, ID_PC, name);
+
+ return pc;
+}
+
+Palette *BKE_paint_palette(Paint *p)
+{
+ return p ? p->palette : NULL;
+}
+
+void BKE_paint_palette_set(Paint *p, Palette *palette)
+{
+ if (p) {
+ id_us_min((ID *)p->palette);
+ id_us_plus((ID *)palette);
+ p->palette = palette;
+ }
+}
+
+void BKE_paint_curve_set(Brush *br, PaintCurve *pc)
+{
+ if (br) {
+ id_us_min((ID *)br->paint_curve);
+ id_us_plus((ID *)pc);
+ br->paint_curve = pc;
+ }
+}
+
+/* remove colour from palette. Must be certain color is inside the palette! */
+void BKE_palette_color_remove(Palette *palette, PaletteColor *color)
+{
+ BLI_remlink(&palette->colors, color);
+ BLI_addhead(&palette->deleted, color);
+}
+
+void BKE_palette_cleanup(Palette *palette)
+{
+ BLI_freelistN(&palette->deleted);
+}
+
+
+Palette *BKE_palette_add(Main *bmain, const char *name)
+{
+ Palette *palette;
+
+ palette = BKE_libblock_alloc(bmain, ID_PAL, name);
+
+ /* enable fake user by default */
+ palette->id.flag |= LIB_FAKEUSER;
+
+ return palette;
+}
+
+void BKE_palette_free(Palette *palette)
+{
+ BLI_freelistN(&palette->colors);
+}
+
+PaletteColor *BKE_palette_color_add(Palette *palette)
+{
+ PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color");
+ BLI_addtail(&palette->colors, color);
+ palette->active_color = BLI_countlist(&palette->colors) - 1;
+ return color;
+}
+
+void BKE_palette_color_delete(struct Palette *palette)
+{
+ PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color);
+
+ if (color) {
+ if ((color == palette->colors.last) && (palette->colors.last != palette->colors.first))
+ palette->active_color--;
+
+ BLI_remlink(&palette->colors, color);
+ BLI_addhead(&palette->deleted, color);
+ }
+}
+
+
+bool BKE_palette_is_empty(const struct Palette *palette)
+{
+ return BLI_listbase_is_empty(&palette->colors);
+}
+
+
/* are we in vertex paint or weight pain face select mode? */
bool BKE_paint_select_face_test(Object *ob)
{
@@ -318,6 +419,7 @@ void BKE_paint_init(Paint *p, const char col[3])
void BKE_paint_free(Paint *paint)
{
id_us_min((ID *)paint->brush);
+ id_us_min((ID *)paint->palette);
}
/* called when copying scene settings, so even if 'src' and 'tar' are the same
@@ -328,6 +430,7 @@ void BKE_paint_copy(Paint *src, Paint *tar)
{
tar->brush = src->brush;
id_us_plus((ID *)tar->brush);
+ id_us_plus((ID *)tar->palette);
}
/* returns non-zero if any of the face's vertices
@@ -378,7 +481,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
return gpm->data[(y * factor) * gridsize + (x * factor)];
}
-/* threshhold to move before updating the brush rotation */
+/* threshold to move before updating the brush rotation */
#define RAKE_THRESHHOLD 20
void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2])
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 8161f9d8875..27d346f65b9 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -1657,11 +1657,14 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f
index_mp_to_orig = NULL;
}
+ totface = dm->getNumTessFaces(dm);
+ if (!totface) {
+ return DMCACHE_NOTFOUND;
+ }
+
mpoly = dm->getPolyArray(dm);
osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
- totface = dm->getNumTessFaces(dm);
-
if (osface == NULL || index_mf_to_mpoly == NULL) {
/* Assume we don't need osface data */
if (index < totface) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 06ac9db0b16..09e20c02691 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -117,7 +117,7 @@ static int particles_are_dynamic(ParticleSystem *psys)
if (psys->part->type == PART_HAIR)
return psys->flag & PSYS_HAIR_DYNAMICS;
else
- return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
+ return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
}
float psys_get_current_display_percentage(ParticleSystem *psys)
@@ -399,7 +399,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
}
}
- if (origindex_final != ORIGINDEX_NONE) {
+ if (origindex_final != ORIGINDEX_NONE && origindex_final < totelem) {
if (nodearray[origindex_final]) {
/* prepend */
node->next = nodearray[origindex_final];
@@ -507,7 +507,7 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
sub_v3_v3v3(delta, max, min);
/* determine major axis */
- axis = (delta[0]>=delta[1]) ? 0 : ((delta[1]>=delta[2]) ? 1 : 2);
+ axis = axis_dominant_v3_single(delta);
d = delta[axis]/(float)res;
@@ -1079,7 +1079,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL;
float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
- if (ELEM3(NULL, ob, psys, psys->part))
+ if (ELEM(NULL, ob, psys, psys->part))
return 0;
part=psys->part;
@@ -2638,7 +2638,7 @@ static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr)
mul_v3_v3fl(sphdata->flow, flow, 1.0f / pfr->tot_neighbors);
}
else {
- sphdata->element_size = MAXFLOAT;
+ sphdata->element_size = FLT_MAX;
copy_v3_v3(sphdata->flow, flow);
}
}
@@ -3153,7 +3153,7 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
extrotfac = 0.0f;
}
- if ((part->flag & PART_ROT_DYN) && ELEM3(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
+ if ((part->flag & PART_ROT_DYN) && ELEM(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
float angle;
float len1 = len_v3(pa->prev_state.vel);
float len2 = len_v3(pa->state.vel);
@@ -4012,6 +4012,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
if (!psys->clmd) {
psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
psys->clmd->sim_parms->goalspring = 0.0f;
+ psys->clmd->sim_parms->vel_damping = 1.0f;
psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
}
@@ -4846,13 +4847,13 @@ void psys_changed_type(Object *ob, ParticleSystem *psys)
psys->flag &= ~PSYS_KEYED;
if (part->type == PART_HAIR) {
- if (ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
+ if (ELEM(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
part->ren_as = PART_DRAW_PATH;
if (part->distr == PART_DISTR_GRID)
part->distr = PART_DISTR_JIT;
- if (ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
+ if (ELEM(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
part->draw_as = PART_DRAW_REND;
CLAMP(part->path_start, 0.0f, 100.0f);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 1a815cf0dee..3e763016efb 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -50,6 +50,15 @@
#define STACK_FIXED_DEPTH 100
+/* Setting zero so we can catch bugs in OpenMP/PBVH. */
+#ifdef _OPENMP
+# ifdef DEBUG
+# define PBVH_OMP_LIMIT 0
+# else
+# define PBVH_OMP_LIMIT 8
+# endif
+#endif
+
typedef struct PBVHStack {
PBVHNode *node;
int revisiting;
@@ -965,7 +974,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
* can only update vertices marked with ME_VERT_PBVH_UPDATE.
*/
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1009,7 +1018,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
}
}
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1046,7 +1055,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
int n;
/* update BB, redraw flag */
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 90b5d8cf1a1..b2178fe69b3 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -284,7 +284,7 @@ Report *BKE_reports_last_displayable(ReportList *reports)
Report *report;
for (report = reports->list.last; report; report = report->prev) {
- if (ELEM3(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO))
+ if (ELEM(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO))
return report;
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 09293503ad5..3d61b0bdefb 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -57,6 +57,7 @@
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
@@ -287,10 +288,10 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
DM_ensure_tessface(dm);
- mvert = (dm) ? dm->getVertArray(dm) : NULL;
- totvert = (dm) ? dm->getNumVerts(dm) : 0;
- mface = (dm) ? dm->getTessFaceArray(dm) : NULL;
- totface = (dm) ? dm->getNumTessFaces(dm) : 0;
+ mvert = dm->getVertArray(dm);
+ totvert = dm->getNumVerts(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
/* sanity checking - potential case when no data will be present */
if ((totvert == 0) || (totface == 0)) {
@@ -344,7 +345,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
}
/* cleanup temp data */
- if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
+ if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
dm->release(dm);
}
}
@@ -394,7 +395,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
}
mul_v3_fl(size, 0.5f);
- if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+ if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
/* take radius as largest x/y dimension, and height as z-dimension */
radius = MAX2(size[0], size[1]);
height = size[2];
@@ -455,6 +456,182 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
/* --------------------- */
+/* helper function to calculate volume of rigidbody object */
+// TODO: allow a parameter to specify method used to calculate this?
+void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ float size[3] = {1.0f, 1.0f, 1.0f};
+ float radius = 1.0f;
+ float height = 1.0f;
+
+ float volume = 0.0f;
+
+ /* if automatically determining dimensions, use the Object's boundbox
+ * - assume that all quadrics are standing upright on local z-axis
+ * - assume even distribution of mass around the Object's pivot
+ * (i.e. Object pivot is centralized in boundbox)
+ * - boundbox gives full width
+ */
+ // XXX: all dimensions are auto-determined now... later can add stored settings for this
+ BKE_object_dimensions_get(ob, size);
+
+ if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+ /* take radius as largest x/y dimension, and height as z-dimension */
+ radius = MAX2(size[0], size[1]) * 0.5f;
+ height = size[2];
+ }
+ else if (rbo->shape == RB_SHAPE_SPHERE) {
+ /* take radius to the the largest dimension to try and encompass everything */
+ radius = max_fff(size[0], size[1], size[2]) * 0.5f;
+ }
+
+ /* calculate volume as appropriate */
+ switch (rbo->shape) {
+ case RB_SHAPE_BOX:
+ volume = size[0] * size[1] * size[2];
+ break;
+
+ case RB_SHAPE_SPHERE:
+ volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius;
+ break;
+
+ /* for now, assume that capsule is close enough to a cylinder... */
+ case RB_SHAPE_CAPSULE:
+ case RB_SHAPE_CYLINDER:
+ volume = (float)M_PI * radius * radius * height;
+ break;
+
+ case RB_SHAPE_CONE:
+ volume = (float)M_PI / 3.0f * radius * radius * height;
+ break;
+
+ case RB_SHAPE_CONVEXH:
+ case RB_SHAPE_TRIMESH:
+ {
+ if (ob->type == OB_MESH) {
+ DerivedMesh *dm = rigidbody_get_mesh(ob);
+ MVert *mvert;
+ MFace *mface;
+ int totvert, totface;
+
+ /* ensure mesh validity, then grab data */
+ if (dm == NULL)
+ return;
+
+ DM_ensure_tessface(dm);
+
+ mvert = dm->getVertArray(dm);
+ totvert = dm->getNumVerts(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
+
+ if (totvert > 0 && totface > 0) {
+ BKE_mesh_calc_volume(mvert, totvert, mface, totface, &volume, NULL);
+ }
+
+ /* cleanup temp data */
+ if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
+ dm->release(dm);
+ }
+ }
+ else {
+ /* rough estimate from boundbox as fallback */
+ /* XXX could implement other types of geometry here (curves, etc.) */
+ volume = size[0] * size[1] * size[2];
+ }
+ break;
+ }
+
+#if 0 // XXX: not defined yet
+ case RB_SHAPE_COMPOUND:
+ volume = 0.0f;
+ break;
+#endif
+ }
+
+ /* return the volume calculated */
+ if (r_vol) *r_vol = volume;
+}
+
+void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3])
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ float size[3] = {1.0f, 1.0f, 1.0f};
+ float height = 1.0f;
+
+ zero_v3(r_com);
+
+ /* if automatically determining dimensions, use the Object's boundbox
+ * - assume that all quadrics are standing upright on local z-axis
+ * - assume even distribution of mass around the Object's pivot
+ * (i.e. Object pivot is centralized in boundbox)
+ * - boundbox gives full width
+ */
+ // XXX: all dimensions are auto-determined now... later can add stored settings for this
+ BKE_object_dimensions_get(ob, size);
+
+ /* calculate volume as appropriate */
+ switch (rbo->shape) {
+ case RB_SHAPE_BOX:
+ case RB_SHAPE_SPHERE:
+ case RB_SHAPE_CAPSULE:
+ case RB_SHAPE_CYLINDER:
+ break;
+
+ case RB_SHAPE_CONE:
+ /* take radius as largest x/y dimension, and height as z-dimension */
+ height = size[2];
+ /* cone is geometrically centered on the median,
+ * center of mass is 1/4 up from the base
+ */
+ r_com[2] = -0.25f * height;
+ break;
+
+ case RB_SHAPE_CONVEXH:
+ case RB_SHAPE_TRIMESH:
+ {
+ if (ob->type == OB_MESH) {
+ DerivedMesh *dm = rigidbody_get_mesh(ob);
+ MVert *mvert;
+ MFace *mface;
+ int totvert, totface;
+
+ /* ensure mesh validity, then grab data */
+ if (dm == NULL)
+ return;
+
+ DM_ensure_tessface(dm);
+
+ mvert = dm->getVertArray(dm);
+ totvert = dm->getNumVerts(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
+
+ if (totvert > 0 && totface > 0) {
+ BKE_mesh_calc_volume(mvert, totvert, mface, totface, NULL, r_com);
+ }
+
+ /* cleanup temp data */
+ if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
+ dm->release(dm);
+ }
+ }
+ break;
+ }
+
+#if 0 // XXX: not defined yet
+ case RB_SHAPE_COMPOUND:
+ volume = 0.0f;
+ break;
+#endif
+ }
+}
+
+/* --------------------- */
+
/**
* Create physics sim representation of object given RigidBody settings
*
@@ -543,7 +720,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
return;
}
- if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
+ if (ELEM(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
if (rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
RB_constraint_delete(rbc->physics_constraint);
@@ -1414,6 +1591,8 @@ struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; }
struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; }
void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc) {}
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {}
+void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) { if (r_vol) *r_vol = 0.0f; }
+void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3]) { zero_v3(r_com); }
struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; }
struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; }
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {}
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 1310162483e..4be75344133 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -392,6 +392,7 @@ void init_actuator(bActuator *act)
bSteeringActuator *sta;
bArmatureActuator *arma;
bMouseActuator *ma;
+ bEditObjectActuator *eoa;
if (act->data) MEM_freeN(act->data);
act->data= NULL;
@@ -430,6 +431,9 @@ void init_actuator(bActuator *act)
break;
case ACT_EDIT_OBJECT:
act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact");
+ eoa = act->data;
+ eoa->upflag= ACT_TRACK_UP_Z;
+ eoa->trackflag= ACT_TRACK_TRAXIS_Y;
break;
case ACT_CONSTRAINT:
act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act");
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index f8ce31f1b8a..eb98e381222 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -39,6 +39,7 @@
#include "DNA_anim_types.h"
#include "DNA_group_types.h"
#include "DNA_linestyle_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
@@ -46,6 +47,8 @@
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -62,6 +65,7 @@
#include "BKE_action.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
+#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
#include "BKE_freestyle.h"
#include "BKE_global.h"
@@ -78,6 +82,7 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
+#include "BKE_unit.h"
#include "BKE_world.h"
#include "RE_engine.h"
@@ -86,6 +91,8 @@
#include "IMB_colormanagement.h"
+#include "bmesh.h"
+
//XXX #include "BIF_previewrender.h"
//XXX #include "BIF_editseq.h"
@@ -253,6 +260,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint);
ts->imapaint.paintcursor = NULL;
+ id_us_plus((ID *)ts->imapaint.stencil);
ts->particle.paintcursor = NULL;
}
@@ -510,6 +518,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->r.border.ymin = 0.0f;
sce->r.border.xmax = 1.0f;
sce->r.border.ymax = 1.0f;
+
+ sce->r.preview_start_resolution = 64;
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct");
sce->toolsettings->doublimit = 0.001;
@@ -553,6 +563,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->toolsettings->proportional_size = 1.0f;
sce->toolsettings->imapaint.paint.flags |= PAINT_SHOW_BRUSH;
+ sce->toolsettings->imapaint.normal_angle = 80;
+ sce->toolsettings->imapaint.seam_bleed = 2;
sce->physics_settings.gravity[0] = 0.0f;
sce->physics_settings.gravity[1] = 0.0f;
@@ -719,14 +731,14 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
/* called from creator.c */
Scene *BKE_scene_set_name(Main *bmain, const char *name)
{
- Scene *sce = (Scene *)BKE_libblock_find_name(ID_SCE, name);
+ Scene *sce = (Scene *)BKE_libblock_find_name_ex(bmain, ID_SCE, name);
if (sce) {
BKE_scene_set_background(bmain, sce);
- printf("Scene switch: '%s' in file: '%s'\n", name, G.main->name);
+ printf("Scene switch: '%s' in file: '%s'\n", name, bmain->name);
return sce;
}
- printf("Can't find scene: '%s' in file: '%s'\n", name, G.main->name);
+ printf("Can't find scene: '%s' in file: '%s'\n", name, bmain->name);
return NULL;
}
@@ -804,9 +816,7 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
BKE_libblock_free(bmain, sce);
}
-/* used by metaballs
- * doesn't return the original duplicated object, only dupli's
- */
+/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
Scene **scene, int val, Base **base, Object **ob)
{
@@ -817,11 +827,12 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
iter->phase = F_START;
iter->dupob = NULL;
iter->duplilist = NULL;
+ iter->dupli_refob = NULL;
}
else {
/* run_again is set when a duplilist has been ended */
while (run_again) {
- run_again = 0;
+ run_again = false;
/* the first base */
if (iter->phase == F_START) {
@@ -879,34 +890,46 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
iter->dupob = iter->duplilist->first;
- if (!iter->dupob)
+ if (!iter->dupob) {
free_object_duplilist(iter->duplilist);
+ iter->duplilist = NULL;
+ }
+ iter->dupli_refob = NULL;
}
}
}
/* handle dupli's */
if (iter->dupob) {
-
- copy_m4_m4(iter->omat, iter->dupob->ob->obmat);
- copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->mat);
-
(*base)->flag |= OB_FROMDUPLI;
*ob = iter->dupob->ob;
iter->phase = F_DUPLI;
-
+
+ if (iter->dupli_refob != *ob) {
+ if (iter->dupli_refob) {
+ /* Restore previous object's real matrix. */
+ copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
+ }
+ /* Backup new object's real matrix. */
+ iter->dupli_refob = *ob;
+ copy_m4_m4(iter->omat, iter->dupli_refob->obmat);
+ }
+ copy_m4_m4((*ob)->obmat, iter->dupob->mat);
+
iter->dupob = iter->dupob->next;
}
else if (iter->phase == F_DUPLI) {
iter->phase = F_SCENE;
(*base)->flag &= ~OB_FROMDUPLI;
- for (iter->dupob = iter->duplilist->first; iter->dupob; iter->dupob = iter->dupob->next) {
- copy_m4_m4(iter->dupob->ob->obmat, iter->omat);
+ if (iter->dupli_refob) {
+ /* Restore last object's real matrix. */
+ copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
+ iter->dupli_refob = NULL;
}
free_object_duplilist(iter->duplilist);
iter->duplilist = NULL;
- run_again = 1;
+ run_again = true;
}
}
}
@@ -1118,11 +1141,6 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra)
double intpart;
scene->r.subframe = modf(cfra, &intpart);
scene->r.cfra = (int)intpart;
-
- if (cfra < 0.0) {
- scene->r.cfra -= 1;
- scene->r.subframe = 1.0f + scene->r.subframe;
- }
}
/* drivers support/hacks
@@ -1541,6 +1559,53 @@ static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bma
}
+static bool check_rendered_viewport_visible(Main *bmain)
+{
+ wmWindowManager *wm = bmain->wm.first;
+ wmWindow *window;
+ for (window = wm->windows.first; window != NULL; window = window->next) {
+ bScreen *screen = window->screen;
+ ScrArea *area;
+ for (area = screen->areabase.first; area != NULL; area = area->next) {
+ View3D *v3d = area->spacedata.first;
+ if (area->spacetype != SPACE_VIEW3D) {
+ continue;
+ }
+ if (v3d->drawtype == OB_RENDER) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
+{
+ /* This is needed to prepare mesh to be used by the render
+ * engine from the viewport rendering. We do loading here
+ * so all the objects which shares the same mesh datablock
+ * are nicely tagged for update and updated.
+ *
+ * This makes it so viewport render engine doesn't need to
+ * call loading of the edit data for the mesh objects.
+ */
+
+ Object *obedit = scene->obedit;
+ if (obedit) {
+ Mesh *mesh = obedit->data;
+ /* TODO(sergey): Check object recalc flags as well? */
+ if ((obedit->type == OB_MESH) &&
+ (mesh->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)))
+ {
+ if (check_rendered_viewport_visible(bmain)) {
+ BMesh *bm = mesh->edit_btmesh->bm;
+ BM_mesh_bm_to_me(bm, mesh, false);
+ DAG_id_tag_update(&mesh->id, 0);
+ }
+ }
+ }
+}
+
void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
{
Scene *sce_iter;
@@ -1552,6 +1617,9 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
DAG_scene_relations_update(bmain, sce_iter);
+ /* flush editing data if needed */
+ prepare_mesh_for_viewport_render(bmain, scene);
+
/* flush recalc flags to dependencies */
DAG_ids_flush_tagged(bmain);
@@ -1832,6 +1900,12 @@ bool BKE_scene_use_new_shading_nodes(Scene *scene)
return (type && type->flag & RE_USE_SHADING_NODES);
}
+bool BKE_scene_uses_blender_internal(struct Scene *scene)
+{
+ return strcmp("BLENDER_RENDER", scene->r.engine) == 0;
+}
+
+
void BKE_scene_base_flag_to_objects(struct Scene *scene)
{
Base *base = scene->base.first;
@@ -1903,3 +1977,29 @@ int BKE_scene_num_threads(const Scene *scene)
{
return BKE_render_num_threads(&scene->r);
}
+
+/* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently)
+ * and unit->scale_length.
+ */
+double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, double value)
+{
+ if (unit->system == USER_UNIT_NONE) {
+ /* Never apply scale_length when not using a unit setting! */
+ return value;
+ }
+
+ switch (unit_type) {
+ case B_UNIT_LENGTH:
+ return value * (double)unit->scale_length;
+ case B_UNIT_CAMERA:
+ return value * (double)unit->scale_length;
+ case B_UNIT_AREA:
+ return value * pow(unit->scale_length, 2);
+ case B_UNIT_VOLUME:
+ return value * pow(unit->scale_length, 3);
+ case B_UNIT_MASS:
+ return value * pow(unit->scale_length, 3);
+ default:
+ return value;
+ }
+}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 9d40ee6e667..b2296151cf7 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -425,6 +425,32 @@ ScrArea *BKE_screen_find_big_area(bScreen *sc, const int spacetype, const short
return big;
}
+/**
+ * Utility function to get the active layer to use when adding new objects.
+ */
+unsigned int BKE_screen_view3d_layer_active_ex(const View3D *v3d, const Scene *scene, bool use_localvd)
+{
+ unsigned int lay;
+ if ((v3d == NULL) || (v3d->scenelock && !v3d->localvd)) {
+ lay = scene->layact;
+ }
+ else {
+ lay = v3d->layact;
+ }
+
+ if (use_localvd) {
+ if (v3d && v3d->localvd) {
+ lay |= v3d->lay;
+ }
+ }
+
+ return lay;
+}
+unsigned int BKE_screen_view3d_layer_active(const struct View3D *v3d, const struct Scene *scene)
+{
+ return BKE_screen_view3d_layer_active_ex(v3d, scene, true);
+}
+
void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene)
{
int bit;
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 2b14b92217b..d2dc9da47f9 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -52,6 +52,11 @@
#include "RNA_access.h"
+/* TODO(sergey): Could be considered a bad level call, but
+ * need this for gaussian table.
+ */
+#include "RE_pipeline.h"
+
static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1,
unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out)
@@ -2579,6 +2584,295 @@ static void do_overdrop_effect(const SeqRenderData *context, Sequence *UNUSED(se
}
}
+/*********************** Gaussian Blur *************************/
+
+/* NOTE: This gaussian blur implementation accumulates values in the square
+ * kernel rather that doing X direction and then Y direction because of the
+ * lack of using multiple-staged filters.
+ *
+ * Once we can we'll implement a way to apply filter as multiple stages we
+ * can optimize hell of a lot in here.
+ */
+
+static void init_gaussian_blur_effect(Sequence *seq)
+{
+ if (seq->effectdata)
+ MEM_freeN(seq->effectdata);
+
+ seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
+}
+
+static int num_inputs_gaussian_blur(void)
+{
+ return 1;
+}
+
+static void free_gaussian_blur_effect(Sequence *seq)
+{
+ if (seq->effectdata)
+ MEM_freeN(seq->effectdata);
+
+ seq->effectdata = NULL;
+}
+
+static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src)
+{
+ dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
+{
+ GaussianBlurVars *data = seq->effectdata;
+ if (data->size_x == 0.0f && data->size_y == 0) {
+ return EARLY_USE_INPUT_1;
+ }
+ return EARLY_DO_EFFECT;
+}
+
+/* TODO(sergey): De-duplicate with compositor. */
+static float *make_gaussian_blur_kernel(float rad, int size)
+{
+ float *gausstab, sum, val;
+ float fac;
+ int i, n;
+
+ n = 2 * size + 1;
+
+ gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__);
+
+ sum = 0.0f;
+ fac = (rad > 0.0f ? 1.0f / rad : 0.0f);
+ for (i = -size; i <= size; i++) {
+ val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac);
+ sum += val;
+ gausstab[i + size] = val;
+ }
+
+ sum = 1.0f / sum;
+ for (i = 0; i < n; i++)
+ gausstab[i] *= sum;
+
+ return gausstab;
+}
+
+static void do_gaussian_blur_effect_byte(Sequence *seq,
+ int start_line,
+ int x, int y,
+ int frame_width, int frame_height,
+ unsigned char *rect,
+ unsigned char *out)
+{
+#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
+ GaussianBlurVars *data = seq->effectdata;
+ const int size_x = (int) (data->size_x + 0.5f),
+ size_y = (int) (data->size_y + 0.5f);
+ int i, j;
+
+ /* Make gaussian weight tabke. */
+ float *gausstab_x, *gausstab_y;
+ gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
+ if (data->size_x == data->size_y) {
+ gausstab_y = gausstab_x;
+ }
+ else {
+ gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
+ }
+
+ for (i = 0; i < y; ++i) {
+ for (j = 0; j < x; ++j) {
+ int out_index = INDEX(j, i);
+ int current_x, current_y;
+ float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float accum_weight = 0.0f;
+ for (current_y = i - size_y;
+ current_y <= i + size_y;
+ ++current_y)
+ {
+ if (current_y < -start_line ||
+ current_y + start_line >= frame_height)
+ {
+ /* Out of bounds. */
+ continue;
+ }
+
+ for (current_x = j - size_x;
+ current_x <= j + size_x;
+ ++current_x)
+ {
+ float weight;
+ int index = INDEX(current_x, current_y + start_line);
+ if (current_x < 0 || current_x >= frame_width) {
+ /* Out of bounds. */
+ continue;
+ }
+ BLI_assert(index >= 0);
+ BLI_assert(index < frame_width * frame_height * 4);
+
+ if (size_x != 0 && size_y != 0) {
+ weight = gausstab_x[current_x - j + size_x] *
+ gausstab_y[current_y - i + size_y];
+ }
+ else if (size_x == 0) {
+ weight = gausstab_y[current_y - i + size_y];
+ }
+ else {
+ weight = gausstab_x[current_x - j + size_x];
+ }
+ accum[0] += rect[index] * weight;
+ accum[1] += rect[index + 1] * weight;
+ accum[2] += rect[index + 2] * weight;
+ accum[3] += rect[index + 3] * weight;
+ accum_weight += weight;
+ }
+ }
+ out[out_index + 0] = accum[0] / accum_weight;
+ out[out_index + 1] = accum[1] / accum_weight;
+ out[out_index + 2] = accum[2] / accum_weight;
+ out[out_index + 3] = accum[3] / accum_weight;
+ }
+ }
+
+ MEM_freeN(gausstab_x);
+ if (gausstab_x != gausstab_y) {
+ MEM_freeN(gausstab_y);
+ }
+#undef INDEX
+}
+
+static void do_gaussian_blur_effect_float(Sequence *seq,
+ int start_line,
+ int x, int y,
+ int frame_width, int frame_height,
+ float *rect,
+ float *out)
+{
+#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
+ GaussianBlurVars *data = seq->effectdata;
+ const int size_x = (int) (data->size_x + 0.5f),
+ size_y = (int) (data->size_y + 0.5f);
+ int i, j;
+
+ /* Make gaussian weight tabke. */
+ float *gausstab_x, *gausstab_y;
+ gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
+ if (data->size_x == data->size_y) {
+ gausstab_y = gausstab_x;
+ }
+ else {
+ gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
+ }
+
+ for (i = 0; i < y; ++i) {
+ for (j = 0; j < x; ++j) {
+ int out_index = INDEX(j, i);
+ int current_x, current_y;
+ float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float accum_weight = 0.0f;
+ for (current_y = i - size_y;
+ current_y <= i + size_y;
+ ++current_y)
+ {
+ float weight;
+ if (current_y < -start_line ||
+ current_y + start_line >= frame_height)
+ {
+ /* Out of bounds. */
+ continue;
+ }
+
+ for (current_x = j - size_x;
+ current_x <= j + size_x;
+ ++current_x)
+ {
+ int index = INDEX(current_x, current_y + start_line);
+ if (current_x < 0 || current_x >= frame_width) {
+ /* Out of bounds. */
+ continue;
+ }
+
+ if (size_x != 0 && size_y != 0) {
+ weight = gausstab_x[current_x - j + size_x] *
+ gausstab_y[current_y - i + size_y];
+ }
+ else if (size_x == 0) {
+ weight = gausstab_y[current_y - i + size_y];
+ }
+ else {
+ weight = gausstab_x[current_x - j + size_x];
+ }
+ madd_v4_v4fl(accum, &rect[index], weight);
+ accum_weight += weight;
+ }
+ }
+ mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight);
+ }
+ }
+
+ MEM_freeN(gausstab_x);
+ if (gausstab_x != gausstab_y) {
+ MEM_freeN(gausstab_y);
+ }
+#undef INDEX
+}
+
+static void do_gaussian_blur_effect(const SeqRenderData *context,
+ Sequence *seq,
+ float UNUSED(cfra),
+ float UNUSED(facf0),
+ float UNUSED(facf1),
+ ImBuf *ibuf1,
+ ImBuf *ibuf2,
+ ImBuf *UNUSED(ibuf3),
+ int start_line,
+ int total_lines,
+ ImBuf *out)
+{
+ if (out->rect_float) {
+ float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+
+ slice_get_float_buffers(context,
+ ibuf1, ibuf2,
+ NULL,
+ out,
+ start_line,
+ &rect1,
+ &rect2,
+ NULL,
+ &rect_out);
+
+ do_gaussian_blur_effect_float(seq,
+ start_line,
+ context->rectx,
+ total_lines,
+ context->rectx,
+ context->recty,
+ ibuf1->rect_float,
+ rect_out);
+ }
+ else {
+ unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+
+ slice_get_byte_buffers(context,
+ ibuf1, ibuf2,
+ NULL,
+ out,
+ start_line,
+ &rect1,
+ &rect2,
+ NULL,
+ &rect_out);
+
+ do_gaussian_blur_effect_byte(seq,
+ start_line,
+ context->rectx,
+ total_lines,
+ context->rectx,
+ context->recty,
+ (unsigned char *) ibuf1->rect,
+ rect_out);
+ }
+}
+
/*********************** sequence effect factory *************************/
static void init_noop(Sequence *UNUSED(seq))
@@ -2767,6 +3061,15 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.early_out = early_out_adjustment;
rval.execute = do_adjustment;
break;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ rval.multithreaded = true;
+ rval.init = init_gaussian_blur_effect;
+ rval.num_inputs = num_inputs_gaussian_blur;
+ rval.free = free_gaussian_blur_effect;
+ rval.copy = copy_gaussian_blur_effect;
+ rval.early_out = early_out_gaussian_blur;
+ rval.execute_slice = do_gaussian_blur_effect;
+ break;
}
return rval;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index f5efe04951f..c9647b05ce7 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -758,7 +758,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r
int prev_startdisp = 0, prev_enddisp = 0;
/* note: don't rename the strip, will break animation curves */
- if (ELEM7(seq->type,
+ if (ELEM(seq->type,
SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM,
SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) == 0)
{
@@ -994,28 +994,29 @@ void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq)
static const char *give_seqname_by_type(int type)
{
switch (type) {
- case SEQ_TYPE_META: return "Meta";
- case SEQ_TYPE_IMAGE: return "Image";
- case SEQ_TYPE_SCENE: return "Scene";
- case SEQ_TYPE_MOVIE: return "Movie";
- case SEQ_TYPE_MOVIECLIP: return "Clip";
- case SEQ_TYPE_MASK: return "Mask";
- case SEQ_TYPE_SOUND_RAM: return "Audio";
- case SEQ_TYPE_CROSS: return "Cross";
- case SEQ_TYPE_GAMCROSS: return "Gamma Cross";
- case SEQ_TYPE_ADD: return "Add";
- case SEQ_TYPE_SUB: return "Sub";
- case SEQ_TYPE_MUL: return "Mul";
- case SEQ_TYPE_ALPHAOVER: return "Alpha Over";
- case SEQ_TYPE_ALPHAUNDER: return "Alpha Under";
- case SEQ_TYPE_OVERDROP: return "Over Drop";
- case SEQ_TYPE_WIPE: return "Wipe";
- case SEQ_TYPE_GLOW: return "Glow";
- case SEQ_TYPE_TRANSFORM: return "Transform";
- case SEQ_TYPE_COLOR: return "Color";
- case SEQ_TYPE_MULTICAM: return "Multicam";
- case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
- case SEQ_TYPE_SPEED: return "Speed";
+ case SEQ_TYPE_META: return "Meta";
+ case SEQ_TYPE_IMAGE: return "Image";
+ case SEQ_TYPE_SCENE: return "Scene";
+ case SEQ_TYPE_MOVIE: return "Movie";
+ case SEQ_TYPE_MOVIECLIP: return "Clip";
+ case SEQ_TYPE_MASK: return "Mask";
+ case SEQ_TYPE_SOUND_RAM: return "Audio";
+ case SEQ_TYPE_CROSS: return "Cross";
+ case SEQ_TYPE_GAMCROSS: return "Gamma Cross";
+ case SEQ_TYPE_ADD: return "Add";
+ case SEQ_TYPE_SUB: return "Sub";
+ case SEQ_TYPE_MUL: return "Mul";
+ case SEQ_TYPE_ALPHAOVER: return "Alpha Over";
+ case SEQ_TYPE_ALPHAUNDER: return "Alpha Under";
+ case SEQ_TYPE_OVERDROP: return "Over Drop";
+ case SEQ_TYPE_WIPE: return "Wipe";
+ case SEQ_TYPE_GLOW: return "Glow";
+ case SEQ_TYPE_TRANSFORM: return "Transform";
+ case SEQ_TYPE_COLOR: return "Color";
+ case SEQ_TYPE_MULTICAM: return "Multicam";
+ case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
+ case SEQ_TYPE_SPEED: return "Speed";
+ case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur";
default:
return NULL;
}
@@ -2224,7 +2225,7 @@ static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, con
init_data.out = out;
IMB_processor_apply_threaded(out->y, sizeof(RenderEffectThread), &init_data,
- render_effect_execute_init_handle, render_effect_execute_do_thread);
+ render_effect_execute_init_handle, render_effect_execute_do_thread);
return out;
}
@@ -2808,7 +2809,7 @@ static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, floa
float nr = give_stripelem_index(seq, cfra);
/* all effects are handled similarly with the exception of speed effect */
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
- bool is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
+ bool is_preprocessed = !ELEM(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
@@ -2875,7 +2876,7 @@ static bool seq_must_swap_input_in_blend_mode(Sequence *seq)
/* bad hack, to fix crazy input ordering of
* those two effects */
- if (ELEM3(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) {
+ if (ELEM(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) {
swap_input = true;
}
@@ -2960,7 +2961,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq
/* Some of the blend modes are unclear how to apply with only single input,
* or some of them will just produce an empty result..
*/
- if (ELEM3(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) {
+ if (ELEM(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) {
int early_out;
if (seq->blend_mode == SEQ_BLEND_REPLACE) {
early_out = EARLY_NO_INPUT;
@@ -3512,16 +3513,28 @@ bool BKE_sequence_single_check(Sequence *seq)
}
/* check if the selected seq's reference unselected seq's */
-bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase)
+bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase, bool one_only)
{
Sequence *seq;
- /* is there more than 1 select */
+ /* is there a valid selection select */
bool ok = false;
+ /* is there one selected already? */
+ bool first = false;
for (seq = seqbase->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
- ok = true;
- break;
+ if (one_only) {
+ ok = true;
+ break;
+ }
+ else {
+ if (first) {
+ ok = true;
+ break;
+ }
+ else
+ first = true;
+ }
}
}
@@ -3688,7 +3701,7 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame)
if (seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
continue;
/* only use elements you can see - not */
- if (ELEM5(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) {
+ if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) {
if (seq->machine > best_machine) {
best_seq = seq;
best_machine = seq->machine;
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index e2cc7b84f95..d2a4d15a2c6 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -50,6 +50,7 @@
#include "BKE_lattice.h"
#include "BKE_deform.h"
+#include "BKE_mesh.h" /* for OMP limits. */
#include "BKE_subsurf.h"
#include "BKE_editmesh.h"
@@ -65,57 +66,6 @@
/* Util macros */
#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
-/* get derived mesh */
-/* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */
-DerivedMesh *object_get_derived_final(Object *ob, bool for_render)
-{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
-
- if (for_render) {
- /* TODO(sergey): use proper derived render here in the future. */
- return ob->derivedFinal;
- }
-
- if (em) {
- DerivedMesh *dm = em->derivedFinal;
- return dm;
- }
-
- return ob->derivedFinal;
-}
-
-/* Space transform */
-void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float target[4][4])
-{
- float itarget[4][4];
- invert_m4_m4(itarget, target);
- mul_m4_m4m4(data->local2target, itarget, local);
- invert_m4_m4(data->target2local, data->local2target);
-}
-
-void space_transform_apply(const SpaceTransform *data, float co[3])
-{
- mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co);
-}
-
-void space_transform_invert(const SpaceTransform *data, float co[3])
-{
- mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co);
-}
-
-static void space_transform_apply_normal(const SpaceTransform *data, float no[3])
-{
- mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no);
- normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */
-}
-
-static void space_transform_invert_normal(const SpaceTransform *data, float no[3])
-{
- mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no);
- normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */
-}
-
/*
* Shrinkwrap to the nearest vertex
*
@@ -135,12 +85,12 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
OUT_OF_MEMORY();
return;
}
-
+
/* Setup nearest */
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static)
+#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -158,7 +108,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
else {
copy_v3_v3(tmp_co, co);
}
- space_transform_apply(&calc->local2target, tmp_co);
+ BLI_space_transform_apply(&calc->local2target, tmp_co);
/* Use local proximity heuristics (to reduce the nearest search)
*
@@ -184,7 +134,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
/* Convert the coordinates back to mesh coordinates */
copy_v3_v3(tmp_co, nearest.co);
- space_transform_invert(&calc->local2target, tmp_co);
+ BLI_space_transform_invert(&calc->local2target, tmp_co);
interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
}
@@ -223,11 +173,11 @@ bool BKE_shrinkwrap_project_normal(
/* Apply space transform (TODO readjust dist) */
if (transf) {
copy_v3_v3(tmp_co, vert);
- space_transform_apply(transf, tmp_co);
+ BLI_space_transform_apply(transf, tmp_co);
co = tmp_co;
copy_v3_v3(tmp_no, dir);
- space_transform_apply_normal(transf, tmp_no);
+ BLI_space_transform_apply_normal(transf, tmp_no);
no = tmp_no;
#ifdef USE_DIST_CORRECT
@@ -246,7 +196,7 @@ bool BKE_shrinkwrap_project_normal(
if (hit_tmp.index != -1) {
/* invert the normal first so face culling works on rotated objects */
if (transf) {
- space_transform_invert_normal(transf, hit_tmp.no);
+ BLI_space_transform_invert_normal(transf, hit_tmp.no);
}
if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) {
@@ -261,7 +211,7 @@ bool BKE_shrinkwrap_project_normal(
if (transf) {
/* Inverting space transform (TODO make coeherent with the initial dist readjust) */
- space_transform_invert(transf, hit_tmp.co);
+ BLI_space_transform_invert(transf, hit_tmp.co);
#ifdef USE_DIST_CORRECT
hit_tmp.dist = len_v3v3(vert, hit_tmp.co);
#endif
@@ -326,7 +276,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
auxMesh = object_get_derived_final(calc->smd->auxTarget, for_render);
if (!auxMesh)
return;
- SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
+ BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
}
/* After sucessufuly build the trees, start projection vertexs */
@@ -335,7 +285,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
{
#ifndef __APPLE__
-#pragma omp parallel for private(i, hit) schedule(static)
+#pragma omp parallel for private(i, hit) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -445,7 +395,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
/* Find the nearest vertex */
#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static)
+#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -460,7 +410,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
else {
copy_v3_v3(tmp_co, co);
}
- space_transform_apply(&calc->local2target, tmp_co);
+ BLI_space_transform_apply(&calc->local2target, tmp_co);
/* Use local proximity heuristics (to reduce the nearest search)
*
@@ -494,7 +444,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
}
/* Convert the coordinates back to mesh coordinates */
- space_transform_invert(&calc->local2target, tmp_co);
+ BLI_space_transform_invert(&calc->local2target, tmp_co);
interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
}
}
@@ -537,7 +487,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
/* TODO there might be several "bugs" on non-uniform scales matrixs
* because it will no longer be nearest surface, not sphere projection
* because space has been deformed */
- SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target);
+ BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target);
/* TODO: smd->keepDist is in global units.. must change to local */
calc.keepDist = smd->keepDist;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 12a19381e9d..0bd9517dcfd 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -41,6 +41,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -2290,18 +2291,23 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
DMSetDrawOptions drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ MTFace *tf_stencil_base = NULL;
+ MTFace *tf_stencil = NULL;
+ MTFace *tf_base;
short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
DMFlagMat *faceFlags = ccgdm->faceFlags;
DMDrawOption draw_option;
int i, totface, gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
+ int gridOffset = 0;
+ int mat_nr_cache = -1;
(void) compareDrawOptions;
@@ -2315,6 +2321,12 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
totface = ccgSubSurf_getNumFaces(ss);
+
+ if (flag & DM_DRAW_USE_TEXPAINT_UV) {
+ int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ }
+
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -2333,6 +2345,18 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mat_nr = 0;
}
+ /* texture painting, handle the correct uv layer here */
+ if (flag & DM_DRAW_USE_TEXPAINT_UV) {
+ if (mat_nr != mat_nr_cache) {
+ tf_base = DM_paint_uvlayer_active_get(dm, mat_nr);
+
+ mat_nr_cache = mat_nr;
+ }
+ tf = tf_base + gridOffset;
+ tf_stencil = tf_stencil_base + gridOffset;
+ gridOffset += gridFaces * gridFaces * numVerts;
+ }
+
if (drawParams)
draw_option = drawParams(tf, (mcol != NULL), mat_nr);
else if (index != ORIGINDEX_NONE)
@@ -2373,26 +2397,31 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glNormal3sv(ln[0][1]);
glVertex3fv(d_co);
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glNormal3sv(ln[0][2]);
glVertex3fv(c_co);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glNormal3sv(ln[0][3]);
glVertex3fv(b_co);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glNormal3sv(ln[0][0]);
glVertex3fv(a_co);
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
ln++;
}
@@ -2408,17 +2437,20 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
if (x != gridFaces - 1) {
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
}
}
@@ -2427,16 +2459,19 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
glEnd();
@@ -2455,22 +2490,27 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glVertex3fv(d_co);
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glVertex3fv(c_co);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glVertex3fv(b_co);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(a_co);
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
}
}
@@ -2483,17 +2523,17 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
static void ccgDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
+ ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
}
static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
+ ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
static void ccgDM_drawUVEdges(DerivedMesh *dm)
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 90687ef9916..4cd85fb342e 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -1286,6 +1286,19 @@ void txt_sel_all(Text *text)
text->selc = text->sell->len;
}
+/**
+ * Reverse of #txt_pop_sel
+ * Clears the selection and ensures the cursor is located
+ * at the selection (where the cursor is visually while editing).
+ */
+void txt_sel_clear(Text *text)
+{
+ if (text->sell) {
+ text->curl = text->sell;
+ text->curc = text->selc;
+ }
+}
+
void txt_sel_line(Text *text)
{
if (!text) return;
@@ -2697,7 +2710,7 @@ void txt_indent(Text *text)
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
- if (ELEM3(NULL, text, text->curl, text->sell)) {
+ if (ELEM(NULL, text, text->curl, text->sell)) {
return;
}
@@ -2764,7 +2777,7 @@ void txt_unindent(Text *text)
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
- if (ELEM3(NULL, text, text->curl, text->sell)) {
+ if (ELEM(NULL, text, text->curl, text->sell)) {
return;
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index bb956cb085c..b1981a3a804 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -41,6 +41,7 @@
#include "BLI_math.h"
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
+#include "BLI_math_color.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
@@ -145,12 +146,12 @@ void init_tex_mapping(TexMapping *texmap)
if (texmap->type == TEXMAP_TYPE_TEXTURE) {
/* to transform a texture, the inverse transform needs
* to be applied to the texture coordinate */
- mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
+ mul_m4_series(texmap->mat, tmat, rmat, smat);
invert_m4(texmap->mat);
}
else if (texmap->type == TEXMAP_TYPE_POINT) {
/* forward transform */
- mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
+ mul_m4_series(texmap->mat, tmat, rmat, smat);
}
else if (texmap->type == TEXMAP_TYPE_VECTOR) {
/* no translation for vectors */
@@ -237,7 +238,7 @@ void init_colorband(ColorBand *coba, bool rangetype)
}
coba->tot = 2;
-
+ coba->color_mode = COLBAND_BLEND_RGB;
}
ColorBand *add_colorband(bool rangetype)
@@ -252,106 +253,209 @@ ColorBand *add_colorband(bool rangetype)
/* ------------------------------------------------------------------------- */
+static float colorband_hue_interp(
+ const int ipotype_hue,
+ const float mfac, const float fac,
+ float h1, float h2)
+{
+ float h_interp;
+ int mode = 0;
+
+#define HUE_INTERP(h_a, h_b) ((mfac * (h_a)) + (fac * (h_b)))
+#define HUE_MOD(h) (((h) < 1.0f) ? (h) : (h) - 1.0f)
+
+ h1 = HUE_MOD(h1);
+ h2 = HUE_MOD(h2);
+
+ BLI_assert(h1 >= 0.0f && h1 < 1.0f);
+ BLI_assert(h2 >= 0.0f && h2 < 1.0f);
+
+ switch (ipotype_hue) {
+ case COLBAND_HUE_NEAR:
+ {
+ if ((h1 < h2) && (h2 - h1) > +0.5f) mode = 1;
+ else if ((h1 > h2) && (h2 - h1) < -0.5f) mode = 2;
+ else mode = 0;
+ break;
+ }
+ case COLBAND_HUE_FAR:
+ {
+ if ((h1 < h2) && (h2 - h1) < +0.5f) mode = 1;
+ else if ((h1 > h2) && (h2 - h1) > -0.5f) mode = 2;
+ else mode = 0;
+ break;
+ }
+ case COLBAND_HUE_CCW:
+ {
+ if (h1 > h2) mode = 2;
+ else mode = 0;
+ break;
+ }
+ case COLBAND_HUE_CW:
+ {
+ if (h1 < h2) mode = 1;
+ else mode = 0;
+ break;
+ }
+ }
+
+ switch (mode) {
+ case 0:
+ h_interp = HUE_INTERP(h1, h2);
+ break;
+ case 1:
+ h_interp = HUE_INTERP(h1 + 1.0f, h2);
+ h_interp = HUE_MOD(h_interp);
+ break;
+ case 2:
+ h_interp = HUE_INTERP(h1, h2 + 1.0f);
+ h_interp = HUE_MOD(h_interp);
+ break;
+ }
+
+ BLI_assert(h_interp >= 0.0f && h_interp < 1.0f);
+
+#undef HUE_INTERP
+#undef HUE_MOD
+
+ return h_interp;
+}
+
bool do_colorband(const ColorBand *coba, float in, float out[4])
{
const CBData *cbd1, *cbd2, *cbd0, *cbd3;
- float fac, mfac, t[4];
+ float fac;
+ int ipotype;
int a;
if (coba == NULL || coba->tot == 0) return 0;
cbd1 = coba->data;
+
+ ipotype = (coba->color_mode == COLBAND_BLEND_RGB) ? coba->ipotype : COLBAND_INTERP_LINEAR;
+
if (coba->tot == 1) {
out[0] = cbd1->r;
out[1] = cbd1->g;
out[2] = cbd1->b;
out[3] = cbd1->a;
}
+ else if ((in <= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) {
+ out[0] = cbd1->r;
+ out[1] = cbd1->g;
+ out[2] = cbd1->b;
+ out[3] = cbd1->a;
+ }
else {
- if (in <= cbd1->pos && coba->ipotype < 2) {
+ CBData left, right;
+
+ /* we're looking for first pos > in */
+ for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break;
+
+ if (a == coba->tot) {
+ cbd2 = cbd1 - 1;
+ right = *cbd2;
+ right.pos = 1.0f;
+ cbd1 = &right;
+ }
+ else if (a == 0) {
+ left = *cbd1;
+ left.pos = 0.0f;
+ cbd2 = &left;
+ }
+ else {
+ cbd2 = cbd1 - 1;
+ }
+
+ if ((in >= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) {
out[0] = cbd1->r;
out[1] = cbd1->g;
out[2] = cbd1->b;
out[3] = cbd1->a;
}
else {
- CBData left, right;
-
- /* we're looking for first pos > in */
- for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break;
-
- if (a == coba->tot) {
- cbd2 = cbd1 - 1;
- right = *cbd2;
- right.pos = 1.0f;
- cbd1 = &right;
- }
- else if (a == 0) {
- left = *cbd1;
- left.pos = 0.0f;
- cbd2 = &left;
+
+ if (cbd2->pos != cbd1->pos) {
+ fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos);
}
else {
- cbd2 = cbd1 - 1;
+ /* was setting to 0.0 in 2.56 & previous, but this
+ * is incorrect for the last element, see [#26732] */
+ fac = (a != coba->tot) ? 0.0f : 1.0f;
}
-
- if (in >= cbd1->pos && coba->ipotype < 2) {
- out[0] = cbd1->r;
- out[1] = cbd1->g;
- out[2] = cbd1->b;
- out[3] = cbd1->a;
+
+ if (ipotype == COLBAND_INTERP_CONSTANT) {
+ /* constant */
+ out[0] = cbd2->r;
+ out[1] = cbd2->g;
+ out[2] = cbd2->b;
+ out[3] = cbd2->a;
}
- else {
-
- if (cbd2->pos != cbd1->pos)
- fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos);
+ else if (ipotype >= COLBAND_INTERP_B_SPLINE) {
+ /* ipo from right to left: 3 2 1 0 */
+ float t[4];
+
+ if (a >= coba->tot - 1) cbd0 = cbd1;
+ else cbd0 = cbd1 + 1;
+ if (a < 2) cbd3 = cbd2;
+ else cbd3 = cbd2 - 1;
+
+ CLAMP(fac, 0.0f, 1.0f);
+
+ if (ipotype == COLBAND_INTERP_CARDINAL) {
+ key_curve_position_weights(fac, t, KEY_CARDINAL);
+ }
else {
- /* was setting to 0.0 in 2.56 & previous, but this
- * is incorrect for the last element, see [#26732] */
- fac = (a != coba->tot) ? 0.0f : 1.0f;
+ key_curve_position_weights(fac, t, KEY_BSPLINE);
+ }
+
+ out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r;
+ out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g;
+ out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b;
+ out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a;
+ CLAMP(out[0], 0.0f, 1.0f);
+ CLAMP(out[1], 0.0f, 1.0f);
+ CLAMP(out[2], 0.0f, 1.0f);
+ CLAMP(out[3], 0.0f, 1.0f);
+ }
+ else {
+ float mfac;
+
+ if (ipotype == COLBAND_INTERP_EASE) {
+ mfac = fac * fac;
+ fac = 3.0f * mfac - 2.0f * mfac * fac;
}
-
- if (coba->ipotype == 4) {
- /* constant */
- out[0] = cbd2->r;
- out[1] = cbd2->g;
- out[2] = cbd2->b;
- out[3] = cbd2->a;
- return 1;
+
+ mfac = 1.0f - fac;
+
+ if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSV)) {
+ float col1[3], col2[3];
+
+ rgb_to_hsv_v(&cbd1->r, col1);
+ rgb_to_hsv_v(&cbd2->r, col2);
+
+ out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]);
+ out[1] = mfac * col1[1] + fac * col2[1];
+ out[2] = mfac * col1[2] + fac * col2[2];
+ out[3] = mfac * cbd1->a + fac * cbd2->a;
+
+ hsv_to_rgb_v(out, out);
}
-
- if (coba->ipotype >= 2) {
- /* ipo from right to left: 3 2 1 0 */
-
- if (a >= coba->tot - 1) cbd0 = cbd1;
- else cbd0 = cbd1 + 1;
- if (a < 2) cbd3 = cbd2;
- else cbd3 = cbd2 - 1;
-
- CLAMP(fac, 0.0f, 1.0f);
-
- if (coba->ipotype == 3)
- key_curve_position_weights(fac, t, KEY_CARDINAL);
- else
- key_curve_position_weights(fac, t, KEY_BSPLINE);
-
- out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r;
- out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g;
- out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b;
- out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a;
- CLAMP(out[0], 0.0f, 1.0f);
- CLAMP(out[1], 0.0f, 1.0f);
- CLAMP(out[2], 0.0f, 1.0f);
- CLAMP(out[3], 0.0f, 1.0f);
+ else if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSL)) {
+ float col1[3], col2[3];
+
+ rgb_to_hsl_v(&cbd1->r, col1);
+ rgb_to_hsl_v(&cbd2->r, col2);
+
+ out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]);
+ out[1] = mfac * col1[1] + fac * col2[1];
+ out[2] = mfac * col1[2] + fac * col2[2];
+ out[3] = mfac * cbd1->a + fac * cbd2->a;
+
+ hsl_to_rgb_v(out, out);
}
else {
-
- if (coba->ipotype == 1) { /* EASE */
- mfac = fac * fac;
- fac = 3.0f * mfac - 2.0f * mfac * fac;
- }
- mfac = 1.0f - fac;
-
+ /* COLBAND_BLEND_RGB */
out[0] = mfac * cbd1->r + fac * cbd2->r;
out[1] = mfac * cbd1->g + fac * cbd2->g;
out[2] = mfac * cbd1->b + fac * cbd2->b;
@@ -408,19 +512,18 @@ CBData *colorband_element_add(struct ColorBand *coba, float position)
if (coba->tot == MAXCOLORBAND) {
return NULL;
}
- else if (coba->tot > 0) {
+ else {
CBData *xnew;
- float col[4];
-
- do_colorband(coba, position, col);
xnew = &coba->data[coba->tot];
xnew->pos = position;
- xnew->r = col[0];
- xnew->g = col[1];
- xnew->b = col[2];
- xnew->a = col[3];
+ if (coba->tot != 0) {
+ do_colorband(coba, position, &xnew->r);
+ }
+ else {
+ zero_v4(&xnew->r);
+ }
}
coba->tot++;
@@ -474,7 +577,8 @@ void BKE_texture_free(Tex *tex)
void default_tex(Tex *tex)
{
- tex->type = TEX_CLOUDS;
+ tex->type = TEX_IMAGE;
+ tex->ima = NULL;
tex->stype = 0;
tex->flag = TEX_CHECKER_ODD;
tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA;
@@ -592,7 +696,7 @@ Tex *add_texture(Main *bmain, const char *name)
void default_mtex(MTex *mtex)
{
- mtex->texco = TEXCO_ORCO;
+ mtex->texco = TEXCO_UV;
mtex->mapto = MAP_COL;
mtex->object = NULL;
mtex->projx = PROJ_X;
@@ -747,8 +851,7 @@ Tex *localize_texture(Tex *tex)
{
Tex *texn;
- texn = BKE_libblock_copy(&tex->id);
- BLI_remlink(&G.main->tex, texn);
+ texn = BKE_libblock_copy_nolib(&tex->id, false);
/* image texture: BKE_texture_free also doesn't decrease */
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index 76b7ad5d982..6300e29f516 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -501,7 +501,7 @@ static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker,
static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track,
const MovieTrackingMarker *old_marker, int curfra, bool tracked,
int frame_width, int frame_height,
- double dst_pixel_x[5], double dst_pixel_y[5])
+ const double dst_pixel_x[5], const double dst_pixel_y[5])
{
MovieTrackingMarker new_marker;
int frame_delta = context->backwards ? -1 : 1;
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index ffbdf5cb486..eb224020977 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -82,7 +82,7 @@ static bool stabilization_median_point_get(MovieTracking *tracking, int framenr,
* NOTE: frame number should be in clip space, not scene space
*/
static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height,
- float firstmedian[2], float median[2],
+ const float firstmedian[2], const float median[2],
float translation[2], float *scale, float *angle)
{
MovieTrackingStabilization *stab = &tracking->stabilization;
@@ -439,6 +439,6 @@ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect
rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */
/* compose transformation matrix */
- mul_serie_m4(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat,
- scale_mat, inv_center_mat, NULL);
+ mul_m4_series(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat,
+ scale_mat, inv_center_mat);
}
diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c
index fb55e3d2137..a65bd28da97 100644
--- a/source/blender/blenkernel/intern/treehash.c
+++ b/source/blender/blenkernel/intern/treehash.c
@@ -59,7 +59,7 @@ static TseGroup *tse_group_create(void)
static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
{
- if (tse_group->size == tse_group->allocated) {
+ if (UNLIKELY(tse_group->size == tse_group->allocated)) {
tse_group->allocated *= 2;
tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated);
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 8aca9f78702..5a2c77b5619 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -41,6 +41,8 @@
# include "BLI_winstuff.h"
#endif
+/* no BKE or DNA includes! */
+
#define TEMP_STR_SIZE 256
#define SEP_CHR '#'
@@ -349,7 +351,7 @@ static void unit_dual_convert(double value, bUnitCollection *usys, bUnitDef **un
static size_t unit_as_string(char *str, int len_max, double value, int prec, bUnitCollection *usys,
/* non exposed options */
- bUnitDef *unit, char pad)
+ const bUnitDef *unit, char pad)
{
double value_conv;
size_t len, i;
@@ -456,7 +458,7 @@ size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system
return unit_as_string(str, len_max, value, prec, usys, NULL, pad ? ' ' : '\0');
}
-BLI_INLINE int isalpha_or_utf8(const int ch)
+BLI_INLINE bool isalpha_or_utf8(const int ch)
{
return (ch >= 128 || isalpha(ch));
}
@@ -493,11 +495,11 @@ static const char *unit_find_str(const char *str, const char *substr)
*
* "1m1cm+2mm" - Original value
* "1*1#1*0.01#+2*0.001#" - Replace numbers
- * "1*1,1*0.01 +2*0.001 " - Add comma's if ( - + * / % ^ < > ) not found in between
+ * "1*1+1*0.01 +2*0.001 " - Add add signs if ( + - * / | & ~ < > ^ ! = % ) not found in between
*
*/
-/* not too strict, (- = * /) are most common */
+/* not too strict, (+ - * /) are most common */
static bool ch_is_op(char op)
{
switch (op) {
@@ -514,9 +516,11 @@ static bool ch_is_op(char op)
case '!':
case '=':
case '%':
- return 1;
+ return true;
+ break;
default:
- return 0;
+ return false;
+ break;
}
}
@@ -579,14 +583,42 @@ static int unit_replace(char *str, int len_max, char *str_tmp, double scale_pref
return ofs;
}
-static int unit_find(const char *str, bUnitDef *unit)
+static bool unit_find(const char *str, bUnitDef *unit)
{
- if (unit_find_str(str, unit->name_short)) return 1;
- if (unit_find_str(str, unit->name_plural)) return 1;
- if (unit_find_str(str, unit->name_alt)) return 1;
- if (unit_find_str(str, unit->name)) return 1;
+ if (unit_find_str(str, unit->name_short)) return true;
+ if (unit_find_str(str, unit->name_plural)) return true;
+ if (unit_find_str(str, unit->name_alt)) return true;
+ if (unit_find_str(str, unit->name)) return true;
- return 0;
+ return false;
+}
+
+static bUnitDef *unit_detect_from_str(bUnitCollection *usys, const char *str, const char *str_prev)
+{
+ /* Try to find a default unit from current or previous string.
+ * This allows us to handle cases like 2 + 2mm, people would expect to get 4mm, not 2.002m!
+ * Note this does not handle corner cases like 2 + 2cm + 1 + 2.5mm... We can't support everything. */
+ bUnitDef *unit = NULL;
+
+ /* see which units the new value has */
+ for (unit = usys->units; unit->name; unit++) {
+ if (unit_find(str, unit))
+ break;
+ }
+ /* Else, try to infer the default unit from the previous string. */
+ if (str_prev && (unit == NULL || unit->name == NULL)) {
+ /* see which units the original value had */
+ for (unit = usys->units; unit->name; unit++) {
+ if (unit_find(str_prev, unit))
+ break;
+ }
+ }
+ /* Else, fall back to default unit. */
+ if (unit == NULL || unit->name == NULL) {
+ unit = unit_default(usys);
+ }
+
+ return unit;
}
/* make a copy of the string that replaces the units with numbers
@@ -597,37 +629,58 @@ static int unit_find(const char *str, bUnitDef *unit)
* 10.1km -> 10.1*1000.0
* ...will be resolved by python.
*
- * values will be split by a comma's
- * 5'2" -> 5*0.3048, 2*0.0254
+ * values will be split by an add sign
+ * 5'2" -> 5*0.3048 + 2*0.0254
*
* str_prev is optional, when valid it is used to get a base unit when none is set.
*
* return true of a change was made.
*/
-int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
+bool bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
{
bUnitCollection *usys = unit_get_system(system, type);
- bUnitDef *unit;
+ bUnitDef *unit = NULL, *default_unit;
+ double scale_pref_base = scale_pref;
char str_tmp[TEMP_STR_SIZE];
- int changed = 0;
+ bool changed = false;
if (usys == NULL || usys->units[0].name == NULL) {
- return 0;
+ return changed;
}
/* make lowercase */
BLI_ascii_strtolower(str, len_max);
+ /* Try to find a default unit from current or previous string. */
+ default_unit = unit_detect_from_str(usys, str, str_prev);
+
+ /* We apply the default unit to the whole expression (default unit is now the reference '1.0' one). */
+ scale_pref_base *= default_unit->scalar;
+
+ /* Apply the default unit on the whole expression, this allows to handle nasty cases like '2+2in'. */
+ if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)*%.9g", str, default_unit->scalar) < sizeof(str_tmp)) {
+ strncpy(str, str_tmp, len_max);
+ }
+ else {
+ /* BLI_snprintf would not fit into str_tmp, cant do much in this case
+ * check for this because otherwise bUnit_ReplaceString could call its self forever */
+ return changed;
+ }
+
for (unit = usys->units; unit->name; unit++) {
/* in case there are multiple instances */
- while (unit_replace(str, len_max, str_tmp, scale_pref, unit))
+ while (unit_replace(str, len_max, str_tmp, scale_pref_base, unit))
changed = true;
}
unit = NULL;
{
/* try other unit systems now, so we can evaluate imperial when metric is set for eg. */
+ /* Note that checking other systems at that point means we do not support their units as 'default' one.
+ * In other words, when in metrics, typing '2+2in' will give 2 meters 2 inches, not 4 inches.
+ * I do think this is the desired behavior!
+ */
bUnitCollection *usys_iter;
int system_iter;
@@ -638,7 +691,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
for (unit = usys_iter->units; unit->name; unit++) {
int ofs = 0;
/* in case there are multiple instances */
- while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref, unit)))
+ while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref_base, unit)))
changed = true;
}
}
@@ -647,35 +700,9 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
}
unit = NULL;
- if (changed == 0) {
- /* no units given so infer a unit from the previous string or default */
- if (str_prev) {
- /* see which units the original value had */
- for (unit = usys->units; unit->name; unit++) {
- if (unit_find(str_prev, unit))
- break;
- }
- }
-
- if (unit == NULL || unit->name == NULL)
- unit = unit_default(usys);
-
- /* add the unit prefix and re-run, use brackets in case there was an expression given */
- if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)%s", str, unit->name) < sizeof(str_tmp)) {
- strncpy(str, str_tmp, len_max);
- return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type);
- }
- else {
- /* BLI_snprintf would not fit into str_tmp, cant do much in this case
- * check for this because otherwise bUnit_ReplaceString could call its self forever */
- return 0;
- }
-
- }
-
- /* replace # with commas when there is no operator between it and the next number
+ /* replace # with add sign when there is no operator between it and the next number
*
- * "1*1# 3*100# * 3" -> "1 *1, 3 *100 * 3"
+ * "1*1# 3*100# * 3" -> "1*1+ 3*100 * 3"
*
* */
{
@@ -683,25 +710,19 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
const char *ch = str;
while ((str_found = strchr(str_found, SEP_CHR))) {
+ bool op_found = false;
- int op_found = 0;
- /* any operators after this?*/
+ /* any operators after this? */
for (ch = str_found + 1; *ch != '\0'; ch++) {
-
if (*ch == ' ' || *ch == '\t') {
- /* do nothing */
- }
- else if (ch_is_op(*ch) || *ch == ',') { /* found an op, no need to insert a ',' */
- op_found = 1;
- break;
- }
- else { /* found a non-op character */
- op_found = 0;
- break;
+ continue;
}
+ op_found = (ch_is_op(*ch) || ELEM(*ch, ',', ')'));
+ break;
}
- *str_found++ = op_found ? ' ' : ',';
+ /* If found an op, comma or closing parenthesis, no need to insert a '+', else we need it. */
+ *str_found++ = op_found ? ' ' : '+';
}
}
@@ -771,7 +792,7 @@ double bUnit_BaseScalar(int system, int type)
}
/* external access */
-int bUnit_IsValid(int system, int type)
+bool bUnit_IsValid(int system, int type)
{
return !(system < 0 || system > UNIT_SYSTEM_TOT || type < 0 || type > B_UNIT_TYPE_TOT);
}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 5065c3ae04f..8e3c92314e6 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -142,8 +142,7 @@ World *localize_world(World *wrld)
World *wrldn;
int a;
- wrldn = BKE_libblock_copy(&wrld->id);
- BLI_remlink(&G.main->world, wrldn);
+ wrldn = BKE_libblock_copy_nolib(&wrld->id, false);
for (a = 0; a < MAX_MTEX; a++) {
if (wrld->mtex[a]) {
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index a9f040b8650..aef44993912 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -110,7 +110,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
}
#endif
#ifdef WITH_FFMPEG
- if (ELEM4(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) {
+ if (ELEM(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) {
mh.start_movie = BKE_ffmpeg_start;
mh.append_movie = BKE_ffmpeg_append;
mh.end_movie = BKE_ffmpeg_end;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 00dfae9e72a..ca21180000d 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -30,13 +30,6 @@
#include <string.h>
#include <stdio.h>
-#if defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__)
-/* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */
-# if _MSC_VER < 1400
-# include <stdint.h>
-# endif
-#endif
-
#include <stdlib.h>
#include <libavformat/avformat.h>
@@ -708,7 +701,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
* you have various implementations around. float samples in particular are not always supported.
*/
const enum AVSampleFormat *p = codec->sample_fmts;
- for (; *p!=-1; p++) {
+ for (; *p != -1; p++) {
if (*p == st->codec->sample_fmt)
break;
}