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:
authorJoshua Leung <aligorith@gmail.com>2009-01-22 13:53:22 +0300
committerJoshua Leung <aligorith@gmail.com>2009-01-22 13:53:22 +0300
commita017982074b3b11fd0157d8d604e02858411db70 (patch)
treea45dfe0864e4803070cbb603d7c0c5d5b5d900e0
parent3cdac8e9f78b0993b2f4ae446728b803837e7b3a (diff)
Animato - Basic version patching support
This is work-in-progress patching support for converting animation saved in old system to work in the new one. * Only IPOs/Actions directly attached to Objects + Shapekeys are converted for now. More types will follow... * This is currently done as a step outside of do_versions() due to problems with various pointers not having been resolved yet, but which are necessary for correct resolution of issues such as drivers... However, the current code does illustrate how the data should be converted to give best results/compat between the two systems. * Still need to get the converted data working with depsgraph correctly. Currently, some of my testfiles work, but the BBB files still don't.
-rw-r--r--source/blender/blenkernel/BKE_ipo.h121
-rw-r--r--source/blender/blenkernel/SConscript2
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c14
-rw-r--r--source/blender/blenkernel/intern/blender.c7
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c149
-rw-r--r--source/blender/blenkernel/intern/fcurve.c9
-rw-r--r--source/blender/blenkernel/intern/ipo.c2837
-rw-r--r--source/blender/blenkernel/intern/key.c5
-rw-r--r--source/blender/blenkernel/intern/library.c72
-rw-r--r--source/blender/blenkernel/intern/object.c32
-rw-r--r--source/blender/blenloader/SConscript2
-rw-r--r--source/blender/blenloader/intern/readfile.c28
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_action/action_edit.c33
-rwxr-xr-xsource/blender/makesrna/intern/rna_pose.c2
15 files changed, 739 insertions, 2576 deletions
diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h
index fae62b4a23e..a3f451438bd 100644
--- a/source/blender/blenkernel/BKE_ipo.h
+++ b/source/blender/blenkernel/BKE_ipo.h
@@ -24,7 +24,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): 2008, Joshua Leung (Animation Cleanup)
+ * Contributor(s): 2008,2009 Joshua Leung (Animation Cleanup, Animation Systme Recode)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -35,127 +35,18 @@
extern "C" {
#endif
-
-/* -------- IPO-Curve (Bezier) Calculations ---------- */
-
-// xxx perhaps this should be in curve api not in anim api
-void correct_bezpart(float *v1, float *v2, float *v3, float *v4);
-
-
-// XXX this file will soon be depreceated...
-#if 0 // XXX old animation system
-
-typedef struct CfraElem {
- struct CfraElem *next, *prev;
- float cfra;
- int sel;
-} CfraElem;
-
+struct Main;
struct Ipo;
-struct IpoCurve;
-struct MTex;
-struct Material;
-struct Scene;
-struct Object;
-struct Sequence;
-struct ListBase;
-struct BezTriple;
-struct ID;
-struct bPoseChannel;
-struct bActionChannel;
-struct rctf;
-/* ------------ Time Management ------------ */
+void do_versions_ipo_to_animato(struct Main *main);
-float frame_to_float(struct Scene *scene, int cfra);
+/* --------------------- xxx stuff ------------------------ */
-/* ------------ IPO Management ---------- */
-
-void free_ipo_curve(struct IpoCurve *icu);
void free_ipo(struct Ipo *ipo);
-void ipo_default_v2d_cur(struct Scene *scene, int blocktype, struct rctf *cur);
-
-struct Ipo *add_ipo(struct Scene *scene, char *name, int idcode);
-struct Ipo *copy_ipo(struct Ipo *ipo);
-
-void ipo_idnew(struct Ipo *ipo);
-
-struct IpoCurve *find_ipocurve(struct Ipo *ipo, int adrcode);
-short has_ipo_code(struct Ipo *ipo, int code);
-
-/* -------------- Make Local -------------- */
-
-void make_local_obipo(struct Ipo *ipo);
-void make_local_matipo(struct Ipo *ipo);
-void make_local_keyipo(struct Ipo *ipo);
-void make_local_ipo(struct Ipo *ipo);
-
-/* ------------ IPO-Curve Sanity ---------------- */
-
-void calchandles_ipocurve(struct IpoCurve *icu);
-void testhandles_ipocurve(struct IpoCurve *icu);
-void sort_time_ipocurve(struct IpoCurve *icu);
-int test_time_ipocurve(struct IpoCurve *icu);
-
-void set_interpolation_ipocurve(struct IpoCurve *icu, short ipo);
-
-/* -------- IPO-Curve (Bezier) Calculations ---------- */
-
+// xxx perhaps this should be in curve api not in anim api
void correct_bezpart(float *v1, float *v2, float *v3, float *v4);
-int findzero(float x, float q0, float q1, float q2, float q3, float *o);
-void berekeny(float f1, float f2, float f3, float f4, float *o, int b);
-void berekenx(float *f, float *o, int b);
-
-/* -------- IPO Curve Calculation and Evaluation --------- */
-
-float eval_icu(struct IpoCurve *icu, float ipotime);
-void calc_icu(struct IpoCurve *icu, float ctime);
-float calc_ipo_time(struct Ipo *ipo, float ctime);
-void calc_ipo(struct Ipo *ipo, float ctime);
-
-void calc_ipo_range(struct Ipo *ipo, float *start, float *end);
-
-/* ------------ Keyframe Column Tools -------------- */
-
-void add_to_cfra_elem(struct ListBase *lb, struct BezTriple *bezt);
-void make_cfra_list(struct Ipo *ipo, struct ListBase *elems);
-
-/* ---------------- IPO DataAPI ----------------- */
-
-void write_ipo_poin(void *poin, int type, float val);
-float read_ipo_poin(void *poin, int type);
-
-void *give_mtex_poin(struct MTex *mtex, int adrcode );
-void *get_pchan_ipo_poin(struct bPoseChannel *pchan, int adrcode);
-void *get_ipo_poin(struct ID *id, struct IpoCurve *icu, int *type);
-
-void set_icu_vars(struct IpoCurve *icu);
-
-/* ---------------- IPO Execution --------------- */
-
-void execute_ipo(struct ID *id, struct Ipo *ipo);
-void execute_action_ipo(struct bActionChannel *achan, struct bPoseChannel *pchan);
-
-void do_ipo_nocalc(struct Scene *scene, struct Ipo *ipo);
-void do_ipo(struct Scene *scene, struct Ipo *ipo);
-void do_mat_ipo(struct Scene *scene, struct Material *ma);
-void do_ob_ipo(struct Scene *scene, struct Object *ob);
-void do_seq_ipo(struct Scene *scene, struct Sequence *seq, int cfra);
-void do_ob_ipodrivers(struct Object *ob, struct Ipo *ipo, float ctime);
-
-void do_all_data_ipos(struct Scene *scene);
-short calc_ipo_spec(struct Ipo *ipo, int adrcode, float *ctime);
-void clear_delta_obipo(struct Ipo *ipo);
-
-/* ----------- IPO <-> GameEngine API ---------------- */
-
-/* the short is an IPO_Channel... */
-
-short IPO_GetChannels(struct Ipo *ipo, short *channels);
-float IPO_GetFloatValue(struct Ipo *ipo, short c, float ctime);
-
-#endif // XXX old animation system
+
#ifdef __cplusplus
};
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index aae4addd71e..bf09b2aac03 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -52,4 +52,4 @@ if env['BF_NO_ELBEEM']:
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'):
incs += ' ' + env['BF_PTHREADS_INC']
-env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [155] )
+env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [165] )
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index fb2a9731a40..30e5daeeb3b 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -86,7 +86,10 @@ AnimData *BKE_id_add_animdata (ID *id)
if (id_has_animdata(id)) {
IdAdtTemplate *iat= (IdAdtTemplate *)id;
- iat->adt= MEM_callocN(sizeof(AnimData), "AnimData");
+ /* check if there's already AnimData, in which case, don't add */
+ if (iat->adt == NULL)
+ iat->adt= MEM_callocN(sizeof(AnimData), "AnimData");
+
return iat->adt;
}
else
@@ -232,7 +235,8 @@ static void animsys_execute_fcurve (PointerRNA *ptr, AnimMapper *remap, FCurve *
free_path= animsys_remap_path(remap, fcu->rna_path, &path);
/* write value to setting */
- animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval);
+ if (path)
+ animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval);
/* free temp path-info */
if (free_path)
@@ -586,7 +590,7 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re
* or be layered on top of existing animation data.
* - Drivers should be in the appropriate order to be evaluated without problems...
*/
- if ((recalc & ADT_RECALC_DRIVERS) && (adt->recalc & ADT_RECALC_DRIVERS))
+ if ((recalc & ADT_RECALC_DRIVERS) /*&& (adt->recalc & ADT_RECALC_DRIVERS)*/) // XXX for now, don't check yet, as depsgraph hasn't been updated
{
animsys_evaluate_drivers(&id_ptr, adt, ctime);
}
@@ -615,7 +619,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
{
ID *id;
- //printf("Evaluate all animation - %f \n", ctime);
+ printf("Evaluate all animation - %f \n", ctime);
/* macro for less typing */
#define EVAL_ANIM_IDS(first) \
@@ -640,7 +644,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
EVAL_ANIM_IDS(main->camera.first);
/* shapekeys */
- // TODO...
+ EVAL_ANIM_IDS(main->key.first);
/* curves */
// TODO...
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index ae18a75daa0..2ad0c98bb79 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -74,6 +74,7 @@
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_ipo.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_object.h"
@@ -371,12 +372,12 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
//setscreen(G.curscreen);
}
+ // XXX is this in the right place?
+ do_versions_ipos_to_animato(G.main); // XXX fixme... complicated versionpatching
+
/* baseflags, groups, make depsgraph, etc */
set_scene_bg(CTX_data_scene(C));
- /* clear BONE_UNKEYED flags, these are not valid anymore for proxies */
- framechange_poses_clear_unkeyed();
-
/* last stage of do_versions actually, that sets recalc flags for recalc poses */
for(ob= G.main->object.first; ob; ob= ob->id.next) {
if(ob->type==OB_ARMATURE)
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 57dca4ddcb5..983a9bc9ac6 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -303,50 +303,66 @@ DagForest * dag_init()
return forest;
}
-static void dag_add_driver_relation(Ipo *ipo, DagForest *dag, DagNode *node, int isdata)
+/* isdata = object data... */
+// XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)...
+static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata)
{
- IpoCurve *icu;
+ FCurve *fcu;
DagNode *node1;
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->driver) {
-
- if (icu->driver->type == IPO_DRIVER_TYPE_PYTHON) {
-
- if ((icu->driver->flag & IPO_DRIVER_FLAG_INVALID) || (icu->driver->name[0] == '\0'))
- continue; /* empty or invalid expression */
+ for (fcu= adt->drivers.first; fcu; fcu= fcu->next) {
+ ChannelDriver *driver= fcu->driver;
+
+ if (driver->type == DRIVER_TYPE_PYTHON) {
+ /* PyDriver / 'Expression' */
+
+ /* skip if invalid in some way */
+ if ((driver->flag & DRIVER_FLAG_INVALID) || (driver->expression[0] == '\0'))
+ continue;
#ifndef DISABLE_PYTHON
- else {
- /* now we need refs to all objects mentioned in this
- * pydriver expression, to call 'dag_add_relation'
- * for each of them */
- Object **obarray = BPY_pydriver_get_objects(icu->driver);
- if (obarray) {
- Object *ob, **oba = obarray;
-
- while (*oba) {
- ob = *oba;
- node1 = dag_get_node(dag, ob);
- if (ob->type == OB_ARMATURE)
- dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Python Ipo Driver");
- else
- dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Python Ipo Driver");
- oba++;
- }
-
- MEM_freeN(obarray);
+ else {
+ /* now we need refs to all objects mentioned in this
+ * pydriver expression, to call 'dag_add_relation'
+ * for each of them */
+ Object **obarray = BPY_pydriver_get_objects(fcu->driver);
+ if (obarray) {
+ Object *ob, **oba = obarray;
+
+ while (*oba) {
+ ob = *oba;
+ node1 = dag_get_node(dag, ob);
+ if (ob->type == OB_ARMATURE)
+ dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Python Driver");
+ else
+ dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Python Driver");
+ oba++;
}
+
+ MEM_freeN(obarray);
}
-#endif /* DISABLE_PYTHON */
- }
- else if (icu->driver->ob) {
- node1 = dag_get_node(dag, icu->driver->ob);
- if(icu->driver->blocktype==ID_AR)
- dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Ipo Driver");
- else
- dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Ipo Driver");
}
+#endif /* DISABLE_PYTHON */
+ }
+ else if (driver->type == DRIVER_TYPE_ROTDIFF) {
+ // XXX rotational difference
+ }
+ else {
+ /* normal channel-drives-channel */
+ node1 = dag_get_node(dag, driver->id); // XXX we assume that id is an object...
+
+ // XXX what happens for bone drivers?
+ dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Ipo Driver");
}
+#if 0 // XXX old 'normal' type
+
+ else if (icu->driver->ob) {
+ node1 = dag_get_node(dag, icu->driver->ob);
+ if(icu->driver->blocktype==ID_AR)
+ dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Ipo Driver");
+ else
+ dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Ipo Driver");
+ }
+#endif // XXX old 'normal' type
}
}
@@ -371,7 +387,6 @@ static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Objec
static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, Object *ob, int mask)
{
bConstraint *con;
- bConstraintChannel *conchan;
DagNode * node;
DagNode * node2;
DagNode * node3;
@@ -426,6 +441,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
}
/* driver dependencies, nla modifiers */
+#if 0 // XXX old animation system
if(ob->ipo)
dag_add_driver_relation(ob->ipo, dag, node, 0);
@@ -466,6 +482,14 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
}
}
}
+#endif // XXX old animation system
+ if (ob->adt)
+ dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation
+
+ key= ob_get_key(ob);
+ if (key && key->adt)
+ dag_add_driver_relation(key->adt, dag, node, 1);
+
if (ob->modifiers.first) {
ModifierData *md;
@@ -515,11 +539,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Proxy");
/* inverted relation, so addtoroot shouldn't be set to zero */
}
+
+
if (ob->type==OB_CAMERA) {
Camera *cam = (Camera *)ob->data;
- if (cam->ipo) {
- dag_add_driver_relation(cam->ipo, dag, node, 1);
- }
+ if (cam->adt)
+ dag_add_driver_relation(cam->adt, dag, node, 1);
if (cam->dof_ob) {
node2 = dag_get_node(dag, cam->dof_ob);
dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Camera DoF");
@@ -527,10 +552,10 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
}
if (ob->type==OB_LAMP) {
Lamp *la = (Lamp *)ob->data;
- if (la->ipo) {
- dag_add_driver_relation(la->ipo, dag, node, 1);
- }
+ if (la->adt)
+ dag_add_driver_relation(la->adt, dag, node, 1);
}
+
if (ob->transflag & OB_DUPLI) {
if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
GroupObject *go;
@@ -566,9 +591,8 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
node2 = dag_get_node(dag, cu->taperobj);
dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Curve Taper");
}
- if(cu->ipo)
- dag_add_driver_relation(cu->ipo, dag, node, 1);
-
+ if (cu->adt)
+ dag_add_driver_relation(cu->adt, dag, node, 1);
}
else if(ob->type==OB_FONT) {
Curve *cu= ob->data;
@@ -1953,24 +1977,6 @@ static int object_modifiers_use_time(Object *ob)
return 0;
}
-#if 0 // XXX old animation system
-static int exists_channel(Object *ob, char *name)
-{
- bActionStrip *strip;
-
- if(ob->action)
- if(get_action_channel(ob->action, name))
- return 1;
-
- for (strip=ob->nlastrips.first; strip; strip=strip->next)
- if(get_action_channel(strip->act, name))
- return 1;
-
- return 0;
-}
-#endif // XXX old animation system
-
-
static short animdata_use_time(AnimData *adt)
{
NlaTrack *nlt;
@@ -2023,14 +2029,8 @@ static void dag_object_time_update_flags(Object *ob)
}
#if 0 // XXX old animation system
- if(ob->action || ob->nlastrips.first) {
- /* since actions now are mixed, we set the recalcs on the safe side */
- ob->recalc |= OB_RECALC_OB;
- if(ob->type==OB_ARMATURE)
- ob->recalc |= OB_RECALC_DATA;
- else if(exists_channel(ob, "Shape"))
- ob->recalc |= OB_RECALC_DATA;
- else if(ob->dup_group) {
+ if(ob->nlastrips.first) {
+ if(ob->dup_group) {
bActionStrip *strip;
/* this case is for groups with nla, whilst nla target has no action or nla */
for(strip= ob->nlastrips.first; strip; strip= strip->next) {
@@ -2041,6 +2041,7 @@ static void dag_object_time_update_flags(Object *ob)
}
#endif // XXX old animation system
if(animdata_use_time(ob->adt)) ob->recalc |= OB_RECALC;
+ if((ob->adt) && (ob->type==OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA;
if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
@@ -2316,6 +2317,7 @@ void DAG_pose_sort(Object *ob)
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
+#if 0 // XXX old animation system... driver stuff to watch out for
if(con->ipo) {
IpoCurve *icu;
for(icu= con->ipo->curve.first; icu; icu= icu->next) {
@@ -2327,7 +2329,7 @@ void DAG_pose_sort(Object *ob)
if(target) {
node2 = dag_get_node(dag, target);
dag_add_relation(dag, node2, node, 0, "Ipo Driver");
-
+
/* uncommented this line, results in dependencies
* not being added properly for this constraint,
* what is the purpose of this? - brecht */
@@ -2336,6 +2338,7 @@ void DAG_pose_sort(Object *ob)
}
}
}
+#endif // XXX old animation system... driver stuff to watch out for
if (cti && cti->get_constraint_targets) {
cti->get_constraint_targets(con, &targets);
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index f547b483092..e4c4e7a37b4 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1190,7 +1190,7 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo
cycles= data->after_cycles;
}
}
- if ELEM3(0, side, mode, cycles)
+ if ELEM(0, side, mode)
return;
/* extrapolation mode is 'cyclic' - find relative place within a cycle */
@@ -1209,7 +1209,12 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo
if (cycdx == 0)
return;
/* check that cyclic is still enabled for the specified time */
- if ( ((float)side * (evaltime - ofs) / cycdx) > cycles )
+ if (cycles == 0) {
+ /* catch this case so that we don't exit when we have cycles=0
+ * as this indicates infinite cycles...
+ */
+ }
+ else if ( ((float)side * (evaltime - ofs) / cycdx) > cycles )
return;
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 16d173bf5d6..0c9897f9b30 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -23,13 +23,19 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): 2008, Joshua Leung (IPO System cleanup)
+ * Contributor(s): 2008,2009 Joshua Leung (IPO System cleanup, Animation System Recode)
*
* ***** END GPL LICENSE BLOCK *****
*/
-#if 0 // XXX old animation system
-
+/* NOTE:
+ *
+ * This file is no longer used to provide tools for the depreceated IPO system. Instead, it
+ * is only used to house the conversion code to the new system.
+ *
+ * -- Joshua Leung, Jan 2009
+ */
+
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -40,8 +46,10 @@
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
#include "DNA_camera_types.h"
#include "DNA_lamp_types.h"
@@ -61,13 +69,16 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
+#include "BLI_dynstr.h"
#include "BKE_utildefines.h"
+#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_blender.h"
#include "BKE_curve.h"
#include "BKE_constraint.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_ipo.h"
#include "BKE_library.h"
@@ -75,1744 +86,732 @@
#include "BKE_mesh.h"
#include "BKE_object.h"
-#ifndef DISABLE_PYTHON
-#include "BPY_extern.h" /* for BPY_pydriver_eval() */
-#endif
-
-#define SMALL -1.0e-10
-
-/* ***************************** Adrcode Blocktype Defines ********************************* */
-
-/* This array concept was meant to make sure that defines such as OB_LOC_X
- don't have to be enumerated, also for backward compatibility, future changes,
- and to enable it all can be accessed with a for-next loop.
-
- This should whole adrcode system should eventually be replaced by a proper Data API
-*/
-
-
-int co_ar[CO_TOTIPO]= {
- CO_ENFORCE, CO_HEADTAIL
-};
-
-int ob_ar[OB_TOTIPO]= {
- OB_LOC_X, OB_LOC_Y, OB_LOC_Z, OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z,
- OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z,
- OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z,
- OB_LAY, OB_TIME, OB_COL_R, OB_COL_G, OB_COL_B, OB_COL_A,
- OB_PD_FSTR, OB_PD_FFALL, OB_PD_SDAMP, OB_PD_RDAMP, OB_PD_PERM, OB_PD_FMAXD
-};
-
-int ac_ar[AC_TOTIPO]= {
- AC_LOC_X, AC_LOC_Y, AC_LOC_Z,
- AC_EUL_X, AC_EUL_Y, AC_EUL_Z,
- AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z,
- AC_SIZE_X, AC_SIZE_Y, AC_SIZE_Z
-};
-
-int ma_ar[MA_TOTIPO]= {
- MA_COL_R, MA_COL_G, MA_COL_B,
- MA_SPEC_R, MA_SPEC_G, MA_SPEC_B,
- MA_MIR_R, MA_MIR_G, MA_MIR_B,
- MA_REF, MA_ALPHA, MA_EMIT, MA_AMB,
- MA_SPEC, MA_HARD, MA_SPTR, MA_IOR,
- MA_MODE, MA_HASIZE, MA_TRANSLU, MA_RAYM,
- MA_FRESMIR, MA_FRESMIRI, MA_FRESTRA, MA_FRESTRAI, MA_ADD,
-
- MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
- MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
- MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
- MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF, MA_MAP1+MAP_DISP
-};
-
-int te_ar[TE_TOTIPO] ={
-
- TE_NSIZE, TE_NDEPTH, TE_NTYPE, TE_TURB,
-
- TE_VNW1, TE_VNW2, TE_VNW3, TE_VNW4,
- TE_VNMEXP, TE_VN_COLT, TE_VN_DISTM,
-
- TE_ISCA, TE_DISTA,
-
- TE_MG_TYP, TE_MGH, TE_MG_LAC, TE_MG_OCT, TE_MG_OFF, TE_MG_GAIN,
-
- TE_N_BAS1, TE_N_BAS2,
-
- TE_COL_R, TE_COL_G, TE_COL_B, TE_BRIGHT, TE_CONTRA
-};
-
-int seq_ar[SEQ_TOTIPO]= {
- SEQ_FAC1
-};
-int cu_ar[CU_TOTIPO]= {
- CU_SPEED
-};
-int wo_ar[WO_TOTIPO]= {
- WO_HOR_R, WO_HOR_G, WO_HOR_B, WO_ZEN_R, WO_ZEN_G, WO_ZEN_B,
- WO_EXPOS, WO_MISI, WO_MISTDI, WO_MISTSTA, WO_MISTHI,
- WO_STAR_R, WO_STAR_G, WO_STAR_B, WO_STARDIST, WO_STARSIZE,
+/* *************************************************** */
+/* Old-Data Freeing Tools */
- MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
- MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
- MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
- MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF
-};
-
-int la_ar[LA_TOTIPO]= {
- LA_ENERGY, LA_COL_R, LA_COL_G, LA_COL_B,
- LA_DIST, LA_SPOTSI, LA_SPOTBL,
- LA_QUAD1, LA_QUAD2, LA_HALOINT,
-
- MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z,
- MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z,
- MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B,
- MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF
-};
-
-/* yafray: aperture & focal distance curves added */
-/* qdn: FDIST now available to Blender as well for defocus node */
-int cam_ar[CAM_TOTIPO]= {
- CAM_LENS, CAM_STA, CAM_END, CAM_YF_APERT, CAM_YF_FDIST, CAM_SHIFT_X, CAM_SHIFT_Y
-};
-
-int snd_ar[SND_TOTIPO]= {
- SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN
-};
-
-int fluidsim_ar[FLUIDSIM_TOTIPO]= {
- FLUIDSIM_VISC, FLUIDSIM_TIME,
- FLUIDSIM_GRAV_X , FLUIDSIM_GRAV_Y , FLUIDSIM_GRAV_Z ,
- FLUIDSIM_VEL_X , FLUIDSIM_VEL_Y , FLUIDSIM_VEL_Z ,
- FLUIDSIM_ACTIVE,
- FLUIDSIM_ATTR_FORCE_STR, FLUIDSIM_ATTR_FORCE_RADIUS,
- FLUIDSIM_VEL_FORCE_STR, FLUIDSIM_VEL_FORCE_RADIUS,
-};
-
-int part_ar[PART_TOTIPO]= {
- PART_EMIT_FREQ, PART_EMIT_LIFE, PART_EMIT_VEL, PART_EMIT_AVE, PART_EMIT_SIZE,
- PART_AVE, PART_SIZE, PART_DRAG, PART_BROWN, PART_DAMP, PART_LENGTH, PART_CLUMP,
- PART_GRAV_X, PART_GRAV_Y, PART_GRAV_Z, PART_KINK_AMP, PART_KINK_FREQ, PART_KINK_SHAPE,
- PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD, PART_PD2_FSTR, PART_PD2_FFALL, PART_PD2_FMAXD
-};
-
-/* ************************** Data-Level Functions ************************* */
-
-/* ---------------------- Freeing --------------------------- */
-
-/* frees the ipo curve itself too */
-void free_ipo_curve (IpoCurve *icu)
-{
- if (icu == NULL)
- return;
-
- if (icu->bezt)
- MEM_freeN(icu->bezt);
- if (icu->driver)
- MEM_freeN(icu->driver);
-
- MEM_freeN(icu);
-}
-
-/* do not free ipo itself */
+/* Free data from old IPO-Blocks (those which haven't been converted), but not IPO block itself */
+// XXX this shouldn't be necessary anymore, but may occur while not all data is converted yet
void free_ipo (Ipo *ipo)
{
IpoCurve *icu, *icn;
-
- if (ipo == NULL)
- return;
+ int n= 0;
for (icu= ipo->curve.first; icu; icu= icn) {
icn= icu->next;
+ n++;
- /* must remove the link before freeing, as the curve is freed too */
- BLI_remlink(&ipo->curve, icu);
- free_ipo_curve(icu);
- }
-}
-
-/* ---------------------- Init --------------------------- */
-
-/* on adding new ipos, or for empty views */
-// XXX users usually find these zoom settings problematic...
-void ipo_default_v2d_cur (Scene *scene, int blocktype, rctf *cur)
-{
- switch (blocktype) {
- case ID_CA:
- cur->xmin= (float)scene->r.sfra;
- cur->xmax= (float)scene->r.efra;
- cur->ymin= 0.0f;
- cur->ymax= 100.0f;
- break;
-
- case ID_MA: case ID_WO: case ID_LA:
- case ID_CU: case ID_CO:
- cur->xmin= (float)(scene->r.sfra - 0.1f);
- cur->xmax= (float)scene->r.efra;
- cur->ymin= (float)-0.1f;
- cur->ymax= (float)+1.1f;
- break;
+ if (icu->bezt) MEM_freeN(icu->bezt);
+ if (icu->bp) MEM_freeN(icu->bp);
+ if (icu->driver) MEM_freeN(icu->driver);
- case ID_TE:
- cur->xmin= (float)(scene->r.sfra - 0.1f);
- cur->xmax= (float)scene->r.efra;
- cur->ymin= (float)-0.1f;
- cur->ymax= (float)+1.1f;
- break;
-
- case ID_SEQ:
- cur->xmin= -5.0f;
- cur->xmax= 105.0f;
- cur->ymin= (float)-0.1f;
- cur->ymax= (float)+1.1f;
- break;
-
- case ID_KE:
- cur->xmin= (float)(scene->r.sfra - 0.1f);
- cur->xmax= (float)scene->r.efra;
- cur->ymin= (float)-0.1f;
- cur->ymax= (float)+2.1f;
- break;
-
- default: /* ID_OB and everything else */
- cur->xmin= (float)scene->r.sfra;
- cur->xmax= (float)scene->r.efra;
- cur->ymin= -5.0f;
- cur->ymax= +5.0f;
- break;
+ BLI_freelinkN(&ipo->curve, icu);
}
-}
-
-/* create a new IPO block (allocates the block) */
-Ipo *add_ipo (Scene *scene, char name[], int blocktype)
-{
- Ipo *ipo;
- ipo= alloc_libblock(&G.main->ipo, ID_IP, name);
- ipo->blocktype= blocktype;
- if(scene) ipo_default_v2d_cur(scene, blocktype, &ipo->cur);
-
- return ipo;
+ printf("Freed %d (Unconverted) Ipo-Curves from IPO '%s' \n", n, ipo->id.name+2);
}
-/* ---------------------- Copy --------------------------- */
+/* *************************************************** */
+/* ADRCODE to RNA-Path Conversion Code */
-/* duplicate an IPO block and all its data */
-Ipo *copy_ipo (Ipo *src)
+/* Object types */
+static char *ob_adrcodes_to_paths (int adrcode, int *array_index)
{
- Ipo *dst;
- IpoCurve *icu;
-
- if (src == NULL)
- return NULL;
+ /* set array index like this in-case nothing sets it correctly */
+ *array_index= 0;
- dst= copy_libblock(src);
- BLI_duplicatelist(&dst->curve, &src->curve);
-
- for (icu= src->curve.first; icu; icu= icu->next) {
- icu->bezt= MEM_dupallocN(icu->bezt);
+ /* result depends on adrcode */
+ switch (adrcode) {
+ case OB_LOC_X:
+ *array_index= 0; return "location";
+ case OB_LOC_Y:
+ *array_index= 1; return "location";
+ case OB_LOC_Z:
+ *array_index= 2; return "location";
+ case OB_DLOC_X:
+ *array_index= 0; return "delta_location";
+ case OB_DLOC_Y:
+ *array_index= 1; return "delta_location";
+ case OB_DLOC_Z:
+ *array_index= 2; return "delta_location";
- if (icu->driver)
- icu->driver= MEM_dupallocN(icu->driver);
+ case OB_ROT_X:
+ *array_index= 0; return "rotation";
+ case OB_ROT_Y:
+ *array_index= 1; return "rotation";
+ case OB_ROT_Z:
+ *array_index= 2; return "rotation";
+ case OB_DROT_X:
+ *array_index= 0; return "delta_rotation";
+ case OB_DROT_Y:
+ *array_index= 1; return "delta_rotation";
+ case OB_DROT_Z:
+ *array_index= 2; return "delta_rotation";
+
+ case OB_SIZE_X:
+ *array_index= 0; return "scale";
+ case OB_SIZE_Y:
+ *array_index= 1; return "scale";
+ case OB_SIZE_Z:
+ *array_index= 2; return "scale";
+ case OB_DSIZE_X:
+ *array_index= 0; return "delta_scale";
+ case OB_DSIZE_Y:
+ *array_index= 1; return "delta_scale";
+ case OB_DSIZE_Z:
+ *array_index= 2; return "delta_scale";
+
+#if 0
+ case OB_LAY: // XXX EVIL BITFLAG ALERT! this one will need special attention...
+ // poin= &(ob->lay); *type= IPO_INT_BIT; break;
+ return NULL;
+
+ case OB_COL_R:
+ poin= &(ob->col[0]); break;
+ case OB_COL_G:
+ poin= &(ob->col[1]); break;
+ case OB_COL_B:
+ poin= &(ob->col[2]); break;
+ case OB_COL_A:
+ poin= &(ob->col[3]); break;
+
+ case OB_PD_FSTR:
+ if (ob->pd) poin= &(ob->pd->f_strength);
+ break;
+ case OB_PD_FFALL:
+ if (ob->pd) poin= &(ob->pd->f_power);
+ break;
+ case OB_PD_SDAMP:
+ if (ob->pd) poin= &(ob->pd->pdef_damp);
+ break;
+ case OB_PD_RDAMP:
+ if (ob->pd) poin= &(ob->pd->pdef_rdamp);
+ break;
+ case OB_PD_PERM:
+ if (ob->pd) poin= &(ob->pd->pdef_perm);
+ break;
+ case OB_PD_FMAXD:
+ if (ob->pd) poin= &(ob->pd->maxdist);
+ break;
+#endif
}
- return dst;
-}
-
-/* ---------------------- Relink --------------------------- */
-
-/* uses id->newid to match pointers with other copied data
- * - called after single-user or other such
- */
-void ipo_idnew (Ipo *ipo)
-{
- if (ipo) {
- IpoCurve *icu;
-
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- if (icu->driver)
- ID_NEW(icu->driver->ob);
- }
- }
-}
-
-/* --------------------- Find + Check ----------------------- */
-
-/* find the IPO-curve within a given IPO-block with the adrcode of interest */
-IpoCurve *find_ipocurve (Ipo *ipo, int adrcode)
-{
- if (ipo) {
- IpoCurve *icu;
-
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- if (icu->adrcode == adrcode)
- return icu;
- }
- }
return NULL;
}
-/* return whether the given IPO block has a IPO-curve with the given adrcode */
-short has_ipo_code(Ipo *ipo, int adrcode)
-{
- /* return success of faliure from trying to find such an IPO-curve */
- return (find_ipocurve(ipo, adrcode) != NULL);
-}
-
-/* ---------------------- Make Local --------------------------- */
-
-
-/* make the given IPO local (for Objects)
- * - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
+/* PoseChannel types
+ * NOTE: pchan name comes from 'actname' added earlier...
*/
-void make_local_obipo (Ipo *src)
+static char *pchan_adrcodes_to_paths (int adrcode, int *array_index)
{
- Object *ob;
- Ipo *dst;
- int local=0, lib=0;
+ /* set array index like this in-case nothing sets it correctly */
+ *array_index= 0;
- /* check if only local and/or lib */
- for (ob= G.main->object.first; ob; ob= ob->id.next) {
- if (ob->ipo == src) {
- if (ob->id.lib) lib= 1;
- else local= 1;
- }
- }
-
- /* only local - set flag */
- if (local && lib==0) {
- src->id.lib= 0;
- src->id.flag= LIB_LOCAL;
- new_id(0, (ID *)src, 0);
- }
- /* mixed: make copy */
- else if (local && lib) {
- dst= copy_ipo(src);
- dst->id.us= 0;
+ /* result depends on adrcode */
+ switch (adrcode) {
+ case AC_QUAT_W:
+ *array_index= 0; return "rotation";
+ case AC_QUAT_X:
+ *array_index= 1; return "rotation";
+ case AC_QUAT_Y:
+ *array_index= 2; return "rotation";
+ case AC_QUAT_Z:
+ *array_index= 3; return "rotation";
+
+#if 0 // XXX these were not 'official' channels (i.e. not in bf-releases)... these will need separate wrapping to work...
+ case AC_EUL_X:
+ *array_index= 0; return "rotation";
+ case AC_EUL_Y:
+ *array_index= 1; return "rotation";
+ case AC_EUL_Z:
+ *array_index= 2; return "rotation";
+#endif
+ case -1: // XXX special case for rotation drivers... until eulers are added...
+ *array_index= 0; return "rotation";
+
+ case AC_LOC_X:
+ *array_index= 0; return "location";
+ case AC_LOC_Y:
+ *array_index= 1; return "location";
+ case AC_LOC_Z:
+ *array_index= 2; return "location";
- for (ob= G.main->object.first; ob; ob= ob->id.next) {
- if (ob->ipo == src) {
- if (ob->id.lib == NULL) {
- ob->ipo= dst;
- dst->id.us++;
- src->id.us--;
- }
- }
- }
- }
-}
-
-/* make the given IPO local (for Materials)
- * - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
- */
-void make_local_matipo (Ipo *src)
-{
- Material *ma;
- Ipo *dst;
- int local=0, lib=0;
-
- /* check if only local and/or lib */
- for (ma= G.main->mat.first; ma; ma= ma->id.next) {
- if (ma->ipo == src) {
- if (ma->id.lib) lib= 1;
- else local= 1;
- }
+ case AC_SIZE_X:
+ *array_index= 0; return "scale";
+ case AC_SIZE_Y:
+ *array_index= 1; return "scale";
+ case AC_SIZE_Z:
+ *array_index= 2; return "scale";
}
- /* only local - set flag */
- if (local && lib==0) {
- src->id.lib= 0;
- src->id.flag= LIB_LOCAL;
- new_id(0, (ID *)src, 0);
- }
- /* mixed: make copy */
- else if (local && lib) {
- dst= copy_ipo(src);
- dst->id.us= 0;
-
- for (ma= G.main->mat.first; ma; ma= ma->id.next) {
- if (ma->ipo == src) {
- if (ma->id.lib == NULL) {
- ma->ipo= dst;
- dst->id.us++;
- src->id.us--;
- }
- }
- }
- }
+ /* for debugging only */
+ printf("ERROR: unmatched PoseChannel setting (code %d) \n", adrcode);
+ return NULL;
}
-/* make the given IPO local (for ShapeKeys)
- * - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
+/* ShapeKey types
+ * NOTE: as we don't have access to the keyblock where the data comes from (for now),
+ * we'll just use numerical indicies for now...
*/
-void make_local_keyipo (Ipo *src)
+static char *shapekey_adrcodes_to_paths (int adrcode, int *array_index)
{
- Key *key;
- Ipo *dst;
- int local=0, lib=0;
-
- /* check if only local and/or lib */
- for (key= G.main->key.first; key; key= key->id.next) {
- if (key->ipo == src) {
- if (key->id.lib) lib= 1;
- else local= 1;
- }
- }
+ static char buf[128];
- /* only local - set flag */
- if (local && lib==0) {
- src->id.lib= 0;
- src->id.flag= LIB_LOCAL;
- new_id(0, (ID *)src, 0);
- }
- /* mixed: make copy */
- else if (local && lib) {
- dst= copy_ipo(src);
- dst->id.us= 0;
-
- for (key= G.main->key.first; key; key= key->id.next) {
- if (key->ipo == src) {
- if (key->id.lib == NULL) {
- key->ipo= dst;
- dst->id.us++;
- src->id.us--;
- }
- }
- }
- }
+ /* block will be attached to ID_KE block, and setting that we alter is the 'value' (which sets keyblock.curval) */
+ // XXX adrcode 0 was dummy 'speed' curve
+ sprintf(buf, "keys[%d].value", adrcode-1); // XXX this doesn't seem too safe...
+ return buf;
}
+/* ------- */
-/* generic call to make IPO's local */
-void make_local_ipo (Ipo *ipo)
+/* Allocate memory for RNA-path for some property given a blocktype, adrcode, and 'root' parts of path
+ * Input:
+ * - blocktype, adrcode - determines setting to get
+ * - actname, constname - used to build path
+ * Output:
+ * - array_index - index in property's array (if applicable) to use
+ * - return - the allocated path...
+ */
+char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index)
{
- /* can't touch lib-linked data */
- if (ipo->id.lib == NULL)
- return;
-
- /* with only one user, just set local flag */
- if (ipo->id.us == 1) {
- ipo->id.lib= 0;
- ipo->id.flag= LIB_LOCAL;
- new_id(0, (ID *)ipo, 0);
- return;
- }
+ DynStr *path= BLI_dynstr_new();
+ char *propname=NULL, *rpath=NULL;
+ char buf[512];
+ int dummy_index= 0;
- /* when more than 1 user, can only make local for certain blocktypes */
- switch (ipo->blocktype) {
- case ID_OB:
- make_local_obipo(ipo);
+ /* get property name based on blocktype */
+ switch (blocktype) {
+ case ID_OB: /* object */
+ propname= ob_adrcodes_to_paths(adrcode, &dummy_index);
break;
- case ID_MA:
- make_local_matipo(ipo);
+
+ case ID_PO: /* pose channel */
+ propname= pchan_adrcodes_to_paths(adrcode, &dummy_index);
break;
- case ID_KE:
- make_local_keyipo(ipo);
+
+ case ID_KE: /* shapekeys */
+ propname= shapekey_adrcodes_to_paths(adrcode, &dummy_index);
break;
- }
-}
-
-/* ***************************** Keyframe Column Tools ********************************* */
-
-/* add a BezTriple to a column */
-void add_to_cfra_elem(ListBase *lb, BezTriple *bezt)
-{
- CfraElem *ce, *cen;
-
- for (ce= lb->first; ce; ce= ce->next) {
- /* double key? */
- if (ce->cfra == bezt->vec[1][0]) {
- if (bezt->f2 & SELECT) ce->sel= bezt->f2;
- return;
- }
- /* should key be inserted before this column? */
- else if (ce->cfra > bezt->vec[1][0]) break;
- }
-
- /* create a new column */
- cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
- if (ce) BLI_insertlinkbefore(lb, ce, cen);
- else BLI_addtail(lb, cen);
-
- cen->cfra= bezt->vec[1][0];
- cen->sel= bezt->f2;
-}
-
-/* make a list of keyframe 'columns' in an IPO block */
-void make_cfra_list (Ipo *ipo, ListBase *elems)
-{
- IpoCurve *icu;
- BezTriple *bezt;
- int a;
-
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- if (icu->flag & IPO_VISIBLE) {
- /* ... removed old checks for adrcode types from here ...
- * - (was this used for IpoKeys in the past?)
- */
- bezt= icu->bezt;
- if (bezt) {
- for (a=0; a < icu->totvert; a++, bezt++) {
- add_to_cfra_elem(elems, bezt);
- }
- }
- }
+ /* XXX problematic blocktypes */
+ case ID_CU:
+ propname= "speed"; // XXX this was a 'dummy curve' that didn't really correspond to any real var...
+ break;
+
+ case ID_SEQ:
+ //SEQ_FAC1:
+ // poin= &(seq->facf0); // XXX this doesn't seem to be included anywhere in sequencer RNA...
+ break;
+
+ /* special hacks */
+ case -1:
+ /* special case for rotdiff drivers... we don't need a property for this... */
+ break;
+
+ // TODO... add other blocktypes...
+ default:
+ printf("IPO2ANIMATO WARNING: No path for blocktype %d, adrcode %d yet \n", blocktype, adrcode);
+ break;
}
-}
-
-/* ***************************** Timing Stuff ********************************* */
-
-/* This (evil) function is needed to cope with two legacy Blender rendering features
- * mblur (motion blur that renders 'subframes' and blurs them together), and fields
- * rendering. Thus, the use of ugly globals from object.c
- */
-// BAD... EVIL... JUJU...!!!!
-float frame_to_float (Scene *scene, int cfra) /* see also bsystem_time in object.c */
-{
- extern float bluroffs; /* bad stuff borrowed from object.c */
- extern float fieldoffs;
- float ctime;
- ctime= (float)cfra;
- ctime+= bluroffs+fieldoffs;
- ctime*= scene->r.framelen;
-
- return ctime;
-}
-
-/* Calculate the extents of IPO block's keyframes */
-void calc_ipo_range (Ipo *ipo, float *start, float *end)
-{
- IpoCurve *icu;
- float min=999999999.0f, max=-999999999.0f;
- short foundvert=0;
-
- if (ipo) {
- for (icu=ipo->curve.first; icu; icu=icu->next) {
- if (icu->totvert) {
- min= MIN2(min, icu->bezt[0].vec[1][0]);
- max= MAX2(max, icu->bezt[icu->totvert-1].vec[1][0]);
- foundvert=1;
- }
- }
- }
-
- /* minimum length is 1 frame */
- if (foundvert) {
- if (min == max) max += 1.0f;
- *start= min;
- *end= max;
- }
- else {
- *start= 0.0f;
- *end= 1.0f;
- }
-}
-
-/* ***************************** IPO Curve Sanity ********************************* */
-/* The functions here are used in various parts of Blender, usually after some editing
- * of keyframe data has occurred. They ensure that keyframe data is properly ordered and
- * that the handles are correctly
- */
-
-/* This function recalculates the handles of an IPO-Curve
- * If the BezTriples have been rearranged, sort them first before using this.
- */
-void calchandles_ipocurve (IpoCurve *icu)
-{
- BezTriple *bezt, *prev, *next;
- int a= icu->totvert;
-
- /* Error checking:
- * - need at least two points
- * - need bezier keys
- * - only bezier-interpolation has handles (for now)
+ /* check if any property found
+ * - blocktype < 0 is special case for a specific type of driver, where we don't need a property name...
*/
- if (ELEM(NULL, icu, icu->bezt) || (a < 2) || ELEM(icu->ipo, IPO_CONST, IPO_LIN))
- return;
-
- /* get initial pointers */
- bezt= icu->bezt;
- prev= NULL;
- next= (bezt + 1);
-
- /* loop over all beztriples, adjusting handles */
- while (a--) {
- /* clamp timing of handles to be on either side of beztriple */
- if (bezt->vec[0][0] > bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
- if (bezt->vec[2][0] < bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
-
- /* calculate autohandles */
- if (icu->flag & IPO_AUTO_HORIZ)
- calchandleNurb(bezt, prev, next, 2); /* 2==special autohandle && keep extrema horizontal */
- else
- calchandleNurb(bezt, prev, next, 1); /* 1==special autohandle */
-
- /* for automatic ease in and out */
- if ((bezt->h1==HD_AUTO) && (bezt->h2==HD_AUTO)) {
- /* only do this on first or last beztriple */
- if ((a==0) || (a==icu->totvert-1)) {
- /* set both handles to have same horizontal value as keyframe */
- if (icu->extrap==IPO_HORIZ) {
- bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
- }
- }
- }
+ if ((propname == NULL) && (blocktype > 0)) {
+ /* nothing was found, so exit */
+ if (array_index)
+ *array_index= 0;
+
+ BLI_dynstr_free(path);
- /* advance pointers for next iteration */
- prev= bezt;
- if (a == 1) next= NULL;
- else next++;
- bezt++;
+ return NULL;
}
-}
-
-/* Use when IPO-Curve with handles has changed
- * It treats all BezTriples with the following rules:
- * - PHASE 1: do types have to be altered?
- * -> Auto handles: become aligned when selection status is NOT(000 || 111)
- * -> Vector handles: become 'nothing' when (one half selected AND other not)
- * - PHASE 2: recalculate handles
-*/
-void testhandles_ipocurve (IpoCurve *icu)
-{
- BezTriple *bezt;
- int a;
-
- /* only beztriples have handles (bpoints don't though) */
- if (ELEM(NULL, icu, icu->bezt))
- return;
-
- /* loop over beztriples */
- for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
- short flag= 0;
-
- /* flag is initialised as selection status
- * of beztriple control-points (labelled 0,1,2)
- */
- if (bezt->f1 & SELECT) flag |= (1<<0); // == 1
- if (bezt->f2 & SELECT) flag |= (1<<1); // == 2
- if (bezt->f3 & SELECT) flag |= (1<<2); // == 4
-
- /* one or two handles selected only */
- if (ELEM(flag, 0, 7)==0) {
- /* auto handles become aligned */
- if (bezt->h1==HD_AUTO)
- bezt->h1= HD_ALIGN;
- if(bezt->h2==HD_AUTO)
- bezt->h2= HD_ALIGN;
-
- /* vector handles become 'free' when only one half selected */
- if(bezt->h1==HD_VECT) {
- /* only left half (1 or 2 or 1+2) */
- if (flag < 4)
- bezt->h1= 0;
- }
- if(bezt->h2==HD_VECT) {
- /* only right half (4 or 2+4) */
- if (flag > 3)
- bezt->h2= 0;
- }
- }
+ else {
+ if (array_index)
+ *array_index= dummy_index;
}
-
- /* recalculate handles */
- calchandles_ipocurve(icu);
-}
-
-/* This function sorts BezTriples so that they are arranged in chronological order,
- * as tools working on IPO-Curves expect that the BezTriples are in order.
- */
-void sort_time_ipocurve(IpoCurve *icu)
-{
- short ok= 1;
- /* keep adjusting order of beztriples until nothing moves (bubble-sort) */
- while (ok) {
- ok= 0;
-
- /* currently, will only be needed when there are beztriples */
- if (icu->bezt) {
- BezTriple *bezt;
- int a;
-
- /* loop over ALL points to adjust position in array and recalculate handles */
- for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
- /* check if thee's a next beztriple which we could try to swap with current */
- if (a < (icu->totvert-1)) {
- /* swap if one is after the other (and indicate that order has changed) */
- if (bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
- SWAP(BezTriple, *bezt, *(bezt+1));
- ok= 1;
- }
-
- /* if either one of both of the points exceeds crosses over the keyframe time... */
- if ( (bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0]) ) {
- /* swap handles if they have switched sides for some reason */
- SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
- SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
- }
- else {
- /* clamp handles */
- if (bezt->vec[0][0] > bezt->vec[1][0])
- bezt->vec[0][0]= bezt->vec[1][0];
- if (bezt->vec[2][0] < bezt->vec[1][0])
- bezt->vec[2][0]= bezt->vec[1][0];
- }
- }
- }
- }
+ /* append preceeding bits to path */
+ if ((actname && actname[0]) && (constname && constname[0])) {
+ /* Constraint in Pose-Channel */
+ sprintf(buf, "pose.pose_channels[\"%s\"].constraints[\"%s\"]", actname, constname);
}
-}
-
-/* This function tests if any BezTriples are out of order, thus requiring a sort */
-int test_time_ipocurve (IpoCurve *icu)
-{
- int a;
-
- /* currently, only need to test beztriples */
- if (icu->bezt) {
- BezTriple *bezt;
-
- /* loop through all beztriples, stopping when one exceeds the one after it */
- for (a=0, bezt= icu->bezt; a < (icu->totvert - 1); a++, bezt++) {
- if (bezt->vec[1][0] > (bezt+1)->vec[1][0])
- return 1;
- }
+ else if (actname && actname[0]) {
+ /* Pose-Channel */
+ sprintf(buf, "pose.pose_channels[\"%s\"]", actname);
}
-
- /* none need any swapping */
- return 0;
-}
-
-/* --------- */
-
-/* The total length of the handles is not allowed to be more
- * than the horizontal distance between (v1-v4).
- * This is to prevent curve loops.
-*/
-void correct_bezpart (float *v1, float *v2, float *v3, float *v4)
-{
- float h1[2], h2[2], len1, len2, len, fac;
-
- /* calculate handle deltas */
- h1[0]= v1[0]-v2[0];
- h1[1]= v1[1]-v2[1];
- h2[0]= v4[0]-v3[0];
- h2[1]= v4[1]-v3[1];
-
- /* calculate distances:
- * - len = span of time between keyframes
- * - len1 = length of handle of start key
- * - len2 = length of handle of end key
- */
- len= v4[0]- v1[0];
- len1= (float)fabs(h1[0]);
- len2= (float)fabs(h2[0]);
-
- /* if the handles have no length, no need to do any corrections */
- if ((len1+len2) == 0.0)
- return;
-
- /* the two handles cross over each other, so force them
- * apart using the proportion they overlap
- */
- if ((len1+len2) > len) {
- fac= len/(len1+len2);
-
- v2[0]= (v1[0]-fac*h1[0]);
- v2[1]= (v1[1]-fac*h1[1]);
+ else if (constname && constname[0]) {
+ /* Constraint in Object */
+ sprintf(buf, "constraints[\"%s\"]", constname);
+ }
+ else
+ strcpy(buf, ""); /* empty string */
+ BLI_dynstr_append(path, buf);
+
+ /* append property to path (only if applicable) */
+ if (blocktype > 0) {
+ /* need to add dot before property if there was anything precceding this */
+ if (buf[0])
+ BLI_dynstr_append(path, ".");
- v3[0]= (v4[0]-fac*h2[0]);
- v3[1]= (v4[1]-fac*h2[1]);
+ /* now write name of property */
+ BLI_dynstr_append(path, propname);
}
-}
-
-/* This function sets the interpolation mode for an entire Ipo-Curve.
- * It is primarily used for patching old files, but is also used in the interface
- * to make sure that all segments of the curve use the same interpolation.
- */
-// XXX move to readfile.c for patching old files only..
-void set_interpolation_ipocurve (IpoCurve *icu, short ipo)
-{
- BezTriple *bezt;
- int a;
- /* validate arguments */
- if (icu == NULL) return;
- if (ELEM3(ipo, IPO_CONST, IPO_LIN, IPO_BEZ)==0) return;
-
- /* set interpolation mode for whole curve */
- icu->ipo= ipo;
+ /* convert to normal MEM_malloc'd string */
+ rpath= BLI_dynstr_get_cstring(path);
+ BLI_dynstr_free(path);
- /* set interpolation mode of all beztriples */
- for (a=0, bezt=icu->bezt; a<icu->totvert; a++, bezt++)
- bezt->ipo= ipo;
+ /* return path... */
+ return rpath;
}
-/* ***************************** Curve Calculations ********************************* */
+/* *************************************************** */
+/* Conversion Utilities */
-/* find root/zero */
-int findzero (float x, float q0, float q1, float q2, float q3, float *o)
+/* Convert IpoDriver to ChannelDriver - will free the old data (i.e. the old driver) */
+static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
{
- double c0, c1, c2, c3, a, b, c, p, q, d, t, phi;
- int nr= 0;
-
- c0= q0 - x;
- c1= 3 * (q1 - q0);
- c2= 3 * (q0 - 2*q1 + q2);
- c3= q3 - q0 + 3 * (q1 - q2);
+ ChannelDriver *cdriver;
- if (c3 != 0.0) {
- a= c2/c3;
- b= c1/c3;
- c= c0/c3;
- a= a/3;
-
- p= b/3 - a*a;
- q= (2*a*a*a - a*b + c) / 2;
- d= q*q + p*p*p;
-
- if (d > 0.0) {
- t= sqrt(d);
- o[0]= (float)(Sqrt3d(-q+t) + Sqrt3d(-q-t) - a);
-
- if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
- else return 0;
- }
- else if (d == 0.0) {
- t= Sqrt3d(-q);
- o[0]= (float)(2*t - a);
-
- if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
- o[nr]= (float)(-t-a);
-
- if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
- else return nr;
- }
- else {
- phi= acos(-q / sqrt(-(p*p*p)));
- t= sqrt(-p);
- p= cos(phi/3);
- q= sqrt(3 - 3*p*p);
- o[0]= (float)(2*t*p - a);
-
- if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
- o[nr]= (float)(-t * (p + q) - a);
-
- if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) nr++;
- o[nr]= (float)(-t * (p - q) - a);
-
- if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
- else return nr;
- }
+ /* allocate memory for new driver */
+ cdriver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
+
+ /* if 'pydriver', just copy data across */
+ if (idriver->type == IPO_DRIVER_TYPE_PYTHON) {
+ /* PyDriver only requires the expression to be copied */
+ cdriver->type = DRIVER_TYPE_PYTHON;
+ strcpy(cdriver->expression, idriver->name); // XXX is this safe?
}
else {
- a=c2;
- b=c1;
- c=c0;
-
- if (a != 0.0) {
- // discriminant
- p= b*b - 4*a*c;
-
- if (p > 0) {
- p= sqrt(p);
- o[0]= (float)((-b-p) / (2 * a));
+ /* what to store depends on the 'blocktype' (ID_OB or ID_PO - object or posechannel) */
+ if (idriver->blocktype == ID_AR) {
+ /* ID_PO */
+ if (idriver->adrcode == OB_ROT_DIFF) {
+ /* Rotational Difference is a special type of driver now... */
+ cdriver->type= DRIVER_TYPE_ROTDIFF;
- if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
- o[nr]= (float)((-b+p)/(2*a));
+ /* driver must use bones from same armature... */
+ cdriver->id= cdriver->id2= (ID *)idriver->ob;
- if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
- else return nr;
- }
- else if (p == 0) {
- o[0]= (float)(-b / (2 * a));
- if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
- else return 0;
- }
- }
- else if (b != 0.0) {
- o[0]= (float)(-c/b);
-
- if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
- else return 0;
- }
- else if (c == 0.0) {
- o[0]= 0.0;
- return 1;
- }
-
- return 0;
- }
-}
-
-void berekeny (float f1, float f2, float f3, float f4, float *o, int b)
-{
- float t, c0, c1, c2, c3;
- int a;
-
- c0= f1;
- c1= 3.0f * (f2 - f1);
- c2= 3.0f * (f1 - 2.0f*f2 + f3);
- c3= f4 - f1 + 3.0f * (f2 - f3);
-
- for (a=0; a < b; a++) {
- t= o[a];
- o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
- }
-}
-
-void berekenx (float *f, float *o, int b)
-{
- float t, c0, c1, c2, c3;
- int a;
-
- c0= f[0];
- c1= 3 * (f[3] - f[0]);
- c2= 3 * (f[0] - 2*f[3] + f[6]);
- c3= f[9] - f[0] + 3 * (f[3] - f[6]);
-
- for (a=0; a < b; a++) {
- t= o[a];
- o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
- }
-}
-
-/* ***************************** IPO - Calculations ********************************* */
-
-/* ---------------------- Curve Evaluation --------------------------- */
-
-/* helper function for evaluating drivers:
- * - we need the local transform = current transform - (parent transform + bone transform)
- * - (local transform is on action channel level)
- */
-static void posechannel_get_local_transform (bPoseChannel *pchan, float loc[], float eul[], float size[])
-{
- float parmat[4][4], offs_bone[4][4], imat[4][4];
- float diff_mat[4][4];
-
- /* get first the parent + bone transform in parmat */
- if (pchan->parent) {
- /* bone transform itself */
- Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
-
- /* The bone's root offset (is in the parent's coordinate system) */
- VECCOPY(offs_bone[3], pchan->bone->head);
-
- /* Get the length translation of parent (length along y axis) */
- offs_bone[3][1]+= pchan->parent->bone->length;
-
- Mat4MulSerie(parmat, pchan->parent->pose_mat, offs_bone, NULL, NULL, NULL, NULL, NULL, NULL);
-
- /* invert it */
- Mat4Invert(imat, parmat);
- }
- else {
- Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
- VECCOPY(offs_bone[3], pchan->bone->head);
-
- /* invert it */
- Mat4Invert(imat, offs_bone);
- }
-
- /* difference: current transform - (parent transform + bone transform) */
- Mat4MulMat4(diff_mat, pchan->pose_mat, imat);
-
- /* extract relevant components */
- if (loc)
- VECCOPY(loc, diff_mat[3]);
- if (eul)
- Mat4ToEul(diff_mat, eul);
- if (size)
- Mat4ToSize(diff_mat, size);
-}
-
-/* evaluate an IPO-driver to get a 'time' value to use instead of "ipotime"
- * - "ipotime" is the frame at which IPO-curve is being evaluated
- * - has to return a float value
- */
-static float eval_driver (IpoDriver *driver, float ipotime)
-{
-#ifndef DISABLE_PYTHON
- /* currently, drivers are either PyDrivers (evaluating a PyExpression, or Object/Pose-Channel transforms) */
- if (driver->type == IPO_DRIVER_TYPE_PYTHON) {
- /* check for empty or invalid expression */
- if ( (driver->name[0] == '\0') ||
- (driver->flag & IPO_DRIVER_FLAG_INVALID) )
- {
- return 0.0f;
- }
-
- /* this evaluates the expression using Python,and returns its result:
- * - on errors it reports, then returns 0.0f
- */
- return BPY_pydriver_eval(driver);
- }
- else
-#endif /* DISABLE_PYTHON */
- {
- Object *ob= driver->ob;
-
- /* must have an object to evaluate */
- if (ob == NULL)
- return 0.0f;
-
- /* if a proxy, use the proxy source*/
- if (ob->proxy_from)
- ob= ob->proxy_from;
-
- /* use given object as driver */
- if (driver->blocktype == ID_OB) {
- /* depsgraph failure: ob ipos are calculated in where_is_object, this might get called too late */
- if ((ob->ipo) && (ob->ctime != ipotime)) {
- /* calculate the value of relevant channel on the Object, but do not write the value
- * calculated on to the Object but onto "ipotime" instead
+ /* paths for the two targets get the pointers to the relevant Pose-Channels
+ * - return pointers to Pose-Channels not rotation channels, as calculation code is picky
+ * - old bone names were stored in same var, in idriver->name
+ *
+ * - we use several hacks here - blocktype == -1 specifies that no property needs to be found, and
+ * providing a name for 'actname' will automatically imply Pose-Channel with name 'actname'
*/
- calc_ipo_spec(ob->ipo, driver->adrcode, &ipotime);
- return ipotime;
+ cdriver->rna_path= get_rna_access(-1, -1, idriver->name, NULL, NULL);
+ cdriver->rna_path2= get_rna_access(-1, -1, idriver->name+DRIVER_NAME_OFFS, NULL, NULL);
}
-
- /* return the value of the relevant channel */
- switch (driver->adrcode) {
- case OB_LOC_X:
- return ob->loc[0];
- case OB_LOC_Y:
- return ob->loc[1];
- case OB_LOC_Z:
- return ob->loc[2];
- case OB_ROT_X: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */
- return (float)( ob->rot[0]/(M_PI_2/9.0) );
- case OB_ROT_Y: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */
- return (float)( ob->rot[1]/(M_PI_2/9.0) );
- case OB_ROT_Z: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */
- return (float)( ob->rot[2]/(M_PI_2/9.0) );
- case OB_SIZE_X:
- return ob->size[0];
- case OB_SIZE_Y:
- return ob->size[1];
- case OB_SIZE_Z:
- return ob->size[2];
- }
- }
-
- /* use given pose-channel as driver */
- else { /* ID_AR */
- bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name);
-
- /* must have at least 1 bone to use */
- if (pchan && pchan->bone) {
- /* rotation difference is not a simple driver (i.e. value drives value), but the angle between 2 bones is driving stuff...
- * - the name of the second pchan is also stored in driver->name, but packed after the other one by DRIVER_NAME_OFFS chars
- */
- if (driver->adrcode == OB_ROT_DIFF) {
- bPoseChannel *pchan2= get_pose_channel(ob->pose, driver->name+DRIVER_NAME_OFFS);
-
- if (pchan2 && pchan2->bone) {
- float q1[4], q2[4], quat[4], angle;
-
- Mat4ToQuat(pchan->pose_mat, q1);
- Mat4ToQuat(pchan2->pose_mat, q2);
-
- QuatInv(q1);
- QuatMul(quat, q1, q2);
- angle = 2.0f * (saacos(quat[0]));
- angle= ABS(angle);
-
- return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle);
- }
- }
+ else {
+ /* 'standard' driver */
+ cdriver->type= DRIVER_TYPE_CHANNEL;
+ cdriver->id= (ID *)idriver->ob;
- /* standard driver */
- else {
- float loc[3], eul[3], size[3];
-
- /* retrieve local transforms to return
- * - we use eulers here NOT quats, so that Objects can be driven by bones easily
- * also, this way is more understandable for users
- */
- posechannel_get_local_transform(pchan, loc, eul, size);
-
- switch (driver->adrcode) {
- case OB_LOC_X:
- return loc[0];
+ switch (idriver->adrcode) {
+ case OB_LOC_X: /* x,y,z location are quite straightforward */
+ cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_X, idriver->name, NULL, &cdriver->array_index);
+ break;
case OB_LOC_Y:
- return loc[1];
+ cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_Y, idriver->name, NULL, &cdriver->array_index);
+ break;
case OB_LOC_Z:
- return loc[2];
- case OB_ROT_X: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */
- return (float)( eul[0]/(M_PI_2/9.0) );
- case OB_ROT_Y: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */
- return (float)( eul[1]/(M_PI_2/9.0) );
- case OB_ROT_Z: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */
- return (float)( eul[2]/(M_PI_2/9.0) );
- case OB_SIZE_X:
- return size[0];
+ cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_Z, idriver->name, NULL, &cdriver->array_index);
+ break;
+
+ case OB_SIZE_X: /* x,y,z scaling are also quite straightforward */
+ cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_X, idriver->name, NULL, &cdriver->array_index);
+ break;
case OB_SIZE_Y:
- return size[1];
+ cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_Y, idriver->name, NULL, &cdriver->array_index);
+ break;
case OB_SIZE_Z:
- return size[2];
+ cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_Z, idriver->name, NULL, &cdriver->array_index);
+ break;
+
+ case OB_ROT_X: /* rotation - we need to be careful with this... XXX (another reason why we need eulers) */
+ case OB_ROT_Y:
+ case OB_ROT_Z:
+ {
+ // XXX this is not yet a 1:1 map, since we'd need euler rotations to make this work nicely (unless we make some hacks)
+ // XXX -1 here is a special hack...
+ cdriver->rna_path= get_rna_access(ID_PO, -1, idriver->name, NULL, NULL);
+ cdriver->array_index= idriver->adrcode - OB_ROT_X;
}
+ break;
}
}
}
- }
+ else {
+ /* ID_OB */
+ cdriver->type= DRIVER_TYPE_CHANNEL;
+ cdriver->id= (ID *)idriver->ob;
+ cdriver->rna_path= get_rna_access(ID_OB, idriver->adrcode, idriver->name, NULL, &cdriver->array_index);
+ }
+ }
- /* return 0.0f, as couldn't find relevant data to use */
- return 0.0f;
+ /* free old driver */
+ MEM_freeN(idriver);
+
+ /* return the new one */
+ return cdriver;
}
-/* evaluate and return the value of the given IPO-curve at the specified frame ("evaltime") */
-float eval_icu (IpoCurve *icu, float evaltime)
+/* Convert IPO-Curve to F-Curve (including Driver data), and free any of the old data that
+ * is not relevant, BUT do not free the IPO-Curve itself...
+ * actname: name of Action-Channel (if applicable) that IPO-Curve's IPO-block belonged to
+ * constname: name of Constraint-Channel (if applicable) that IPO-Curve's IPO-block belonged to
+ */
+static FCurve *icu_to_fcu (IpoCurve *icu, char *actname, char *constname)
{
- float cvalue = 0.0f;
+ FCurve *fcu;
+ int i= 0;
- /* if there is a driver, evaluate it to find value to use as "evaltime"
- * - this value will also be returned as the value of the 'curve', if there are no keyframes
- */
+ /* allocate memory for a new F-Curve */
+ fcu= MEM_callocN(sizeof(FCurve), "FCurve");
+
+ /* convert driver - will free the old one... */
if (icu->driver) {
- /* ipotime now serves as input for the curve */
- evaltime= cvalue= eval_driver(icu->driver, evaltime);
+ fcu->driver= idriver_to_cdriver(icu->driver);
+ icu->driver= NULL;
}
- /* there are keyframes (in the form of BezTriples) which can be interpolated between */
+ /* convert keyframes
+ * - beztriples and bpoints are mutually exclusive, so we won't have both at the same time
+ * - beztriples are more likely to be encountered as they are keyframes (the other type wasn't used yet)
+ */
+ // XXX we need to cope with the nasty old 'bitflag' curves... that will be a task for later
+ fcu->totvert= icu->totvert;
+
if (icu->bezt) {
- /* get pointers */
- BezTriple *bezt, *prevbezt, *lastbezt;
- float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
- float cycdx, cycdy, ofs, cycyofs= 0.0f;
- int a, b;
+ /* allocate new array for keyframes/beztriples */
+ fcu->bezt= MEM_callocN(sizeof(BezTriple)*fcu->totvert, "BezTriples");
- /* get pointers */
- a= icu->totvert-1;
- prevbezt= icu->bezt;
- bezt= prevbezt+1;
- lastbezt= prevbezt + a;
-
- /* extrapolation mode is 'cyclic' - find relative place within a cycle */
- if (icu->extrap & IPO_CYCL) {
- /* ofs is start frame of cycle */
- ofs= prevbezt->vec[1][0];
-
- /* calculate period and amplitude (total height) of a cycle */
- cycdx= lastbezt->vec[1][0] - prevbezt->vec[1][0];
- cycdy= lastbezt->vec[1][1] - prevbezt->vec[1][1];
+ /* check if we need to set interpolation settings (thus doing it the 'slow' way) */
+ if (icu->ipo != IPO_MIXED) {
+ BezTriple *dst, *src;
- /* cycle occurs over some period of time (cycdx should be positive all the time) */
- if (cycdx) {
- /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle
- * - IPO_CYCLX = (IPO_CYCL + IPO_DIR)
- */
- if (icu->extrap & IPO_DIR) {
- cycyofs = (float)floor((evaltime - ofs) / cycdx);
- cycyofs *= cycdy;
- }
+ /* loop through copying all BezTriples, as we need to set interpolation settings too */
+ for (dst=fcu->bezt, src=icu->bezt; i < fcu->totvert; i++, dst++, src++) {
+ /* firstly, copy BezTriple data */
+ *dst= *src;
- /* calculate where in the cycle we are (overwrite evaltime to reflect this) */
- evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
- if (evaltime < ofs) evaltime += cycdx;
- }
- }
-
- /* evaluation time at or past endpoints? */
- if (prevbezt->vec[1][0] >= evaltime) {
- /* before or on first keyframe */
- if ((icu->extrap & IPO_DIR) && (prevbezt->ipo != IPO_CONST)) {
- /* linear or bezier interpolation */
- if (prevbezt->ipo==IPO_LIN) {
- /* Use the next center point instead of our own handle for
- * linear interpolated extrapolate
- */
- if (icu->totvert == 1)
- cvalue= prevbezt->vec[1][1];
- else {
- bezt = prevbezt+1;
- dx= prevbezt->vec[1][0] - evaltime;
- fac= bezt->vec[1][0] - prevbezt->vec[1][0];
-
- /* prevent division by zero */
- if (fac) {
- fac= (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac;
- cvalue= prevbezt->vec[1][1] - (fac * dx);
- }
- else
- cvalue= prevbezt->vec[1][1];
- }
- }
- else {
- /* Use the first handle (earlier) of first BezTriple to calculate the
- * gradient and thus the value of the curve at evaltime
- */
- dx= prevbezt->vec[1][0] - evaltime;
- fac= prevbezt->vec[1][0] - prevbezt->vec[0][0];
-
- /* prevent division by zero */
- if (fac) {
- fac= (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac;
- cvalue= prevbezt->vec[1][1] - (fac * dx);
- }
- else
- cvalue= prevbezt->vec[1][1];
- }
- }
- else {
- /* constant (IPO_HORIZ) extrapolation or constant interpolation,
- * so just extend first keyframe's value
- */
- cvalue= prevbezt->vec[1][1];
- }
- }
- else if (lastbezt->vec[1][0] <= evaltime) {
- /* after or on last keyframe */
- if( (icu->extrap & IPO_DIR) && (lastbezt->ipo != IPO_CONST)) {
- /* linear or bezier interpolation */
- if (lastbezt->ipo==IPO_LIN) {
- /* Use the next center point instead of our own handle for
- * linear interpolated extrapolate
- */
- if (icu->totvert == 1)
- cvalue= lastbezt->vec[1][1];
- else {
- prevbezt = lastbezt - 1;
- dx= evaltime - lastbezt->vec[1][0];
- fac= lastbezt->vec[1][0] - prevbezt->vec[1][0];
-
- /* prevent division by zero */
- if (fac) {
- fac= (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac;
- cvalue= lastbezt->vec[1][1] + (fac * dx);
- }
- else
- cvalue= lastbezt->vec[1][1];
- }
- }
- else {
- /* Use the gradient of the second handle (later) of last BezTriple to calculate the
- * gradient and thus the value of the curve at evaltime
- */
- dx= evaltime - lastbezt->vec[1][0];
- fac= lastbezt->vec[2][0] - lastbezt->vec[1][0];
-
- /* prevent division by zero */
- if (fac) {
- fac= (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac;
- cvalue= lastbezt->vec[1][1] + (fac * dx);
- }
- else
- cvalue= lastbezt->vec[1][1];
- }
- }
- else {
- /* constant (IPO_HORIZ) extrapolation or constant interpolation,
- * so just extend last keyframe's value
- */
- cvalue= lastbezt->vec[1][1];
+ /* now copy interpolation from curve */
+ dst->ipo= icu->ipo;
}
}
else {
- /* evaltime occurs somewhere in the middle of the curve */
- for (a=0; prevbezt && bezt && (a < icu->totvert-1); a++, prevbezt=bezt, bezt++) {
- /* evaltime occurs within the interval defined by these two keyframes */
- if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) {
- /* value depends on interpolation mode */
- if (prevbezt->ipo == IPO_CONST) {
- /* constant (evaltime not relevant, so no interpolation needed) */
- cvalue= prevbezt->vec[1][1];
- }
- else if (prevbezt->ipo == IPO_LIN) {
- /* linear - interpolate between values of the two keyframes */
- fac= bezt->vec[1][0] - prevbezt->vec[1][0];
-
- /* prevent division by zero */
- if (fac) {
- fac= (evaltime - prevbezt->vec[1][0]) / fac;
- cvalue= prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1]));
- }
- else
- cvalue= prevbezt->vec[1][1];
- }
- else {
- /* bezier interpolation */
- /* v1,v2 are the first keyframe and its 2nd handle */
- v1[0]= prevbezt->vec[1][0];
- v1[1]= prevbezt->vec[1][1];
- v2[0]= prevbezt->vec[2][0];
- v2[1]= prevbezt->vec[2][1];
- /* v3,v4 are the last keyframe's 1st handle + the last keyframe */
- v3[0]= bezt->vec[0][0];
- v3[1]= bezt->vec[0][1];
- v4[0]= bezt->vec[1][0];
- v4[1]= bezt->vec[1][1];
-
- /* adjust handles so that they don't overlap (forming a loop) */
- correct_bezpart(v1, v2, v3, v4);
-
- /* try to get a value for this position - if failure, try another set of points */
- b= findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl);
- if (b) {
- berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
- cvalue= opl[0];
- break;
- }
- }
- }
- }
+ /* interpolation already set (from AnimSys2 branch) */
+ memcpy(fcu->bezt, icu->bezt, sizeof(BezTriple)*fcu->totvert);
}
-
- /* apply y-offset (for 'cyclic extrapolation') to calculated value */
- cvalue += cycyofs;
}
-
- /* clamp evaluated value to lie within allowable value range for this channel */
- if (icu->ymin < icu->ymax) {
- CLAMP(cvalue, icu->ymin, icu->ymax);
+ else if (icu->bp) {
+ /* TODO: need to convert from BPoint type to the more compact FPoint type... but not priority, since no data used this */
+ //BPoint *bp;
+ //FPoint *fpt;
}
- /* return evaluated value */
- return cvalue;
-}
-
-/* ------------------- IPO-Block/Curve Calculation - General API ----------------------- */
-
-/* calculate the value of the given IPO-curve at the current frame, and set its curval */
-void calc_icu (IpoCurve *icu, float ctime)
-{
- /* calculate and set curval (evaluates driver too) */
- icu->curval= eval_icu(icu, ctime);
-}
-
-/* calculate for the current frame, all IPO-curves in IPO-block that can be evaluated
- * - icu->curval is set for all IPO-curves which are evaluated!
- */
-void calc_ipo (Ipo *ipo, float ctime)
-{
- IpoCurve *icu;
-
- /* if there is no IPO block to evaluate, or whole block is "muted" */
- if (ipo == NULL) return;
- if (ipo->muteipo) return;
-
- /* loop over all curves */
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- /* only evaluated curve if allowed to:
- * - Muted channels should not be evaluated as they shouldn't have any effect
- * --> user explictly turned them off!
- * - Drivers should be evaluated at all updates
- * --> TODO Note: drivers should be separated from standard channels
- * - IPO_LOCK is not set, as it is set by some internal mechanisms to prevent
- * IPO-curve from overwriting data (currently only used for IPO-Record).
- */
- if ((icu->driver) || (icu->flag & IPO_LOCK)==0) {
- if ((icu->flag & IPO_MUTE)==0)
- calc_icu(icu, ctime);
+ /* get rna-path
+ * - we will need to set the 'disabled' flag if no path is able to be made (for now)
+ */
+ fcu->rna_path= get_rna_access(icu->blocktype, icu->adrcode, actname, constname, &fcu->array_index);
+ if (fcu->rna_path == NULL)
+ fcu->flag |= FCURVE_DISABLED;
+
+ /* copy flags */
+ if (icu->flag & IPO_VISIBLE) fcu->flag |= FCURVE_VISIBLE;
+ if (icu->flag & IPO_SELECT) fcu->flag |= FCURVE_SELECTED;
+ if (icu->flag & IPO_ACTIVE) fcu->flag |= FCURVE_ACTIVE;
+ if (icu->flag & IPO_MUTE) fcu->flag |= FCURVE_MUTED;
+ if (icu->flag & IPO_PROTECT) fcu->flag |= FCURVE_PROTECTED;
+ if (icu->flag & IPO_AUTO_HORIZ) fcu->flag |= FCURVE_AUTO_HANDLES;
+
+ /* set extrapolation */
+ switch (icu->extrap) {
+ case IPO_HORIZ: /* constant extrapolation */
+ case IPO_DIR: /* linear extrapolation */
+ {
+ /* just copy, as the new defines match the old ones... */
+ fcu->extend= icu->extrap;
}
- }
-}
-
-/* ------------------- IPO-Block/Curve Calculation - Special Hacks ----------------------- */
-
-/* Calculate and return the value of the 'Time' Ipo-Curve from an Object,
- * OR return the current time if not found
- * - used in object.c -> bsystem_time()
- */
-float calc_ipo_time (Ipo *ipo, float ctime)
-{
- /* only Time IPO from Object IPO-blocks are relevant */
- if ((ipo) && (ipo->blocktype == ID_OB)) {
- IpoCurve *icu= find_ipocurve(ipo, OB_TIME);
-
- /* only calculate (and set icu->curval) for time curve */
- if (icu) {
- calc_icu(icu, ctime);
- return (10.0f * icu->curval);
+ break;
+
+ case IPO_CYCL: /* cyclic extrapolation */
+ case IPO_CYCLX: /* cyclic extrapolation + offset */
+ {
+ /* Add a new FModifier (Cyclic) instead of setting extend value
+ * as that's the new equivilant of that option.
+ */
+ FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES);
+ FMod_Cycles *data= (FMod_Cycles *)fcm->data;
+
+ /* if 'offset' one is in use, set appropriate settings */
+ if (icu->extrap == IPO_CYCLX)
+ data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC_OFFSET;
+ else
+ data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC;
}
+ break;
}
- /* no appropriate time-curve found */
- return ctime;
+ /* return new F-Curve */
+ return fcu;
}
-/* Evaluate the specified channel in the given IPO block on the specified frame (ctime),
- * writing the value into that channel's icu->curval, but ALSO dumping it in ctime.
- * - Returns success and modifies ctime!
+/* Convert IPO-block (i.e. all its IpoCurves) for some ID to the new system
+ * This assumes that AnimData has been added already. Separation of drivers
+ * from animation data is accomplished here too...
*/
-short calc_ipo_spec (Ipo *ipo, int adrcode, float *ctime)
+static void ipo_to_animdata (ID *id, Ipo *ipo, char *actname, char *constname)
{
- IpoCurve *icu= find_ipocurve(ipo, adrcode);
+ AnimData *adt= BKE_animdata_from_id(id);
+ bAction *act= adt->action;
+ //bActionGroup *grp;
+ IpoCurve *icu, *icn;
+ FCurve *fcu;
+
+ /* sanity check */
+ if ELEM(NULL, id, ipo)
+ return;
+
+ printf("ipo to animdata - ID:%s, IPO:%s, actname:%s constname:%s curves:%d \n",
+ id->name+2, ipo->id.name+2, (actname)?actname:"<None>", (constname)?constname:"<None>",
+ BLI_countlist(&ipo->curve));
+
+ /* validate actname and constname
+ * - clear actname if it was one of the generic <builtin> ones (i.e. 'Object', or 'Shapes')
+ * - actname can then be used to assign F-Curves in Action to Action Groups
+ * (i.e. thus keeping the benefits that used to be provided by Action Channels for grouping
+ * F-Curves for bones). This may be added later... for now let's just dump without them...
+ */
+ if (actname) {
+ if ((GS(id->name) == ID_OB) && (strcmp(actname, "Object") == 0))
+ actname= NULL;
+ if ((GS(id->name) == ID_OB) && (strcmp(actname, "Shape") == 0))
+ actname= NULL;
+ }
- /* only evaluate if found */
- if (icu) {
- /* only calculate if allowed to (not locked and not muted)
- * - drivers not taken into account, because this may be called when calculating a driver
+ /* loop over IPO-Curves, freeing as we progress */
+ for (icu= ipo->curve.first; icu; icu= icn) {
+ /* get link to next (for later) */
+ icn= icu->next;
+
+ /* convert IPO-Curve to F-Curve
+ * NOTE: this frees any of the old data stored in the IPO-Curve that isn't needed anymore...
*/
- if ((icu->flag & (IPO_LOCK|IPO_MUTE))==0)
- calc_icu(icu, *ctime);
+ // XXX we need to cope with the nasty old 'bitflag' curves... that will be a task for later
+ // we will need to create a few new curves when doing so, and will need to sift through the keyframes to add relevant data
+ fcu= icu_to_fcu(icu, actname, constname);
+
+ /* conversion path depends on whether it's a driver or not */
+ if (fcu->driver == NULL) {
+ /* try to get action */
+ if (adt->action == NULL)
+ act= adt->action= add_empty_action("ConvertedAction"); // XXX we need a better name for this...
+
+ /* add F-Curve to action */
+ BLI_addtail(&act->curves, fcu);
+ }
+ else {
+ /* add F-Curve to AnimData's drivers */
+ BLI_addtail(&adt->drivers, fcu);
+ }
- /* value resulting from calculations is written into ctime! */
- *ctime= icu->curval;
- return 1;
+ /* free this IpoCurve now that it's been converted */
+ BLI_freelinkN(&ipo->curve, icu);
}
-
- /* couldn't evaluate */
- return 0;
}
-/* ***************************** IPO - DataAPI ********************************* */
-
-/* --------------------- Flush/Execute IPO Values ----------------------------- */
-
-/* Flush IpoCurve->curvals to the data they affect (defined by ID)
- * - not for Actions or Constraints! (those have their own special handling)
+/* Convert Action-block to new system
+ * NOTE: we need to be careful here, as same data-structs are used for new system too!
*/
-void execute_ipo (ID *id, Ipo *ipo)
+static void action_to_animdata (ID *id, bAction *act)
{
- IpoCurve *icu;
- void *poin;
- int type;
+ AnimData *adt= BKE_animdata_from_id(id);
+ bActionChannel *achan, *achann;
+ bConstraintChannel *conchan, *conchann;
- /* don't do anything without an IPO block */
- if (ipo == NULL)
+ /* only continue if there are Action Channels (indicating unconverted data) */
+ if (ELEM(NULL, adt, act->chanbase.first))
return;
-
- /* loop over IPO Curves, getting pointer to var to affect, and write into that pointer */
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- poin= get_ipo_poin(id, icu, &type);
- if (poin) write_ipo_poin(poin, type, icu->curval);
+
+ /* get rid of all Action Groups */
+ // XXX this is risky if there's some old, some new data in the Action...
+ if (act->groups.first)
+ BLI_freelistN(&act->groups);
+
+ /* check if we need to set this Action as the AnimData's action */
+ if (adt->action == NULL) {
+ /* set this Action as AnimData's Action */
+ adt->action= act;
}
-}
-
-/* Flush Action-Channel IPO data to Pose Channel */
-void execute_action_ipo (bActionChannel *achan, bPoseChannel *pchan)
-{
- /* only do this if there's an Action Channel and Pose Channel to use */
- if (achan && achan->ipo && pchan) {
- IpoCurve *icu;
- /* loop over IPO-curves, getting a pointer to pchan var to write to */
- for (icu= achan->ipo->curve.first; icu; icu= icu->next) {
- void *poin= get_pchan_ipo_poin(pchan, icu->adrcode);
+ /* loop through Action-Channels, converting data, freeing as we go */
+ for (achan= act->chanbase.first; achan; achan= achann) {
+ /* get pointer to next Action Channel */
+ achann= achan->next;
+
+ /* convert Action Channel's IPO data */
+ if (achan->ipo) {
+ ipo_to_animdata(id, achan->ipo, achan->name, NULL);
+ achan->ipo->id.us--;
+ achan->ipo= NULL;
+ }
+
+ /* convert constraint channel IPO-data */
+ for (conchan= achan->constraintChannels.first; conchan; conchan= conchann) {
+ /* get pointer to next Constraint Channel */
+ conchann= conchan->next;
- if (poin) {
- /* only euler-rotations are of type float-degree, all others are 'float' only */
- if (ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z))
- write_ipo_poin(poin, IPO_FLOAT_DEGR, icu->curval);
- else
- write_ipo_poin(poin, IPO_FLOAT, icu->curval);
+ /* convert Constraint Channel's IPO data */
+ if (conchan->ipo) {
+ ipo_to_animdata(id, conchan->ipo, achan->name, conchan->name);
+ conchan->ipo->id.us--;
+ conchan->ipo= NULL;
}
+
+ /* free Constraint Channel */
+ BLI_freelinkN(&achan->constraintChannels, conchan);
}
- }
-}
-
-
-/* --------------------- Force Calculation + Flush IPO Values ----------------------------- */
-
-/* Calculate values for given IPO block, then flush to all of block's users
- * - for general usage
- */
-void do_ipo (Scene *scene, Ipo *ipo)
-{
- if (ipo) {
- float ctime= frame_to_float(scene, scene->r.cfra);
- /* calculate values, then flush to all users of this IPO block */
- calc_ipo(ipo, ctime);
- do_ipo_nocalc(scene, ipo);
+ /* free Action Channel */
+ BLI_freelinkN(&act->chanbase, achan);
}
}
-/* Calculate values for given Material's IPO block, then flush to given Material only */
-void do_mat_ipo (Scene *scene, Material *ma)
-{
- float ctime;
-
- if (ELEM(NULL, ma, ma->ipo))
- return;
-
- ctime= frame_to_float(scene, scene->r.cfra);
- /* if(ob->ipoflag & OB_OFFS_OB) ctime-= ob->sf; */
-
- /* calculate values for current time, then flush values to given material only */
- calc_ipo(ma->ipo, ctime);
- execute_ipo((ID *)ma, ma->ipo);
-}
+/* *************************************************** */
+/* External API - Only Called from do_versions() */
-/* Calculate values for given Object's IPO block, then flush to given Object only
- * - there's also some funky stuff that looks like it's for scene layers
+/* Called from do_versions() in readfile.c to convert the old 'IPO/adrcode' system
+ * to the new 'Animato/RNA' system.
+ *
+ * The basic method used here, is to loop over datablocks which have IPO-data, and
+ * add those IPO's to new AnimData blocks as Actions.
+ * Action/NLA data only works well for Objects, so these only need to be checked for there.
+ *
+ * Data that has been converted should be freed immediately, which means that it is immediately
+ * clear which datablocks have yet to be converted, and also prevent freeing errors when we exit.
*/
-void do_ob_ipo (Scene *scene, Object *ob)
+// XXX currently done after all file reading...
+void do_versions_ipos_to_animato(Main *main)
{
- float ctime;
- unsigned int lay;
+ ID *id;
+ AnimData *adt;
- if (ob->ipo == NULL)
+ if (main == NULL) {
+ printf("Argh! Main is NULL in do_versions_ipos_to_animato() \n");
return;
-
- /* do not set ob->ctime here: for example when parent in invisible layer */
- ctime= bsystem_time(scene, ob, (float) scene->r.cfra, 0.0);
-
- /* calculate values of */
- calc_ipo(ob->ipo, ctime);
-
- /* Patch: remember localview */
- lay= ob->lay & 0xFF000000;
-
- /* flush IPO values to this object only */
- execute_ipo((ID *)ob, ob->ipo);
-
- /* hack: for layer animation??? - is this what this is? (Aligorith, 28Sep2008) */
- ob->lay |= lay;
- if ((ob->id.name[2]=='S') && (ob->id.name[3]=='C') && (ob->id.name[4]=='E')) {
- if (strcmp(scene->id.name+2, ob->id.name+6)==0) {
- scene->lay= ob->lay;
- //XXX copy_view3d_lock(0);
- /* no redraw here! creates too many calls */
- }
}
-}
-
-/* Only execute those IPO-Curves with drivers, on the current frame, for the given Object
- * - TODO: Drivers should really be made separate from standard anim channels
- */
-void do_ob_ipodrivers (Object *ob, Ipo *ipo, float ctime)
-{
- IpoCurve *icu;
- void *poin;
- int type;
-
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- if (icu->driver) {
- icu->curval= eval_icu(icu, ctime);
-
- poin= get_ipo_poin((ID *)ob, icu, &type);
- if (poin) write_ipo_poin(poin, type, icu->curval);
- }
+
+ /* only convert if version is right */
+ // XXX???
+ if (main->versionfile >= 250) {
+ printf("WARNING: Animation data too new to convert (Version %d) \n", main->versionfile);
+ return;
}
-}
-
-/* Special variation to calculate IPO values for Sequence + perform other stuff */
-void do_seq_ipo (Scene *scene, Sequence *seq, int cfra)
-{
- float ctime, div;
+ else
+ printf("INFO: Converting to Animato... \n"); // xxx debug
+
- /* seq_ipo has an exception: calc both fields immediately */
- if (seq->ipo) {
- if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
- ctime = frame_to_float(scene, cfra);
- div = 1.0;
- }
- else {
- ctime= frame_to_float(scene, cfra - seq->startdisp);
- div= (seq->enddisp - seq->startdisp) / 100.0f;
- if (div == 0.0) return;
- }
+ /* objects */
+ for (id= main->object.first; id; id= id->next) {
+ Object *ob= (Object *)id;
+ bPoseChannel *pchan;
+ bConstraint *con;
+ bConstraintChannel *conchan, *conchann;
- /* 2nd field */
- calc_ipo(seq->ipo, (ctime+0.5f)/div);
- execute_ipo((ID *)seq, seq->ipo);
- seq->facf1= seq->facf0;
+ printf("\tconverting ob %s \n", id->name+2);
- /* 1st field */
- calc_ipo(seq->ipo, ctime/div);
- execute_ipo((ID *)seq, seq->ipo);
- }
- else
- seq->facf1= seq->facf0= 1.0f;
-}
-
-/* --------- */
-
-
-/* exception: it does calc for objects...
- * now find out why this routine was used anyway!
- */
-void do_ipo_nocalc (struct Scene *scene, Ipo *ipo)
-{
- Object *ob;
- Material *ma;
- Tex *tex;
- World *wo;
- Lamp *la;
- Camera *ca;
- bSound *snd;
-
- if (ipo == NULL)
- return;
-
- /* only flush IPO values (without calculating first/again) on
- * to the datablocks that use the given IPO block
- */
- switch (ipo->blocktype) {
- case ID_OB:
- for (ob= G.main->object.first; ob; ob= ob->id.next) {
- if (ob->ipo == ipo) do_ob_ipo(scene, ob);
- }
- break;
- case ID_MA:
- for (ma= G.main->mat.first; ma; ma= ma->id.next) {
- if (ma->ipo == ipo) execute_ipo((ID *)ma, ipo);
- }
- break;
- case ID_TE:
- for (tex= G.main->tex.first; tex; tex= tex->id.next) {
- if (tex->ipo == ipo) execute_ipo((ID *)tex, ipo);
- }
- break;
- case ID_WO:
- for (wo= G.main->world.first; wo; wo= wo->id.next) {
- if (wo->ipo == ipo) execute_ipo((ID *)wo, ipo);
- }
- break;
- case ID_LA:
- for (la= G.main->lamp.first; la; la= la->id.next) {
- if (la->ipo == ipo) execute_ipo((ID *)la, ipo);
- }
- break;
- case ID_CA:
- for (ca= G.main->camera.first; ca; ca= ca->id.next) {
- if (ca->ipo == ipo) execute_ipo((ID *)ca, ipo);
- }
- break;
- case ID_SO:
- for (snd= G.main->sound.first; snd; snd= snd->id.next) {
- if (snd->ipo == ipo) execute_ipo((ID *)snd, ipo);
+ /* check if object has any animation data */
+ if ((ob->ipo) || (ob->action) || (ob->nlastrips.first)) {
+ /* Add AnimData block */
+ adt= BKE_id_add_animdata(id);
+
+ /* IPO first */
+ if (ob->ipo) {
+ ipo_to_animdata(id, ob->ipo, NULL, NULL);
+ ob->ipo->id.us--;
+ ob->ipo= NULL;
+ }
+
+ /* now Action */
+ if (ob->action) {
+ action_to_animdata(id, ob->action);
+
+ /* only decrease usercount if this Action isn't now being used by AnimData */
+ if (ob->action != adt->action) {
+ ob->action->id.us--;
+ ob->action= NULL;
+ }
+ }
+
+ /* finally NLA */
+ // XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!)
}
- break;
- }
-}
-
-/* Executes IPO's for whole database on frame change, in a specified order,
- * with datablocks being calculated in alphabetical order
- * - called on scene_update_for_newframe() only
- */
-void do_all_data_ipos (Scene *scene)
-{
- Material *ma;
- Tex *tex;
- World *wo;
- Ipo *ipo;
- Lamp *la;
- Key *key;
- Camera *ca;
- bSound *snd;
- Sequence *seq;
- Editing *ed;
- Base *base;
- float ctime;
-
- ctime= frame_to_float(scene, scene->r.cfra);
-
- /* this exception cannot be depgraphed yet... what todo with objects in other layers?... */
- for (base= scene->base.first; base; base= base->next) {
- Object *ob= base->object;
- /* only update layer when an ipo */
- if (has_ipo_code(ob->ipo, OB_LAY)) {
- do_ob_ipo(scene, ob);
- base->lay= ob->lay;
+ /* check PoseChannels for constraints with local data */
+ if (ob->pose) {
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ for (con= pchan->constraints.first; con; con= con->next) {
+ /* if constraint has own IPO, convert add these to Object
+ * (NOTE: they're most likely to be drivers too)
+ */
+
+ /* check for Action Constraint */
+ // XXX do we really want to do this here?
+ }
+ }
}
- }
-
- /* layers for the set...*/
- if (scene->set) {
- for (base= scene->set->base.first; base; base= base->next) {
- Object *ob= base->object;
+
+ /* check constraint channels - we need to remove them anyway... */
+ for (conchan= ob->constraintChannels.first; conchan; conchan= conchann) {
+ /* get pointer to next Constraint Channel */
+ conchann= conchan->next;
- if (has_ipo_code(ob->ipo, OB_LAY)) {
- do_ob_ipo(scene, ob);
- base->lay= ob->lay;
+ /* convert Constraint Channel's IPO data */
+ if (conchan->ipo) {
+ ipo_to_animdata(id, conchan->ipo, NULL, conchan->name);
+ conchan->ipo->id.us--;
+ conchan->ipo= NULL;
}
+
+ /* free Constraint Channel */
+ BLI_freelinkN(&ob->constraintChannels, conchan);
}
}
- /* Calculate all IPO blocks in use, execept those for Objects */
- for (ipo= G.main->ipo.first; ipo; ipo= ipo->id.next) {
- if ((ipo->id.us) && (ipo->blocktype != ID_OB)) {
- calc_ipo(ipo, ctime);
+ /* shapekeys */
+ for (id= main->key.first; id; id= id->next) {
+ Key *key= (Key *)id;
+
+ printf("\tconverting key %s \n", id->name+2);
+
+ /* we're only interested in the IPO
+ * NOTE: for later, it might be good to port these over to Object instead, as many of these
+ * are likely to be drivers, but it's hard to trace that from here, so move this to Ob loop?
+ */
+ if (key->ipo) {
+ /* Add AnimData block */
+ adt= BKE_id_add_animdata(id);
+
+ /* Convert Shapekey data... */
+ ipo_to_animdata(id, key->ipo, NULL, NULL);
+ key->ipo->id.us--;
+ key->ipo= NULL;
}
}
-
- /* Texture Blocks */
- for (tex= G.main->tex.first; tex; tex= tex->id.next) {
- if (tex->ipo) execute_ipo((ID *)tex, tex->ipo);
- }
-
- /* Material Blocks */
- for (ma= G.main->mat.first; ma; ma= ma->id.next) {
- if (ma->ipo) execute_ipo((ID *)ma, ma->ipo);
- }
- /* World Blocks */
- for (wo= G.main->world.first; wo; wo= wo->id.next) {
- if (wo->ipo) execute_ipo((ID *)wo, wo->ipo);
- }
-
- /* ShapeKey Blocks */
- for (key= G.main->key.first; key; key= key->id.next) {
- if (key->ipo) execute_ipo((ID *)key, key->ipo);
- }
+ // XXX add other types too...
- /* Lamp Blocks */
- for (la= G.main->lamp.first; la; la= la->id.next) {
- if (la->ipo) execute_ipo((ID *)la, la->ipo);
- }
-
- /* Camera Blocks */
- for (ca= G.main->camera.first; ca; ca= ca->id.next) {
- if (ca->ipo) execute_ipo((ID *)ca, ca->ipo);
- }
-
- /* Sound Blocks (Old + Unused) */
- for (snd= G.main->sound.first; snd; snd= snd->id.next) {
- if (snd->ipo) execute_ipo((ID *)snd, snd->ipo);
- }
-
- /* Sequencer: process FAC Ipos used as volume envelopes */
- ed= scene->ed;
- if (ed) {
- for (seq= ed->seqbasep->first; seq; seq= seq->next) {
- if ( ((seq->type == SEQ_RAM_SOUND) || (seq->type == SEQ_HD_SOUND)) &&
- (seq->startdisp <= scene->r.cfra+2) &&
- (seq->enddisp>scene->r.cfra) &&
- (seq->ipo) )
- {
- do_seq_ipo(scene, seq, scene->r.cfra);
- }
- }
- }
+ printf("INFO: animato convert done \n"); // xxx debug
}
-/* --------------------- Assorted ----------------------------- */
-/* clear delta-transforms on all Objects which use the given IPO block */
-void clear_delta_obipo(Ipo *ipo)
-{
- Object *ob;
-
- /* only search if there's an IPO */
- if (ipo == NULL)
- return;
-
- /* search through all objects in database */
- for (ob= G.main->object.first; ob; ob= ob->id.next) {
- /* can only update if not a library */
- if (ob->id.lib == NULL) {
- if (ob->ipo == ipo) {
- memset(&ob->dloc, 0, 12);
- memset(&ob->drot, 0, 12);
- memset(&ob->dsize, 0, 12);
- }
- }
- }
-}
+#if 0 // XXX old animation system
/* ***************************** IPO - DataAPI ********************************* */
@@ -1824,77 +823,6 @@ void clear_delta_obipo(Ipo *ipo)
/* --------------------- Get Pointer API ----------------------------- */
-/* get pointer to pose-channel's channel, but set appropriate flags first */
-// TODO: most channels (except euler rots, which are float-degr) are floats, so do we need type arg?
-void *get_pchan_ipo_poin (bPoseChannel *pchan, int adrcode)
-{
- void *poin= NULL;
-
- switch (adrcode) {
- case AC_QUAT_W:
- poin= &(pchan->quat[0]);
- pchan->flag |= POSE_ROT;
- break;
- case AC_QUAT_X:
- poin= &(pchan->quat[1]);
- pchan->flag |= POSE_ROT;
- break;
- case AC_QUAT_Y:
- poin= &(pchan->quat[2]);
- pchan->flag |= POSE_ROT;
- break;
- case AC_QUAT_Z:
- poin= &(pchan->quat[3]);
- pchan->flag |= POSE_ROT;
- break;
-
- case AC_EUL_X:
- poin= &(pchan->eul[0]);
- pchan->flag |= POSE_ROT;
- //type= IPO_FLOAT_DEGR;
- break;
- case AC_EUL_Y:
- poin= &(pchan->eul[1]);
- pchan->flag |= POSE_ROT;
- //type= IPO_FLOAT_DEGR;
- break;
- case AC_EUL_Z:
- poin= &(pchan->eul[2]);
- pchan->flag |= POSE_ROT;
- //type= IPO_FLOAT_DEGR;
- break;
-
- case AC_LOC_X:
- poin= &(pchan->loc[0]);
- pchan->flag |= POSE_LOC;
- break;
- case AC_LOC_Y:
- poin= &(pchan->loc[1]);
- pchan->flag |= POSE_LOC;
- break;
- case AC_LOC_Z:
- poin= &(pchan->loc[2]);
- pchan->flag |= POSE_LOC;
- break;
-
- case AC_SIZE_X:
- poin= &(pchan->size[0]);
- pchan->flag |= POSE_SIZE;
- break;
- case AC_SIZE_Y:
- poin= &(pchan->size[1]);
- pchan->flag |= POSE_SIZE;
- break;
- case AC_SIZE_Z:
- poin= &(pchan->size[2]);
- pchan->flag |= POSE_SIZE;
- break;
- }
-
- /* return pointer */
- return poin;
-}
-
/* get texture channel */
static void *give_tex_poin (Tex *tex, int adrcode, int *type )
{
@@ -2024,83 +952,6 @@ void *get_ipo_poin (ID *id, IpoCurve *icu, int *type)
/* data is divided into 'blocktypes' based on ID-codes */
switch (GS(id->name)) {
- case ID_OB: /* object channels ----------------------------- */
- {
- Object *ob= (Object *)id;
-
- switch (icu->adrcode) {
- case OB_LOC_X:
- poin= &(ob->loc[0]); break;
- case OB_LOC_Y:
- poin= &(ob->loc[1]); break;
- case OB_LOC_Z:
- poin= &(ob->loc[2]); break;
- case OB_DLOC_X:
- poin= &(ob->dloc[0]); break;
- case OB_DLOC_Y:
- poin= &(ob->dloc[1]); break;
- case OB_DLOC_Z:
- poin= &(ob->dloc[2]); break;
-
- case OB_ROT_X:
- poin= &(ob->rot[0]); *type= IPO_FLOAT_DEGR; break;
- case OB_ROT_Y:
- poin= &(ob->rot[1]); *type= IPO_FLOAT_DEGR; break;
- case OB_ROT_Z:
- poin= &(ob->rot[2]); *type= IPO_FLOAT_DEGR; break;
- case OB_DROT_X:
- poin= &(ob->drot[0]); *type= IPO_FLOAT_DEGR; break;
- case OB_DROT_Y:
- poin= &(ob->drot[1]); *type= IPO_FLOAT_DEGR; break;
- case OB_DROT_Z:
- poin= &(ob->drot[2]); *type= IPO_FLOAT_DEGR; break;
-
- case OB_SIZE_X:
- poin= &(ob->size[0]); break;
- case OB_SIZE_Y:
- poin= &(ob->size[1]); break;
- case OB_SIZE_Z:
- poin= &(ob->size[2]); break;
- case OB_DSIZE_X:
- poin= &(ob->dsize[0]); break;
- case OB_DSIZE_Y:
- poin= &(ob->dsize[1]); break;
- case OB_DSIZE_Z:
- poin= &(ob->dsize[2]); break;
-
- case OB_LAY:
- poin= &(ob->lay); *type= IPO_INT_BIT; break;
-
- case OB_COL_R:
- poin= &(ob->col[0]); break;
- case OB_COL_G:
- poin= &(ob->col[1]); break;
- case OB_COL_B:
- poin= &(ob->col[2]); break;
- case OB_COL_A:
- poin= &(ob->col[3]); break;
-
- case OB_PD_FSTR:
- if (ob->pd) poin= &(ob->pd->f_strength);
- break;
- case OB_PD_FFALL:
- if (ob->pd) poin= &(ob->pd->f_power);
- break;
- case OB_PD_SDAMP:
- if (ob->pd) poin= &(ob->pd->pdef_damp);
- break;
- case OB_PD_RDAMP:
- if (ob->pd) poin= &(ob->pd->pdef_rdamp);
- break;
- case OB_PD_PERM:
- if (ob->pd) poin= &(ob->pd->pdef_perm);
- break;
- case OB_PD_FMAXD:
- if (ob->pd) poin= &(ob->pd->maxdist);
- break;
- }
- }
- break;
case ID_MA: /* material channels ----------------------------- */
{
Material *ma= (Material *)id;
@@ -2193,35 +1044,6 @@ void *get_ipo_poin (ID *id, IpoCurve *icu, int *type)
poin= give_tex_poin(tex, icu->adrcode, type);
}
break;
- case ID_SEQ: /* sequence channels ----------------------------- */
- {
- Sequence *seq= (Sequence *)id;
-
- switch (icu->adrcode) {
- case SEQ_FAC1:
- poin= &(seq->facf0); break;
- }
- }
- break;
- case ID_CU: /* curve channels ----------------------------- */
- {
- poin= &(icu->curval);
- }
- break;
- case ID_KE: /* shapekey channels ----------------------------- */
- {
- Key *key= (Key *)id;
- KeyBlock *kb;
-
- for(kb= key->block.first; kb; kb= kb->next) {
- if (kb->adrcode == icu->adrcode)
- break;
- }
-
- if (kb)
- poin= &(kb->curval);
- }
- break;
case ID_WO: /* world channels ----------------------------- */
{
World *wo= (World *)id;
@@ -2455,482 +1277,5 @@ void *get_ipo_poin (ID *id, IpoCurve *icu, int *type)
return poin;
}
-/* --------------------- IPO-Curve Limits ----------------------------- */
-
-/* set limits for IPO-curve
- * Note: must be synced with UI and PyAPI
- */
-void set_icu_vars (IpoCurve *icu)
-{
- /* defaults. 0.0 for y-extents makes these ignored */
- icu->ymin= icu->ymax= 0.0;
- icu->ipo= IPO_BEZ;
-
- switch (icu->blocktype) {
- case ID_OB: /* object channels ----------------------------- */
- {
- if (icu->adrcode == OB_LAY) {
- icu->ipo= IPO_CONST;
- icu->vartype= IPO_BITS;
- }
- }
- break;
- case ID_MA: /* material channels ----------------------------- */
- {
- if (icu->adrcode < MA_MAP1) {
- switch (icu->adrcode) {
- case MA_HASIZE:
- icu->ymax= 10000.0; break;
- case MA_HARD:
- icu->ymax= 511.0; break;
- case MA_SPEC:
- icu->ymax= 2.0; break;
- case MA_MODE:
- icu->ipo= IPO_CONST;
- icu->vartype= IPO_BITS; break;
- case MA_RAYM:
- icu->ymax= 1.0; break;
- case MA_TRANSLU:
- icu->ymax= 1.0; break;
- case MA_IOR:
- icu->ymin= 1.0;
- icu->ymax= 3.0; break;
- case MA_FRESMIR:
- icu->ymax= 5.0; break;
- case MA_FRESMIRI:
- icu->ymin= 1.0;
- icu->ymax= 5.0; break;
- case MA_FRESTRA:
- icu->ymax= 5.0; break;
- case MA_FRESTRAI:
- icu->ymin= 1.0;
- icu->ymax= 5.0; break;
- case MA_ADD:
- icu->ymax= 1.0; break;
- case MA_EMIT:
- icu->ymax= 2.0; break;
- default:
- icu->ymax= 1.0; break;
- }
- }
- else {
- switch (icu->adrcode & (MA_MAP1-1)) {
- case MAP_OFS_X:
- case MAP_OFS_Y:
- case MAP_OFS_Z:
- case MAP_SIZE_X:
- case MAP_SIZE_Y:
- case MAP_SIZE_Z:
- icu->ymax= 1000.0;
- icu->ymin= -1000.0;
- break;
- case MAP_R:
- case MAP_G:
- case MAP_B:
- case MAP_DVAR:
- case MAP_COLF:
- case MAP_VARF:
- case MAP_DISP:
- icu->ymax= 1.0;
- break;
- case MAP_NORF:
- icu->ymax= 25.0;
- break;
- }
- }
- }
- break;
- case ID_TE: /* texture channels ----------------------------- */
- {
- switch (icu->adrcode & (MA_MAP1-1)) {
- case TE_NSIZE:
- icu->ymin= 0.0001f;
- icu->ymax= 2.0f;
- break;
- case TE_NDEPTH:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 6.0f;
- break;
- case TE_NTYPE:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 1.0f;
- break;
- case TE_TURB:
- icu->ymax= 200.0f;
- break;
- case TE_VNW1:
- case TE_VNW2:
- case TE_VNW3:
- case TE_VNW4:
- icu->ymax= 2.0f;
- icu->ymin= -2.0f;
- break;
- case TE_VNMEXP:
- icu->ymax= 10.0f;
- icu->ymin= 0.01f;
- break;
- case TE_VN_DISTM:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 6.0f;
- break;
- case TE_VN_COLT:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 3.0f;
- break;
- case TE_ISCA:
- icu->ymax= 10.0f;
- icu->ymin= 0.01f;
- break;
- case TE_DISTA:
- icu->ymax= 10.0f;
- break;
- case TE_MG_TYP:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 6.0f;
- break;
- case TE_MGH:
- icu->ymin= 0.0001f;
- icu->ymax= 2.0f;
- break;
- case TE_MG_LAC:
- case TE_MG_OFF:
- case TE_MG_GAIN:
- icu->ymax= 6.0f; break;
- case TE_MG_OCT:
- icu->ymax= 8.0f; break;
- case TE_N_BAS1:
- case TE_N_BAS2:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 8.0f;
- break;
- case TE_COL_R:
- icu->ymax= 0.0f; break;
- case TE_COL_G:
- icu->ymax= 2.0f; break;
- case TE_COL_B:
- icu->ymax= 2.0f; break;
- case TE_BRIGHT:
- icu->ymax= 2.0f; break;
- case TE_CONTRA:
- icu->ymax= 5.0f; break;
- }
- }
- break;
- case ID_SEQ: /* sequence channels ----------------------------- */
- {
- icu->ymax= 1.0f;
- }
- break;
- case ID_CU: /* curve channels ----------------------------- */
- {
- icu->ymax= 1.0f;
- }
- break;
- case ID_WO: /* world channels ----------------------------- */
- {
- if (icu->adrcode < MA_MAP1) {
- switch (icu->adrcode) {
- case WO_EXPOS:
- icu->ymax= 5.0f; break;
-
- case WO_MISTDI:
- case WO_MISTSTA:
- case WO_MISTHI:
- case WO_STARDIST:
- case WO_STARSIZE:
- break;
-
- default:
- icu->ymax= 1.0f;
- break;
- }
- }
- else {
- switch (icu->adrcode & (MA_MAP1-1)) {
- case MAP_OFS_X:
- case MAP_OFS_Y:
- case MAP_OFS_Z:
- case MAP_SIZE_X:
- case MAP_SIZE_Y:
- case MAP_SIZE_Z:
- icu->ymax= 100.0f;
- icu->ymin= -100.0f;
- break;
- case MAP_R:
- case MAP_G:
- case MAP_B:
- case MAP_DVAR:
- case MAP_COLF:
- case MAP_NORF:
- case MAP_VARF:
- case MAP_DISP:
- icu->ymax= 1.0f;
- }
- }
- }
- break;
- case ID_LA: /* lamp channels ----------------------------- */
- {
- if (icu->adrcode < MA_MAP1) {
- switch (icu->adrcode) {
- case LA_ENERGY:
- case LA_DIST:
- break;
-
- case LA_COL_R:
- case LA_COL_G:
- case LA_COL_B:
- case LA_SPOTBL:
- case LA_QUAD1:
- case LA_QUAD2:
- icu->ymax= 1.0f; break;
-
- case LA_SPOTSI:
- icu->ymax= 180.0f; break;
-
- case LA_HALOINT:
- icu->ymax= 5.0f; break;
- }
- }
- else {
- switch (icu->adrcode & (MA_MAP1-1)) {
- case MAP_OFS_X:
- case MAP_OFS_Y:
- case MAP_OFS_Z:
- case MAP_SIZE_X:
- case MAP_SIZE_Y:
- case MAP_SIZE_Z:
- icu->ymax= 100.0f;
- icu->ymin= -100.0f;
- break;
- case MAP_R:
- case MAP_G:
- case MAP_B:
- case MAP_DVAR:
- case MAP_COLF:
- case MAP_NORF:
- case MAP_VARF:
- case MAP_DISP:
- icu->ymax= 1.0f;
- }
- }
- }
- break;
- case ID_CA: /* camera channels ----------------------------- */
- {
- switch (icu->adrcode) {
- case CAM_LENS:
- icu->ymin= 1.0f;
- icu->ymax= 1000.0f;
- break;
- case CAM_STA:
- icu->ymin= 0.001f;
- break;
- case CAM_END:
- icu->ymin= 0.1f;
- break;
-
- case CAM_YF_APERT:
- icu->ymin = 0.0f;
- icu->ymax = 2.0f;
- break;
- case CAM_YF_FDIST:
- icu->ymin = 0.0f;
- icu->ymax = 5000.0f;
- break;
-
- case CAM_SHIFT_X:
- case CAM_SHIFT_Y:
- icu->ymin= -2.0f;
- icu->ymax= 2.0f;
- break;
- }
- }
- break;
- case ID_SO: /* sound channels ----------------------------- */
- {
- switch (icu->adrcode) {
- case SND_VOLUME:
- icu->ymin= 0.0f;
- icu->ymax= 1.0f;
- break;
- case SND_PITCH:
- icu->ymin= -12.0f;
- icu->ymin= 12.0f;
- break;
- case SND_PANNING:
- icu->ymin= 0.0f;
- icu->ymax= 1.0f;
- break;
- case SND_ATTEN:
- icu->ymin= 0.0f;
- icu->ymin= 1.0f;
- break;
- }
- }
- break;
- case ID_PA: /* particle channels ----------------------------- */
- {
- switch (icu->adrcode) {
- case PART_EMIT_LIFE:
- case PART_SIZE:
- case PART_KINK_FREQ:
- case PART_EMIT_VEL:
- case PART_EMIT_AVE:
- case PART_EMIT_SIZE:
- icu->ymin= 0.0f;
- break;
- case PART_CLUMP:
- icu->ymin= -1.0f;
- icu->ymax= 1.0f;
- break;
- case PART_DRAG:
- case PART_DAMP:
- case PART_LENGTH:
- icu->ymin= 0.0f;
- icu->ymax= 1.0f;
- break;
- case PART_KINK_SHAPE:
- icu->ymin= -0.999f;
- icu->ymax= 0.999f;
- break;
- }
- }
- break;
- case ID_CO: /* constraint channels ----------------------------- */
- {
- icu->ymin= 0.0f;
- icu->ymax= 1.0f;
- }
- break;
- }
-
- /* by default, slider limits will be icu->ymin and icu->ymax */
- icu->slide_min= icu->ymin;
- icu->slide_max= icu->ymax;
-}
-
-/* --------------------- Pointer I/O API ----------------------------- */
-
-/* write the given value directly into the given pointer */
-void write_ipo_poin (void *poin, int type, float val)
-{
- /* Note: we only support a limited number of types, with the value
- * to set needing to be cast to the appropriate type first
- * -> (float to integer conversions could be slow)
- */
- switch(type) {
- case IPO_FLOAT:
- *((float *)poin)= val;
- break;
-
- case IPO_FLOAT_DEGR: /* special hack for rotation so that it fits on same axis as other transforms */
- *((float *)poin)= (float)(val * M_PI_2 / 9.0);
- break;
-
- case IPO_INT:
- case IPO_INT_BIT: // fixme... directly revealing bitflag combinations is evil!
- case IPO_LONG:
- *((int *)poin)= (int)val;
- break;
-
- case IPO_SHORT:
- case IPO_SHORT_BIT: // fixme... directly revealing bitflag combinations is evil!
- *((short *)poin)= (short)val;
- break;
-
- case IPO_CHAR:
- case IPO_CHAR_BIT: // fixme... directly revealing bitflag combinations is evil!
- *((char *)poin)= (char)val;
- break;
- }
-}
-
-/* read the value from the pointer that was obtained */
-float read_ipo_poin (void *poin, int type)
-{
- float val = 0.0;
-
- /* Note: we only support a limited number of types, with the value
- * to set needing to be cast to the appropriate type first
- * -> (int to float conversions may loose accuracy in rare cases)
- */
- switch (type) {
- case IPO_FLOAT:
- val= *((float *)poin);
- break;
-
- case IPO_FLOAT_DEGR: /* special hack for rotation so that it fits on same axis as other transforms */
- val= *( (float *)poin);
- val = (float)(val / (M_PI_2/9.0));
- break;
-
- case IPO_INT:
- case IPO_INT_BIT: // fixme... directly revealing bitflag combinations is evil!
- case IPO_LONG:
- val= (float)( *((int *)poin) );
- break;
-
- case IPO_SHORT:
- case IPO_SHORT_BIT: // fixme... directly revealing bitflag combinations is evil!
- val= *((short *)poin);
- break;
-
- case IPO_CHAR:
- case IPO_CHAR_BIT: // fixme... directly revealing bitflag combinations is evil
- val= *((char *)poin);
- break;
- }
-
- /* return value */
- return val;
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!! FIXME - BAD CRUFT WARNING !!!!!!!!!!!!!!!!!!!!!!!
-
-
-/* ***************************** IPO <--> GameEngine Interface ********************************* */
-
-/* channels is max 32 items, allocated by calling function */
-short IPO_GetChannels (Ipo *ipo, IPO_Channel *channels)
-{
- IpoCurve *icu;
- int total = 0;
-
- /* don't do anything with no IPO-block */
- if (ipo == NULL)
- return 0;
-
- /* store the IPO-curve's adrcode in the relevant channel slot */
- for (icu=ipo->curve.first; (icu) && (total < 31); icu=icu->next, total++)
- channels[total]= icu->adrcode;
-
- /* return the number of channels stored */
- return total;
-}
-
-/* Get the float value for channel 'channel' at time 'ctime' */
-float IPO_GetFloatValue (Ipo *ipo, IPO_Channel channel, float ctime)
-{
- /* don't evaluate if no IPO to use */
- if (ipo == NULL)
- return 0;
-
- /* only calculate the specified channel */
- calc_ipo_spec(ipo, channel, &ctime);
-
- /* unapply rotation hack, as gameengine doesn't use it */
- if ((OB_ROT_X <= channel) && (channel <= OB_DROT_Z))
- ctime *= (float)(M_PI_2/9.0);
-
- /* return the value of this channel */
- return ctime;
-}
#endif // XXX old animation system
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 718ddf2dc96..8c5bac3019e 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -35,6 +35,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
@@ -1367,6 +1368,10 @@ int do_ob_key(Scene *scene, Object *ob)
execute_ipo((ID *)key, key->ipo);
}
#endif // XXX old animation system
+ /* do shapekey local drivers */
+ float ctime= (float)scene->r.cfra; // XXX this needs to be checked
+ printf("ob %s - do shapekey drivers \n", ob->id.name+2);
+ BKE_animsys_evaluate_animdata(&key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
if(ob->type==OB_MESH) return do_mesh_key(scene, ob, ob->data);
else if(ob->type==OB_CURVE) return do_curve_key(scene, ob->data);
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index ecd6e22c3ef..b74406f3d3f 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -232,6 +232,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
/* BACKWARDS! also watch order of free-ing! (mesh<->mat) */
lb[a++]= &(main->ipo);
+ lb[a++]= &(main->action); // xxx moved here to avoid problems when freeing with animato (aligorith)
lb[a++]= &(main->key);
lb[a++]= &(main->nodetree);
lb[a++]= &(main->image);
@@ -244,7 +245,6 @@ int set_listbasepointers(Main *main, ListBase **lb)
*/
lb[a++]= &(main->armature);
- lb[a++]= &(main->action);
lb[a++]= &(main->mesh);
lb[a++]= &(main->curve);
@@ -490,7 +490,7 @@ void free_libblock(ListBase *lb, void *idv)
free_camera((Camera*) id);
break;
case ID_IP:
- /*free_ipo((Ipo *)id);*/
+ free_ipo((Ipo *)id);
break;
case ID_KE:
free_key((Key *)id);
@@ -682,52 +682,6 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor
}
}
- /* Silly routine, the only difference between the one
- * above is that it only adds items with a matching
- * blocktype... this should be unified somehow... - zr
- */
-static void IPOnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int blocktype)
-{
- ID *id;
- int i, nids;
-
- for (id= lb->first, nids= 0; id; id= id->next) {
- Ipo *ipo= (Ipo*) id;
-
- if (ipo->blocktype==blocktype)
- nids++;
- }
-
- if (nids>MAX_IDPUP) {
- BLI_dynstr_append(pupds, "DataBrowse %x-2");
- } else {
- for (i=0, id= lb->first; id; id= id->next) {
- Ipo *ipo= (Ipo*) id;
-
- if (ipo->blocktype==blocktype) {
- char buf[32];
-
- if (id==link)
- *nr= i+1;
-
- if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.')
- continue;
-
- get_flags_for_id(id, buf);
-
- BLI_dynstr_append(pupds, buf);
- BLI_dynstr_append(pupds, id->name+2);
- sprintf(buf, "%%x%d", i+1);
- BLI_dynstr_append(pupds, buf);
-
- if(id->next)
- BLI_dynstr_append(pupds, "|");
-
- i++;
- }
- }
- }
-}
/* used by headerbuttons.c buttons.c editobject.c editseq.c */
/* if nr==NULL no MAX_IDPUP, this for non-header browsing */
@@ -775,28 +729,6 @@ void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb
}
-/* only used by headerbuttons.c */
-void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype)
-{
- DynStr *pupds= BLI_dynstr_new();
-
- if (title) {
- BLI_dynstr_append(pupds, title);
- BLI_dynstr_append(pupds, "%t|");
- }
-
- if (extraops) {
- BLI_dynstr_append(pupds, extraops);
- if (BLI_dynstr_get_len(pupds))
- BLI_dynstr_append(pupds, "|");
- }
-
- IPOnames_to_dyn_pupstring(pupds, lb, link, nr, blocktype);
-
- *str= BLI_dynstr_get_cstring(pupds);
- BLI_dynstr_free(pupds);
-}
-
/* used by buttons.c library.c mball.c */
void splitIDname(char *name, char *left, int *nr)
{
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 2718981e398..15fde4420f0 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2274,7 +2274,7 @@ void object_handle_update(Scene *scene, Object *ob)
if(ob->recalc & OB_RECALC_OB) {
- // printf("recalcob %s\n", ob->id.name+2);
+ printf("recalcob %s\n", ob->id.name+2);
/* handle proxy copy for target */
if(ob->id.lib && ob->proxy_from) {
@@ -2296,7 +2296,7 @@ void object_handle_update(Scene *scene, Object *ob)
if(ob->recalc & OB_RECALC_DATA) {
- // printf("recalcdata %s\n", ob->id.name+2);
+ printf("recalcdata %s\n", ob->id.name+2);
/* includes all keys and modifiers */
if(ob->type==OB_MESH) {
@@ -2312,29 +2312,20 @@ void object_handle_update(Scene *scene, Object *ob)
else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
makeDispListCurveTypes(scene, ob, 0);
}
- else if(ob->type==OB_LATTICE) {
- lattice_calc_modifiers(scene, ob);
- }
- else if(ob->type==OB_CAMERA) {
- //Camera *cam = (Camera *)ob->data;
-
- // xxx old animation code here
- //calc_ipo(cam->ipo, frame_to_float(scene, scene->r.cfra));
- //execute_ipo(&cam->id, cam->ipo);
+ else if(ELEM(ob->type, OB_CAMERA, OB_LAMP)) {
+ ID *data_id= (ID *)ob->data;
+ AnimData *adt= BKE_animdata_from_id(data_id);
+ float ctime= (float)scene->r.cfra; // XXX this is bad...
- // in new system, this has already been done! - aligorith
+ /* evaluate drivers */
+ BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
}
- else if(ob->type==OB_LAMP) {
- //Lamp *la = (Lamp *)ob->data;
-
- // xxx old animation code here
- //calc_ipo(la->ipo, frame_to_float(scene, scene->r.cfra));
- //execute_ipo(&la->id, la->ipo);
-
- // in new system, this has already been done! - aligorith
+ else if(ob->type==OB_LATTICE) {
+ lattice_calc_modifiers(scene, ob);
}
else if(ob->type==OB_ARMATURE) {
/* this happens for reading old files and to match library armatures with poses */
+ // XXX this won't screw up the pose set already...
if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC))
armature_rebuild_pose(ob, ob->data);
@@ -2343,7 +2334,6 @@ void object_handle_update(Scene *scene, Object *ob)
// printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
}
else {
- //do_all_pose_actions(scene, ob); // xxx old animation system
where_is_pose(scene, ob);
}
}
diff --git a/source/blender/blenloader/SConscript b/source/blender/blenloader/SConscript
index 5a445ad0cfc..1aeb6bd9b83 100644
--- a/source/blender/blenloader/SConscript
+++ b/source/blender/blenloader/SConscript
@@ -11,4 +11,4 @@ incs += ' ' + env['BF_ZLIB_INC']
defs = []
-env.BlenderLib ( 'bf_blenloader', sources, Split(incs), defs, libtype=['core','player'], priority = [165, 30] )
+env.BlenderLib ( 'bf_blenloader', sources, Split(incs), defs, libtype=['core','player'], priority = [135, 30] )
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index b1ce482cbc5..23f22523e19 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -122,6 +122,7 @@
#include "BKE_global.h" // for G
#include "BKE_group.h"
#include "BKE_image.h"
+#include "BKE_ipo.h"
#include "BKE_key.h" //void set_four_ipo
#include "BKE_lattice.h"
#include "BKE_library.h" // for wich_libbase
@@ -1823,6 +1824,7 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
}
}
+/* NOTE: this assumes that link_list has already been called on the list */
static void direct_link_fcurves(FileData *fd, ListBase *list)
{
FCurve *fcu;
@@ -1904,8 +1906,8 @@ static void direct_link_action(FileData *fd, bAction *act)
bActionChannel *achan; // XXX depreceated - old animation system
bActionGroup *agrp;
- link_list(fd, &act->curves); // xxx - do we need to patch the data for this?
- link_list(fd, &act->chanbase);
+ link_list(fd, &act->curves);
+ link_list(fd, &act->chanbase); // XXX depreceated - old animation system
link_list(fd, &act->groups);
link_list(fd, &act->markers);
@@ -1951,6 +1953,7 @@ static void direct_link_animdata(FileData *fd, AnimData *adt)
return;
/* link drivers */
+ link_list(fd, &adt->drivers);
direct_link_fcurves(fd, &adt->drivers);
/* link overrides */
@@ -8665,14 +8668,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 3)) {
bScreen *sc;
- Ipo *ipo;
- IpoCurve *icu;
-
- /* fix IPO-curves to work with new interpolation options */
- //for (ipo=main->ipo.first; ipo; ipo= ipo->id.next) {
- // for (icu= ipo->curve.first; icu; icu= icu->next)
- // set_interpolation_ipocurve(icu, icu->ipo); // function removed (XXX add it here)
- //}
/* adjust default settings for Animation Editors */
for (sc= main->screen.first; sc; sc= sc->id.next) {
@@ -8719,10 +8714,15 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
for(screen= main->screen.first; screen; screen= screen->id.next)
do_versions_windowmanager_2_50(screen);
+ /* old Animation System (using IPO's) needs to be converted to the new Animato system
+ * (NOTE: conversion code in blenkernel/intern/ipo.c for now)
+ */
+ //do_versions_ipos_to_animato(main);
+
/* struct audio data moved to renderdata */
for(scene= main->scene.first; scene; scene= scene->id.next) {
scene->r.audio = scene->audio;
-
+
if(!scene->toolsettings->uv_selectmode)
scene->toolsettings->uv_selectmode= UV_SELECT_VERTEX;
}
@@ -8836,7 +8836,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_material(fd, main);
lib_link_texture(fd, main);
lib_link_image(fd, main);
- lib_link_ipo(fd, main);
+ lib_link_ipo(fd, main); // XXX depreceated... still needs to be maintained for version patches still
lib_link_key(fd, main);
lib_link_world(fd, main);
lib_link_lamp(fd, main);
@@ -9136,7 +9136,6 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
/* own action */
expand_doit(fd, mainvar, adt->action);
- expand_action(fd, mainvar, adt->action); // XXX this call is only used for patching old animation system
/* drivers - assume that these F-Curves have driver data to be in this list... */
for (fcd= adt->drivers.first; fcd; fcd= fcd->next) {
@@ -9167,6 +9166,9 @@ static void expand_group(FileData *fd, Main *mainvar, Group *group)
static void expand_key(FileData *fd, Main *mainvar, Key *key)
{
expand_doit(fd, mainvar, key->ipo); // XXX depreceated - old animation system
+
+ if(key->adt)
+ expand_animdata(fd, mainvar, key->adt);
}
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 39a477f30fb..48b3bbb918c 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -1058,6 +1058,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
}
break;
+ case ANIMTYPE_FILLACTD:
+ case ANIMTYPE_FILLMATD:
case ANIMTYPE_DSSKEY:
{
if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45);
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index c54ceba67f8..8b89c41775c 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -255,32 +255,15 @@ static float actcopy_firstframe= 999999999.0f;
// XXX find some header to put this in!
void free_actcopybuf ()
{
-#if 0 // XXX old animation system
- bActionChannel *achan, *anext;
- bConstraintChannel *conchan, *cnext;
+ FCurve *fcu, *fcn;
- for (achan= actcopybuf.first; achan; achan= anext) {
- anext= achan->next;
-
- if (achan->ipo) {
- free_ipo(achan->ipo);
- MEM_freeN(achan->ipo);
- }
-
- for (conchan=achan->constraintChannels.first; conchan; conchan=cnext) {
- cnext= conchan->next;
-
- if (conchan->ipo) {
- free_ipo(conchan->ipo);
- MEM_freeN(conchan->ipo);
- }
-
- BLI_freelinkN(&achan->constraintChannels, conchan);
- }
-
- BLI_freelinkN(&actcopybuf, achan);
+ /* free_fcurve() frees F-Curve memory too, but we don't need to do remlink first, as we're freeing all
+ * channels anyway, and the freeing func only cares about the data it's given
+ */
+ for (fcu= actcopybuf.first; fcu; fcu= fcn) {
+ fcn= fcu->next;
+ free_fcurve(fcu);
}
-#endif // XXX old animation system
actcopybuf.first= actcopybuf.last= NULL;
actcopy_firstframe= 999999999.0f;
@@ -292,7 +275,7 @@ void free_actcopybuf ()
* Only the selected action channels gets their selected keyframes copied.
*/
static short copy_action_keys (bAnimContext *ac)
-{
+{
#if 0 // XXX old animation system
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index b1258e05f56..3731efb294c 100755
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -124,7 +124,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "loc");
RNA_def_property_ui_text(prop, "Location", "");
- prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_VECTOR);
+ prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_float_sdna(prop, NULL, "size");
RNA_def_property_ui_text(prop, "Scale", "");