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:
authorTon Roosendaal <ton@blender.org>2005-10-03 00:51:35 +0400
committerTon Roosendaal <ton@blender.org>2005-10-03 00:51:35 +0400
commit015fe7ea817680e785e4dd2b4118bbfdabeba766 (patch)
treee20c853d86690bb30f45843314b76a90d51138a7 /source/blender/blenkernel
parent42fe4c568d2c393dcb016882a08a710ac3b11173 (diff)
Version 1.0 of IpoDrivers.
First note that this is new functionality, unfinished, and only for testing and feedback purposes. I'll list below what works, and what will need work still. This text is also in cms: http://www.blender.org/cms/Ipo_Drivers.680.0.html An IpoDriver is like an IpoCurve, but instead of a Bezier curve, it allows to connect a property of other Objects as input for the "channel". For example, IpoDrivers can be used to have a Shape Key being "driven" by the rotation of a Bone. Or the RGB colors of a Material get driven by the XYZ location of an Object. Editing of Drivers happens in the IpoWindow. Here you can notice that the channels (right hand window) now have an "active" channel indicator. To add a Driver, you have to use the "Transform Properties" Panel (Nkey). Here you can add or remove a Driver to the active channel, and use the buttons to fill in what kind of relationship you want to establish. Driver Objects Note that any Ipo Channel can become driven now, but that only Object transformation or Pose Bone transformation can be used to become a Driver now. At this moment, only the local transformation is taken into account. For Objects that means the location/rotation/scale value without Parent transform (as shown in "Transform Properties" Panel for Objects). For Pose Bones it means that only the Pose transform (changes of rest position) is Driver information (also as shown in Transform Property Panel in Pose Mode). Mapping of Drivers When an Ipo Channel is "driven", the mapping is by default one-to-one. It is only restricted by already built-in limits for Channels, like for Material the "R" value can only range from 0.0 to 1.0. Also note that when mapping rotations, the actual rotation values in Ipos are scaled down with a factor 10.0. (180 degrees actually has in the Ipo system a value of 18.0). This is an ancient year zero convention in Blender... it is a bit hidden, because the ruler (vertical as well as horizontal) displays the virtual values correctly. Only the Properties panel shows the actual value. When you draw an IpoCurve in a Driven channel, this curve will define the mapping between the Driver output (horizontal) and Driven input (vertical, as usual). A nice new option to use is "Insert one-to-one curve" (press I-key, or in pulldown menu). This will also zoom the display in exactly to fill the window, allowing easy edit. If you use this option with degrees, it will map 180 degree rotation to a range of 1.0 unit. Live updates Since the Drivers are integrated in the Ipo system, they will always be updated whenever an Ipo is evaluated. This happens at least on frame changes. For interactive feedback, updates while transforming objects were added in these cases: - Driven Object Ipos, by other Objects or Pose Bones - Driven Shape Key Ipos, by other Objects or Pose Bones You can also insert Drivers on Action Ipos, but these are only evaluated on frame change now. Todo - Drivers can also get a text button, allowing a 1 line Python script to be executed. - Make UI for it a bit less hidden... maybe with visualization in 3D? - Allowing global transform coordinates as Driver too. Issues - renaming Bones won't rename drivers - (file) appending the Ipo won't append the linked driver Objects
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_ipo.h6
-rw-r--r--source/blender/blenkernel/intern/constraint.c2
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c39
-rw-r--r--source/blender/blenkernel/intern/ipo.c164
-rw-r--r--source/blender/blenkernel/intern/key.c2
-rw-r--r--source/blender/blenkernel/intern/object.c39
6 files changed, 211 insertions, 41 deletions
diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h
index c0a5be27bcf..6acbceb8e3f 100644
--- a/source/blender/blenkernel/BKE_ipo.h
+++ b/source/blender/blenkernel/BKE_ipo.h
@@ -52,7 +52,10 @@ struct ID;
/* struct IPO_Channel; */
float frame_to_float(int cfra);
+
+void free_ipo_curve(struct IpoCurve *icu);
void free_ipo(struct Ipo *ipo);
+
struct Ipo *add_ipo(char *name, int idcode);
struct Ipo *copy_ipo(struct Ipo *ipo);
void make_local_obipo(struct Ipo *ipo);
@@ -79,11 +82,14 @@ void *give_mtex_poin(struct MTex *mtex, int adrcode );
void *get_ipo_poin(struct ID *id, struct IpoCurve *icu, int *type);
void set_icu_vars(struct IpoCurve *icu);
void execute_ipo(struct ID *id, struct Ipo *ipo);
+
void do_ipo_nocalc(struct Ipo *ipo);
void do_ipo(struct Ipo *ipo);
void do_mat_ipo(struct Material *ma);
void do_ob_ipo(struct Object *ob);
void do_seq_ipo(struct Sequence *seq);
+void do_ob_ipodrivers(struct Object *ob, struct Ipo *ipo);
+
int has_ipo_code(struct Ipo *ipo, int code);
void do_all_data_ipos(void);
int calc_ipo_spec(struct Ipo *ipo, int adrcode, float *ctime);
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 9c06c2d015d..6fd3cbcfd8b 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -756,7 +756,7 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
if(data->subtarget[0]) {
pchan = get_pose_channel(data->tar->pose, data->subtarget);
if (pchan) {
- float arm_mat[3][3], pose_mat[3][3];
+ float arm_mat[3][3], pose_mat[3][3]; /* arm mat should be bone mat! bug... */
Mat3CpyMat4(arm_mat, pchan->bone->arm_mat);
Mat3CpyMat4(pose_mat, pchan->pose_mat);
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 61a0ea20a2e..45c9d0b874e 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -47,6 +47,7 @@
#include "DNA_ID.h"
#include "DNA_effect_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -289,6 +290,23 @@ DagForest * dag_init()
return forest;
}
+static void dag_add_driver_relation(Ipo *ipo, DagForest *dag, DagNode *node, int isdata)
+{
+ IpoCurve *icu;
+ DagNode *node1;
+
+ for(icu= ipo->curve.first; icu; icu= icu->next) {
+ if(icu->driver && 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);
+ else
+ dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB);
+ }
+ }
+}
+
+
struct DagForest *build_dag(struct Scene *sce, short mask)
{
Base *base;
@@ -300,6 +318,7 @@ struct DagForest *build_dag(struct Scene *sce, short mask)
DagNode * scenenode;
DagForest *dag;
DagAdjList *itA;
+ Key *key;
dag = sce->theDag;
sce->dagisvalid=1;
@@ -324,9 +343,8 @@ struct DagForest *build_dag(struct Scene *sce, short mask)
dag_add_relation(dag,node,node2,DAG_RL_DATA);
node2->first_ancestor = ob;
node2->ancestor_count += 1;
-
-
}
+
if (ob->type == OB_ARMATURE) {
if (ob->pose){
bPoseChannel *pchan;
@@ -354,6 +372,23 @@ struct DagForest *build_dag(struct Scene *sce, short mask)
}
}
}
+
+ /* driver dependencies */
+ if(ob->ipo)
+ dag_add_driver_relation(ob->ipo, dag, node, 0);
+
+ key= ob_get_key(ob);
+ if(key && key->ipo)
+ dag_add_driver_relation(key->ipo, dag, node, 1);
+
+ if(ob->action) {
+ bActionChannel *chan;
+ for (chan = ob->action->chanbase.first; chan; chan=chan->next){
+ if(chan->ipo)
+ dag_add_driver_relation(chan->ipo, dag, node, 1);
+ }
+ }
+
if (ob->modifiers.first) {
ModifierData *md;
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index ece3e39ae1e..36f461feaf2 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -42,6 +42,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_camera_types.h"
#include "DNA_lamp_types.h"
@@ -184,17 +185,24 @@ float frame_to_float(int cfra) /* see also bsystem_time in object.c */
return ctime;
}
+/* includes ipo curve itself */
+void free_ipo_curve(IpoCurve *icu)
+{
+ if(icu->bezt) MEM_freeN(icu->bezt);
+ if(icu->bp) MEM_freeN(icu->bp);
+ if(icu->driver) MEM_freeN(icu->driver);
+ MEM_freeN(icu);
+}
+
/* do not free ipo itself */
void free_ipo(Ipo *ipo)
{
IpoCurve *icu;
- icu= ipo->curve.first;
- while(icu) {
- if(icu->bezt) MEM_freeN(icu->bezt);
- icu= icu->next;
+ while( (icu= ipo->curve.first) ) {
+ BLI_remlink(&ipo->curve, icu);
+ free_ipo_curve(icu);
}
- BLI_freelistN(&ipo->curve);
}
Ipo *add_ipo(char *name, int idcode)
@@ -212,7 +220,7 @@ Ipo *copy_ipo(Ipo *ipo)
Ipo *ipon;
IpoCurve *icu;
- if(ipo==0) return 0;
+ if(ipo==NULL) return 0;
ipon= copy_libblock(ipo);
@@ -221,6 +229,7 @@ Ipo *copy_ipo(Ipo *ipo)
icu= ipon->curve.first;
while(icu) {
icu->bezt= MEM_dupallocN(icu->bezt);
+ if(icu->driver) icu->driver= MEM_dupallocN(icu->driver);
icu= icu->next;
}
@@ -247,7 +256,7 @@ void make_local_obipo(Ipo *ipo)
ob= ob->id.next;
}
- if(local && lib==0) {
+ if(local && lib==NULL) {
ipo->id.lib= 0;
ipo->id.flag= LIB_LOCAL;
new_id(0, (ID *)ipo, 0);
@@ -260,7 +269,7 @@ void make_local_obipo(Ipo *ipo)
while(ob) {
if(ob->ipo==ipo) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
ob->ipo= ipon;
ipon->id.us++;
ipo->id.us--;
@@ -291,7 +300,7 @@ void make_local_matipo(Ipo *ipo)
ma= ma->id.next;
}
- if(local && lib==0) {
+ if(local && lib==NULL) {
ipo->id.lib= 0;
ipo->id.flag= LIB_LOCAL;
new_id(0, (ID *)ipo, 0);
@@ -304,7 +313,7 @@ void make_local_matipo(Ipo *ipo)
while(ma) {
if(ma->ipo==ipo) {
- if(ma->id.lib==0) {
+ if(ma->id.lib==NULL) {
ma->ipo= ipon;
ipon->id.us++;
ipo->id.us--;
@@ -335,7 +344,7 @@ void make_local_keyipo(Ipo *ipo)
key= key->id.next;
}
- if(local && lib==0) {
+ if(local && lib==NULL) {
ipo->id.lib= 0;
ipo->id.flag= LIB_LOCAL;
new_id(0, (ID *)ipo, 0);
@@ -348,7 +357,7 @@ void make_local_keyipo(Ipo *ipo)
while(key) {
if(key->ipo==ipo) {
- if(key->id.lib==0) {
+ if(key->id.lib==NULL) {
key->ipo= ipon;
ipon->id.us++;
ipo->id.us--;
@@ -363,7 +372,7 @@ void make_local_keyipo(Ipo *ipo)
void make_local_ipo(Ipo *ipo)
{
- if(ipo->id.lib==0) return;
+ if(ipo->id.lib==NULL) return;
if(ipo->id.us==1) {
ipo->id.lib= 0;
ipo->id.flag= LIB_LOCAL;
@@ -443,7 +452,7 @@ void testhandles_ipocurve(IpoCurve *icu)
int flag, a;
bezt= icu->bezt;
- if(bezt==0) return;
+ if(bezt==NULL) return;
a= icu->totvert;
while(a--) {
@@ -675,6 +684,86 @@ void berekenx(float *f, float *o, int b)
}
}
+static float eval_driver(IpoDriver *driver)
+{
+ Object *ob= driver->ob;
+
+ if(ob==NULL) return 0.0f;
+
+ if(driver->blocktype==ID_OB) {
+ 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:
+ return ob->rot[0]/(M_PI_2/9.0);
+ case OB_ROT_Y:
+ return ob->rot[1]/(M_PI_2/9.0);
+ case OB_ROT_Z:
+ return 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];
+ }
+ }
+ else { /* ID_AR */
+ bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name);
+ if(pchan && pchan->bone) {
+ float pose_mat[3][3];
+ float diff_mat[3][3], par_mat[3][3], ipar_mat[3][3];
+ float eul[3], size[3];
+
+ /* we need the local transform = current transform - (parent transform + bone transform) */
+
+ Mat3CpyMat4(pose_mat, pchan->pose_mat);
+
+ if (pchan->parent) {
+ Mat3CpyMat4(par_mat, pchan->parent->pose_mat);
+ Mat3MulMat3(diff_mat, par_mat, pchan->bone->bone_mat);
+
+ Mat3Inv(ipar_mat, diff_mat);
+ }
+ else {
+ Mat3Inv(ipar_mat, pchan->bone->bone_mat);
+ }
+
+ Mat3MulMat3(diff_mat, ipar_mat, pose_mat);
+
+ Mat3ToEul(diff_mat, eul);
+ Mat3ToSize(diff_mat, size);
+
+ switch(driver->adrcode) {
+ case OB_LOC_X:
+ return pchan->loc[0];
+ case OB_LOC_Y:
+ return pchan->loc[1];
+ case OB_LOC_Z:
+ return pchan->loc[2];
+ case OB_ROT_X:
+ return eul[0]/(M_PI_2/9.0);
+ case OB_ROT_Y:
+ return eul[1]/(M_PI_2/9.0);
+ case OB_ROT_Z:
+ return eul[2]/(M_PI_2/9.0);
+ case OB_SIZE_X:
+ return size[0];
+ case OB_SIZE_Y:
+ return size[1];
+ case OB_SIZE_Z:
+ return size[2];
+ }
+ }
+ }
+
+ return 0.0f;
+}
+
float eval_icu(IpoCurve *icu, float ipotime)
{
BezTriple *bezt, *prevbezt;
@@ -684,6 +773,10 @@ float eval_icu(IpoCurve *icu, float ipotime)
cycyofs= 0.0;
+ if(icu->driver) {
+ /* ipotime now serves as input for the curve */
+ ipotime= cvalue= eval_driver(icu->driver);
+ }
if(icu->bezt) {
prevbezt= icu->bezt;
bezt= prevbezt+1;
@@ -814,10 +907,12 @@ void calc_ipo(Ipo *ipo, float ctime)
{
IpoCurve *icu;
+ if(ipo==NULL) return;
+
icu= ipo->curve.first;
while(icu) {
- if( (icu->flag & IPO_LOCK)==0) calc_icu(icu, ctime);
+ if(icu->driver || (icu->flag & IPO_LOCK)==0) calc_icu(icu, ctime);
icu= icu->next;
}
@@ -1186,7 +1281,7 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
poin= &(ma->add); break;
}
- if(poin==0) {
+ if(poin==NULL) {
mtex= 0;
if(icu->adrcode & MA_MAP1) mtex= ma->mtex[0];
else if(icu->adrcode & MA_MAP2) mtex= ma->mtex[1];
@@ -1270,7 +1365,7 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
poin= &(wo->starsize); break;
}
- if(poin==0) {
+ if(poin==NULL) {
mtex= 0;
if(icu->adrcode & MA_MAP1) mtex= wo->mtex[0];
else if(icu->adrcode & MA_MAP2) mtex= wo->mtex[1];
@@ -1315,7 +1410,7 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
poin= &(la->haint); break;
}
- if(poin==0) {
+ if(poin==NULL) {
mtex= 0;
if(icu->adrcode & MA_MAP1) mtex= la->mtex[0];
else if(icu->adrcode & MA_MAP2) mtex= la->mtex[1];
@@ -1650,7 +1745,7 @@ void execute_ipo(ID *id, Ipo *ipo)
void *poin;
int type;
- if(ipo==0) return;
+ if(ipo==NULL) return;
icu= ipo->curve.first;
while(icu) {
@@ -1673,7 +1768,7 @@ void do_ipo_nocalc(Ipo *ipo)
Camera *ca;
bSound *snd;
- if(ipo==0) return;
+ if(ipo==NULL) return;
switch(ipo->blocktype) {
case ID_OB:
@@ -1747,7 +1842,7 @@ void do_mat_ipo(Material *ma)
{
float ctime;
- if(ma==0 || ma->ipo==0) return;
+ if(ma==NULL || ma->ipo==NULL) return;
ctime= frame_to_float(G.scene->r.cfra);
/* if(ob->ipoflag & OB_OFFS_OB) ctime-= ob->sf; */
@@ -1762,7 +1857,7 @@ void do_ob_ipo(Object *ob)
float ctime;
unsigned int lay;
- if(ob->ipo==0) return;
+ if(ob->ipo==NULL) return;
/* do not set ob->ctime here: for example when parent in invisible layer */
@@ -1785,6 +1880,21 @@ void do_ob_ipo(Object *ob)
}
}
+void do_ob_ipodrivers(Object *ob, Ipo *ipo)
+{
+ IpoCurve *icu;
+ void *poin;
+ int type;
+
+ for(icu= ipo->curve.first; icu; icu= icu->next) {
+ if(icu->driver) {
+ icu->curval= eval_icu(icu, 0.0f);
+ poin= get_ipo_poin((ID *)ob, icu, &type);
+ if(poin) write_ipo_poin(poin, type, icu->curval);
+ }
+ }
+}
+
void do_seq_ipo(Sequence *seq)
{
float ctime, div;
@@ -1794,7 +1904,7 @@ void do_seq_ipo(Sequence *seq)
if(seq->ipo) {
ctime= frame_to_float(G.scene->r.cfra - seq->startdisp);
div= (seq->enddisp - seq->startdisp)/100.0f;
- if(div==0) return;
+ if(div==0.0) return;
/* 2nd field */
calc_ipo(seq->ipo, (ctime+0.5f)/div);
@@ -1813,7 +1923,7 @@ int has_ipo_code(Ipo *ipo, int code)
{
IpoCurve *icu;
- if(ipo==0) return 0;
+ if(ipo==NULL) return 0;
icu= ipo->curve.first;
while(icu) {
@@ -1924,7 +2034,7 @@ int calc_ipo_spec(Ipo *ipo, int adrcode, float *ctime)
{
IpoCurve *icu;
- if(ipo==0) return 0;
+ if(ipo==NULL) return 0;
icu= ipo->curve.first;
while(icu) {
@@ -1948,11 +2058,11 @@ void clear_delta_obipo(Ipo *ipo)
{
Object *ob;
- if(ipo==0) return;
+ if(ipo==NULL) return;
ob= G.main->object.first;
while(ob) {
- if(ob->id.lib==0) {
+ if(ob->id.lib==NULL) {
if(ob->ipo==ipo) {
memset(&ob->dloc, 0, 12);
memset(&ob->drot, 0, 12);
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index c32874f69c5..d0c0b1f9927 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -935,6 +935,8 @@ static int do_mesh_key(Mesh *me)
else {
ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0);
+ calc_ipo(me->key->ipo, ctime); /* also all relative key positions */
+
if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 29bfff8bc66..aa8efe61565 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -237,6 +237,7 @@ void unlink_object(Object *ob)
Scene *sce;
Curve *cu;
Tex *tex;
+ Ipo *ipo;
Group *group;
bConstraint *con;
int a;
@@ -308,7 +309,7 @@ void unlink_object(Object *ob)
for(a=0; a<MAX_MTEX; a++) {
if(mat->mtex[a] && ob==mat->mtex[a]->object) {
/* actually, test for lib here... to do */
- mat->mtex[a]->object= 0;
+ mat->mtex[a]->object= NULL;
}
}
@@ -319,7 +320,7 @@ void unlink_object(Object *ob)
tex= G.main->tex.first;
while(tex) {
if(tex->env) {
- if(tex->env->object == ob) tex->env->object= 0;
+ if(tex->env->object == ob) tex->env->object= NULL;
}
tex= tex->id.next;
}
@@ -333,10 +334,10 @@ void unlink_object(Object *ob)
/* worlds */
wrld= G.main->world.first;
while(wrld) {
- if(wrld->id.lib==0) {
+ if(wrld->id.lib==NULL) {
for(a=0; a<MAX_MTEX; a++) {
if(wrld->mtex[a] && ob==wrld->mtex[a]->object)
- wrld->mtex[a]->object =0;
+ wrld->mtex[a]->object= NULL;
}
}
@@ -346,12 +347,23 @@ void unlink_object(Object *ob)
/* scenes */
sce= G.main->scene.first;
while(sce) {
- if(sce->id.lib==0) {
- if(sce->camera==ob) sce->camera= 0;
+ if(sce->id.lib==NULL) {
+ if(sce->camera==ob) sce->camera= NULL;
}
sce= sce->id.next;
}
- /* keys */
+ /* ipos */
+ ipo= G.main->ipo.first;
+ while(ipo) {
+ if(ipo->id.lib==NULL) {
+ IpoCurve *icu;
+ for(icu= ipo->curve.first; icu; icu= icu->next) {
+ if(icu->driver && icu->driver->ob==ob)
+ icu->driver->ob= NULL;
+ }
+ }
+ ipo= ipo->id.next;
+ }
/* screens */
sc= G.main->screen.first;
@@ -365,11 +377,11 @@ void unlink_object(Object *ob)
View3D *v3d= (View3D*) sl;
if(v3d->camera==ob) {
- v3d->camera= 0;
+ v3d->camera= NULL;
if(v3d->persp>1) v3d->persp= 1;
}
if(v3d->localvd && v3d->localvd->camera==ob ) {
- v3d->localvd->camera= 0;
+ v3d->localvd->camera= NULL;
if(v3d->localvd->persp>1) v3d->localvd->persp= 1;
}
}
@@ -1285,8 +1297,9 @@ void where_is_object_time(Object *ob, float ctime)
if(ob==NULL) return;
+ /* this is needed to be able to grab objects with ipos, otherwise it always freezes them */
stime= bsystem_time(ob, 0, ctime, 0.0);
- if( stime != ob->ctime) {
+ if(stime != ob->ctime) {
ob->ctime= stime;
if(ob->ipo) {
@@ -1296,7 +1309,11 @@ void where_is_object_time(Object *ob, float ctime)
/* do constraint ipos ... */
do_constraint_channels(&ob->constraints, &ob->constraintChannels, ctime);
}
-
+ else {
+ /* but, the drivers have to be done */
+ if(ob->ipo) do_ob_ipodrivers(ob, ob->ipo);
+ }
+
if(ob->parent) {
par= ob->parent;