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/key.c')
-rw-r--r--source/blender/blenkernel/intern/key.c409
1 files changed, 320 insertions, 89 deletions
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index a1d0680785d..23d9c076182 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -52,6 +52,7 @@
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
+#include "DNA_strands_types.h"
#include "DNA_texture_types.h"
#include "BKE_animsys.h"
@@ -66,20 +67,21 @@
#include "BKE_particle.h"
#include "BKE_editmesh.h"
#include "BKE_scene.h"
+#include "BKE_strands.h"
#include "RNA_access.h"
#include "RE_render_ext.h"
-#define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */
-#define KEY_MODE_BPOINT 1
-#define KEY_MODE_BEZTRIPLE 2
-
/* old defines from DNA_ipo_types.h for data-type, stored in DNA - don't modify! */
#define IPO_FLOAT 4
#define IPO_BEZTRIPLE 100
#define IPO_BPOINT 101
+#define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */
+#define KEY_MODE_BPOINT 1
+#define KEY_MODE_BEZTRIPLE 2
+
void BKE_key_free(Key *key)
{
KeyBlock *kb;
@@ -104,55 +106,70 @@ void BKE_key_free_nolib(Key *key)
}
}
-Key *BKE_key_add(ID *id) /* common function */
+static void key_set_elemstr(ID *id, short fromtype, char *r_elemstr, int *r_elemsize)
+{
+ /* XXX the code here uses some defines which will soon be deprecated... */
+ char elemtype = IPO_FLOAT;
+ char numelem = 0;
+ int elemsize = 0;
+
+ switch (fromtype) {
+ case KEY_FROMTYPE_ID:
+ if (id) {
+ switch (GS(id->name)) {
+ case ID_ME:
+ numelem = 3;
+ elemtype = IPO_FLOAT;
+ elemsize = 12;
+ break;
+ case ID_LT:
+ numelem = 3;
+ elemtype = IPO_FLOAT;
+ elemsize = 12;
+ break;
+ case ID_CU:
+ numelem = 4;
+ elemtype = IPO_BPOINT;
+ elemsize = 16;
+ break;
+ }
+ }
+ break;
+ case KEY_FROMTYPE_STRANDS:
+ numelem = 3;
+ elemtype = IPO_FLOAT;
+ elemsize = 12;
+ break;
+ }
+
+ r_elemstr[0] = numelem;
+ r_elemstr[1] = elemtype;
+ r_elemstr[2] = 0;
+ *r_elemsize = elemsize;
+}
+
+Key *BKE_key_add_ex(ID *from, short fromtype) /* common function */
{
Key *key;
- char *el;
key = BKE_libblock_alloc(G.main, ID_KE, "Key");
key->type = KEY_NORMAL;
- BKE_key_set_from_id(key, id);
+ BKE_key_set_from_id(key, from);
+ key->fromtype = fromtype;
key->uidgen = 1;
- /* XXX the code here uses some defines which will soon be deprecated... */
- switch (GS(id->name)) {
- case ID_ME:
- el = key->elemstr;
-
- el[0] = 3;
- el[1] = IPO_FLOAT;
- el[2] = 0;
-
- key->elemsize = 12;
-
- break;
- case ID_LT:
- el = key->elemstr;
-
- el[0] = 3;
- el[1] = IPO_FLOAT;
- el[2] = 0;
-
- key->elemsize = 12;
-
- break;
- case ID_CU:
- el = key->elemstr;
-
- el[0] = 4;
- el[1] = IPO_BPOINT;
- el[2] = 0;
-
- key->elemsize = 16;
-
- break;
- }
+ key_set_elemstr(from, fromtype, key->elemstr, &key->elemsize);
return key;
}
+Key *BKE_key_add(ID *id)
+{
+ return BKE_key_add_ex(id, KEY_FROMTYPE_ID);
+}
+
Key *BKE_key_add_particles(Object *ob, ParticleSystem *psys) /* particles are "special" */
{
Key *key;
@@ -566,7 +583,7 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **
if (kb == actkb) {
/* this hack makes it possible to edit shape keys in
* edit mode with shape keys blending applied */
- if (key->from_extra.type == KEY_OWNER_MESH) {
+ if (key->from && key->from_extra.type == KEY_OWNER_MESH) {
Mesh *me;
BMVert *eve;
BMIter iter;
@@ -598,39 +615,50 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **
/* currently only the first value of 'ofs' may be set. */
static bool key_pointer_size(const Key *key, const int mode, int *poinsize, int *ofs)
{
- switch (key->from_extra.type) {
- case KEY_OWNER_MESH:
- *ofs = sizeof(float) * 3;
- *poinsize = *ofs;
- break;
- case KEY_OWNER_LATTICE:
- *ofs = sizeof(float) * 3;
- *poinsize = *ofs;
- break;
- case KEY_OWNER_CURVE:
- if (mode == KEY_MODE_BPOINT) {
- *ofs = sizeof(float) * 4;
- *poinsize = *ofs;
- }
- else {
- ofs[0] = sizeof(float) * 12;
- *poinsize = (*ofs) / 3;
+ switch (key->fromtype) {
+ case KEY_FROMTYPE_ID:
+ if (!key->from)
+ return false;
+
+ switch (GS(key->from->name)) {
+ case ID_ME:
+ *ofs = sizeof(float) * 3;
+ *poinsize = *ofs;
+ break;
+ case KEY_OWNER_LATTICE:
+ *ofs = sizeof(float) * 3;
+ *poinsize = *ofs;
+ break;
+ case KEY_OWNER_CURVE:
+ if (mode == KEY_MODE_BPOINT) {
+ *ofs = sizeof(float) * 4;
+ *poinsize = *ofs;
+ }
+ else {
+ ofs[0] = sizeof(float) * 12;
+ *poinsize = (*ofs) / 3;
+ }
+ break;
+ case KEY_OWNER_PARTICLES:
+ *ofs = sizeof(float) * 3;
+ *poinsize = *ofs;
+ break;
+
+ default:
+ BLI_assert(!"invalid 'key->from' ID type");
+ return false;
}
break;
- case KEY_OWNER_PARTICLES:
+
+ case KEY_FROMTYPE_STRANDS:
*ofs = sizeof(float) * 3;
*poinsize = *ofs;
break;
-
- default:
- BLI_assert(!"invalid 'key->from' ID type");
- return false;
}
-
return true;
}
-static void cp_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, const int mode)
+static void cp_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, const int mode, void *kref_data)
{
float ktot = 0.0, kd = 0.0;
int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo = 0;
@@ -657,7 +685,12 @@ static void cp_key(const int start, int end, const int tot, char *poin, Key *key
}
k1 = key_block_get_data(key, actkb, kb, &freek1);
- kref = key_block_get_data(key, actkb, key->refkey, &freekref);
+ if (kref_data) {
+ kref = kref_data;
+ freekref = NULL;
+ }
+ else
+ kref = key_block_get_data(key, actkb, key->refkey, &freekref);
/* this exception is needed curves with multiple splines */
if (start != 0) {
@@ -760,7 +793,7 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const
a1 = max_ii(a, start);
a2 = min_ii(a + step, end);
- if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BPOINT);
+ if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BPOINT, NULL);
}
else if (nu->bezt) {
step = 3 * nu->pntsu;
@@ -769,7 +802,7 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const
a1 = max_ii(a, start);
a2 = min_ii(a + step, end);
- if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BEZTRIPLE);
+ if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BEZTRIPLE, NULL);
}
else {
step = 0;
@@ -777,8 +810,8 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const
}
}
-void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb,
- float **per_keyblock_weights, const int mode)
+void BKE_key_evaluate_relative_ex(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb,
+ float **per_keyblock_weights, const int mode, char *refdata)
{
KeyBlock *kb;
int *ofsp, ofs[3], elemsize, b;
@@ -803,7 +836,8 @@ void BKE_key_evaluate_relative(const int start, int end, const int tot, char *ba
if (mode == KEY_MODE_BEZTRIPLE) elemsize *= 3;
/* step 1 init */
- cp_key(start, end, tot, basispoin, key, actkb, key->refkey, NULL, mode);
+ if (!refdata)
+ cp_key(start, end, tot, basispoin, key, actkb, key->refkey, NULL, mode, NULL);
/* step 2: do it */
@@ -813,17 +847,21 @@ void BKE_key_evaluate_relative(const int start, int end, const int tot, char *ba
/* only with value, and no difference allowed */
if (!(kb->flag & KEYBLOCK_MUTE) && icuval != 0.0f && kb->totelem == tot) {
- KeyBlock *refb;
float weight, *weights = per_keyblock_weights ? per_keyblock_weights[keyblock_index] : NULL;
char *freefrom = NULL, *freereffrom = NULL;
- /* reference now can be any block */
- refb = BLI_findlink(&key->block, kb->relative);
- if (refb == NULL) continue;
-
poin = basispoin;
from = key_block_get_data(key, actkb, kb, &freefrom);
- reffrom = key_block_get_data(key, actkb, refb, &freereffrom);
+ if (refdata) {
+ reffrom = refdata;
+ }
+ else {
+ /* reference now can be any block */
+ KeyBlock *refb = BLI_findlink(&key->block, kb->relative);
+ if (refb == NULL) continue;
+
+ reffrom = key_block_get_data(key, actkb, refb, &freereffrom);
+ }
poin += start * poinsize;
reffrom += key->elemsize * start; // key elemsize yes!
@@ -878,6 +916,11 @@ void BKE_key_evaluate_relative(const int start, int end, const int tot, char *ba
}
}
+void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb,
+ float **per_keyblock_weights, const int mode)
+{
+ BKE_key_evaluate_relative_ex(start, end, tot, basispoin, key, actkb, per_keyblock_weights, mode, NULL);
+}
static void do_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, const int mode)
{
@@ -1174,6 +1217,21 @@ static float *get_object_weights_array(Object *ob, char *vgroup, WeightsArrayCac
return NULL;
}
+static float *get_weights_array_strands(Strands *strands, const char *UNUSED(vgroup), bool is_refkey, WeightsArrayCache *UNUSED(cache))
+{
+ int totvert = strands->totverts;
+
+ if (is_refkey) {
+ /* for the refkey, return zero weights, so the refkey actually uses the unmodified data */
+ float *weights = MEM_callocN(totvert * sizeof(float), "weights");
+ return weights;
+ }
+ else {
+ /* TODO no vgroup support for strands yet */
+ return NULL;
+ }
+}
+
float **BKE_keyblock_get_per_block_object_weights(Object *ob, Key *key, WeightsArrayCache *cache)
{
KeyBlock *keyblock;
@@ -1281,6 +1339,26 @@ float **BKE_keyblock_get_per_block_particle_weights(Object *ob, ParticleSystem *
return per_keyblock_weights;
}
+float **BKE_keyblock_strands_get_per_block_weights(Strands *strands, Key *key, WeightsArrayCache *cache)
+{
+ KeyBlock *keyblock;
+ float **per_keyblock_weights;
+ int keyblock_index;
+
+ per_keyblock_weights =
+ MEM_mallocN(sizeof(*per_keyblock_weights) * key->totkey,
+ "per keyblock weights");
+
+ for (keyblock = key->block.first, keyblock_index = 0;
+ keyblock;
+ keyblock = keyblock->next, keyblock_index++)
+ {
+ per_keyblock_weights[keyblock_index] = get_weights_array_strands(strands, keyblock->vgroup, keyblock == key->refkey, cache);
+ }
+
+ return per_keyblock_weights;
+}
+
void BKE_keyblock_free_per_block_weights(Key *key, float **per_keyblock_weights, WeightsArrayCache *cache)
{
int a;
@@ -1329,7 +1407,7 @@ static void do_mesh_key(Object *ob, Key *key, char *out, const int tot)
do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
}
else {
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY, NULL);
}
}
}
@@ -1420,7 +1498,7 @@ static void do_latt_key(Object *ob, Key *key, char *out, const int tot)
do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
}
else {
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY, NULL);
}
}
@@ -1449,7 +1527,7 @@ static void do_psys_key(Object *ob, ParticleSystem *psys, float cfra, Key *key,
if (flag == 0)
do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
else
- cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY, NULL);
}
}
@@ -1529,7 +1607,7 @@ float *BKE_key_evaluate_object_ex(
if (OB_TYPE_SUPPORT_VGROUP(ob->type)) {
float *weights = get_object_weights_array(ob, kb->vgroup, NULL);
- cp_key(0, tot, tot, out, key, actkb, kb, weights, 0);
+ cp_key(0, tot, tot, out, key, actkb, kb, weights, 0, NULL);
if (weights) MEM_freeN(weights);
}
@@ -1555,6 +1633,103 @@ float *BKE_key_evaluate_object(Object *ob, int *r_totelem)
return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0);
}
+static void do_strands_key(Strands *strands, Key *key, KeyBlock *actkb, char *out, const int tot)
+{
+ KeyBlock *k[4];
+ float t[4];
+ int flag = 0;
+
+ if (key->type == KEY_RELATIVE) {
+ WeightsArrayCache cache = {0, NULL};
+ float **per_keyblock_weights ;
+ per_keyblock_weights = BKE_keyblock_strands_get_per_block_weights(strands, key, &cache);
+ BKE_key_evaluate_relative_ex(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY, out);
+ BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, &cache);
+ }
+ else {
+ const float ctime_scaled = key->ctime / 100.0f;
+
+ flag = setkeys(ctime_scaled, &key->block, k, t, 0);
+
+ if (flag == 0) {
+ do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
+ }
+ else {
+ cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY, out);
+ }
+ }
+}
+
+float *BKE_key_evaluate_strands_ex(Strands *strands, Key *key, KeyBlock *actkb, bool lock_shape, int *r_totelem, float *arr, size_t arr_size)
+{
+ char *out;
+ int tot = 0, size = 0;
+
+ if (key == NULL || BLI_listbase_is_empty(&key->block))
+ return NULL;
+
+ /* compute size of output array */
+ tot = strands->totverts;
+ size = tot * 3 * sizeof(float);
+ /* if nothing to interpolate, cancel */
+ if (tot == 0 || size == 0)
+ return NULL;
+
+ /* allocate array */
+ if (arr == NULL) {
+ out = MEM_callocN(size, "BKE_key_evaluate_strands out");
+ }
+ else {
+ if (arr_size != size) {
+ return NULL;
+ }
+
+ out = (char *)arr;
+ }
+
+ if (lock_shape && actkb) {
+ /* shape locked, copy the locked shape instead of blending */
+ float *weights;
+
+ if (actkb->flag & KEYBLOCK_MUTE)
+ actkb = key->refkey;
+
+ /* XXX weights not supported for strands yet */
+ weights = get_weights_array_strands(strands, actkb->vgroup, actkb == key->refkey, NULL);
+
+ cp_key(0, tot, tot, out, key, actkb, actkb, weights, 0, out);
+
+ if (weights)
+ MEM_freeN(weights);
+ }
+ else {
+ do_strands_key(strands, key, actkb, out, tot);
+ }
+
+ if (r_totelem) {
+ *r_totelem = tot;
+ }
+ return (float *)out;
+}
+
+float *BKE_key_evaluate_strands(Strands *strands, Key *key, KeyBlock *actkb, bool lock_shape, int *r_totelem)
+{
+ size_t size = sizeof(float) * 3 * strands->totverts;
+ float *data = MEM_mallocN(size, "strands shape key data");
+ float *result;
+ float *fp;
+ int i;
+
+ for (i = 0, fp = data; i < strands->totverts; ++i, fp += 3)
+ copy_v3_v3(fp, strands->verts[i].co);
+
+ result = BKE_key_evaluate_strands_ex(strands, key, actkb, lock_shape, r_totelem, data, size);
+ if (result != data)
+ MEM_freeN(data);
+
+ return result;
+}
+
/* returns key coordinates when key applied, NULL otherwise */
float *BKE_key_evaluate_particles_ex(Object *ob, ParticleSystem *psys, float cfra, int *r_totelem,
float *arr, size_t arr_size)
@@ -1606,7 +1781,7 @@ float *BKE_key_evaluate_particles_ex(Object *ob, ParticleSystem *psys, float cfr
psys->shapenr = 1;
}
- cp_key(0, tot, tot, out, key, actkb, kb, NULL, 0);
+ cp_key(0, tot, tot, out, key, actkb, kb, NULL, 0, NULL);
}
else if (ob->shapeflag & OB_SHAPE_LOCK) {
/* shape locked, copy the locked shape instead of blending */
@@ -1623,7 +1798,7 @@ float *BKE_key_evaluate_particles_ex(Object *ob, ParticleSystem *psys, float cfr
weights = get_particle_weights_array(ob, psys, kb->name, cfra);
- cp_key(0, tot, tot, out, key, actkb, kb, weights, 0);
+ cp_key(0, tot, tot, out, key, actkb, kb, weights, 0, NULL);
if (weights) MEM_freeN(weights);
}
@@ -2035,6 +2210,55 @@ void BKE_keyblock_convert_to_mesh(KeyBlock *kb, Mesh *me)
}
}
+/************************* Strands ************************/
+void BKE_keyblock_update_from_strands(Strands *strands, KeyBlock *kb)
+{
+ StrandsVertex *vert;
+ float (*fp)[3];
+ int a, tot;
+
+ BLI_assert(strands->totverts == kb->totelem);
+
+ tot = strands->totverts;
+ if (tot == 0) return;
+
+ vert = strands->verts;
+ fp = kb->data;
+ for (a = 0; a < tot; a++, fp++, vert++) {
+ copy_v3_v3(*fp, vert->co);
+ }
+}
+
+void BKE_keyblock_convert_from_strands(Strands *strands, Key *key, KeyBlock *kb)
+{
+ int tot = strands->totverts;
+
+ if (strands->totverts == 0) return;
+
+ MEM_SAFE_FREE(kb->data);
+
+ kb->data = MEM_mallocN(key->elemsize * tot, __func__);
+ kb->totelem = tot;
+
+ BKE_keyblock_update_from_strands(strands, kb);
+}
+
+void BKE_keyblock_convert_to_strands(KeyBlock *kb, Strands *strands)
+{
+ StrandsVertex *vert;
+ const float (*fp)[3];
+ int a, tot;
+
+ vert = strands->verts;
+ fp = kb->data;
+
+ tot = min_ii(kb->totelem, strands->totverts);
+
+ for (a = 0; a < tot; a++, fp++, vert++) {
+ copy_v3_v3(vert->co, *fp);
+ }
+}
+
/************************* raw coords ************************/
void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
{
@@ -2272,11 +2496,10 @@ void BKE_keyblock_convert_from_hair_keys(struct Object *UNUSED(ob), struct Parti
* \param org_index if < 0, current object's active shape will be used as skey to move.
* \return true if something was done, else false.
*/
-bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
+bool BKE_keyblock_move_ex(Key *key, int *shapenr, int org_index, int new_index)
{
- Key *key = BKE_key_from_object(ob);
KeyBlock *kb;
- const int act_index = ob->shapenr - 1;
+ const int act_index = *shapenr - 1;
const int totkey = key->totkey;
int i;
bool rev, in_range = false;
@@ -2336,13 +2559,13 @@ bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
/* Need to update active shape number if it's affected, same principle as for relative indices above. */
if (org_index == act_index) {
- ob->shapenr = new_index + 1;
+ *shapenr = new_index + 1;
}
else if (act_index < org_index && act_index >= new_index) {
- ob->shapenr++;
+ (*shapenr)++;
}
else if (act_index > org_index && act_index <= new_index) {
- ob->shapenr--;
+ (*shapenr)--;
}
/* First key is always refkey, matches interface and BKE_key_sort */
@@ -2351,6 +2574,14 @@ bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
return true;
}
+bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
+{
+ int shapenr;
+ bool result = BKE_keyblock_move_ex(BKE_key_from_object(ob), &shapenr, org_index, new_index);
+ ob->shapenr = shapenr;
+ return result;
+}
+
/**
* Check if given keyblock (as index) is used as basis by others in given key.
*/