Proxy Objects revisited!

The first incarnation assumed that proxies were local objects per
definition. Unfortunately that makes it impossible to - for example -
reference-link an entire Scene with proxies, to be used as a special
character set.

This commit makes the proxy implementation also a bit more clear.

Related work: the scene-sets were not executed fully or correctly for
the dependency graph. That happens now (in 3d view) as well.
This commit is contained in:
Ton Roosendaal 2006-11-30 15:54:21 +00:00
parent 9711d54fb7
commit 342c900220
13 changed files with 98 additions and 84 deletions

@ -38,16 +38,6 @@
extern "C" {
#endif
/* defines now, might become functions */
/* proxy rule: lib_object->proxy == the one we borrow from, only set temporal and cleared here */
/* local_object->proxy == pointer to library object, saved in files and read */
#define OB_COPY_PROXY(a) a->id.lib && a->proxy
#define OB_IS_PROXY(a) a->id.lib==NULL && a->proxy
#define OB_DO_PROXY(a) a->id.lib==NULL && a->proxy && a->proxy_group==NULL
struct Base;
struct Object;
struct Camera;

@ -52,7 +52,7 @@ struct QuicktimeCodecData;
if(seqar) MEM_freeN(seqar); \
}
/* note; doesn't work when scene is empty */
#define SETLOOPER(s, b) sce= s, b= sce->base.first; b; b= (b->next?b->next:sce->set?(sce=sce->set)->base.first:NULL)

@ -665,7 +665,6 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
Mat4Invert(obinv, target->obmat);
Mat4CpyMat4(premat, target->obmat);
Mat4MulMat4(postmat, armOb->obmat, obinv);
Mat4Invert(premat, postmat);
/* bone defmats are already in the channels, chan_mat */
@ -967,21 +966,25 @@ void where_is_armature (bArmature *arm)
}
}
/* if bone layer is protected, copy the data from proxy->pose */
static void pose_proxy_synchronize(Object *ob, Object *proxy, int layer_protected)
/* if bone layer is protected, copy the data from from->pose */
static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected)
{
bPose *pose= ob->pose, *proxypose= proxy->pose;
bPose *pose= ob->pose, *frompose= from->pose;
bPoseChannel *pchan, *pchanp, pchanw;
bConstraint *con;
char *str;
if(proxypose==NULL) return;
if(frompose==NULL) return;
/* exception, armature local layer should be proxied too */
if(pose->proxy_layer)
((bArmature *)ob->data)->layer= pose->proxy_layer;
/* clear all transformation values from library */
rest_pose(proxypose);
rest_pose(frompose);
pchan= pose->chanbase.first;
pchanp= proxypose->chanbase.first;
pchanp= frompose->chanbase.first;
for(; pchan && pchanp; pchan= pchan->next, pchanp= pchanp->next) {
if(pchan->bone->layer & layer_protected) {
@ -997,7 +1000,7 @@ static void pose_proxy_synchronize(Object *ob, Object *proxy, int layer_protecte
copy_constraints(&pchanw.constraints, &pchanp->constraints);
for(con= pchanw.constraints.first; con; con= con->next) {
if(proxy==get_constraint_target(con, &str))
if(from==get_constraint_target(con, &str))
set_constraint_target(con, ob, NULL);
}
@ -1064,10 +1067,10 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
BLI_freelinkN(&pose->chanbase, pchan);
}
}
// printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
// printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
/* synchronize protected layers with proxy */
if(OB_IS_PROXY(ob))
if(ob->proxy)
pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected);
update_pose_constraint_flags(ob->pose); // for IK detection for example

@ -71,6 +71,7 @@
#include "BKE_mball.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
#include "MEM_guardedalloc.h"
@ -466,7 +467,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int
dag_add_relation(dag,node2,node,DAG_RL_OB_OB);
addtoroot = 0;
}
if (ob->id.lib==NULL && ob->proxy) {
if (ob->proxy) {
node2 = dag_get_node(dag, ob->proxy);
dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA|DAG_RL_OB_OB);
/* inverted relation, so addtoroot shouldn't be set to zero */
@ -1792,15 +1793,16 @@ static void dag_object_time_update_flags(Object *ob)
}
/* flag all objects that need recalc, for changes in time for example */
void DAG_scene_update_flags(Scene *sce, unsigned int lay)
void DAG_scene_update_flags(Scene *scene, unsigned int lay)
{
Base *base;
Object *ob;
Group *group;
GroupObject *go;
Scene *sce;
/* set ob flags where animated systems are */
for(base= sce->base.first; base; base= base->next) {
for(SETLOOPER(scene, base)) {
ob= base->object;
/* now if DagNode were part of base, the node->lay could be checked... */
@ -1810,8 +1812,7 @@ void DAG_scene_update_flags(Scene *sce, unsigned int lay)
/* handled in next loop */
if(ob->dup_group)
ob->dup_group->id.flag |= LIB_DOIT;
}
}
/* we do groups each once */
for(group= G.main->group.first; group; group= group->id.next) {
@ -1822,25 +1823,26 @@ void DAG_scene_update_flags(Scene *sce, unsigned int lay)
}
}
DAG_scene_flush_update(sce, lay);
for(sce= scene; sce; sce= sce->set)
DAG_scene_flush_update(sce, lay);
/* test: set time flag, to disable baked systems to update */
for(base= sce->base.first; base; base= base->next) {
for(SETLOOPER(scene, base)) {
ob= base->object;
if(ob->recalc)
ob->recalc |= OB_RECALC_TIME;
}
/* hrmf... an exception to look at once, for invisible camera object we do it over */
if(sce->camera)
dag_object_time_update_flags(sce->camera);
if(scene->camera)
dag_object_time_update_flags(scene->camera);
/* and store the info in groupobject */
for(group= G.main->group.first; group; group= group->id.next) {
if(group->id.flag & LIB_DOIT) {
for(go= group->gobject.first; go; go= go->next) {
go->recalc= go->ob->recalc;
// printf("ob %s recalc %d\n", go->ob->id.name, go->recalc);
// printf("ob %s recalc %d\n", go->ob->id.name, go->recalc);
}
group->id.flag &= ~LIB_DOIT;
}

@ -753,8 +753,8 @@ static float eval_driver(IpoDriver *driver, float ipotime)
Object *ob= driver->ob;
if(ob==NULL) return 0.0f;
if(ob->id.lib && ob->proxy)
ob= ob->proxy;
if(ob->proxy_from)
ob= ob->proxy_from;
if(driver->blocktype==ID_OB) {
/* depsgraph failure; ob ipos are calculated in where_is_object, this might get called too late */

@ -273,6 +273,10 @@ void unlink_object(Object *ob)
while(obt) {
if(obt->proxy==ob)
obt->proxy= NULL;
if(obt->proxy_from==ob) {
obt->proxy_from= NULL;
obt->recalc |= OB_RECALC_OB;
}
if(obt->proxy_group==ob)
obt->proxy_group= NULL;
@ -992,7 +996,8 @@ void make_local_object(Object *ob)
*/
if(ob->id.lib==NULL) return;
if(ob->proxy) return;
ob->proxy= ob->proxy_from= NULL;
if(ob->id.us==1) {
ob->id.lib= NULL;
@ -1047,7 +1052,7 @@ void make_local_object(Object *ob)
/* *************** PROXY **************** */
/* proxy rule: lib_object->proxy == the one we borrow from, set temporally while object_update */
/* proxy rule: lib_object->proxy_from == the one we borrow from, set temporally while object_update */
/* local_object->proxy == pointer to library object, saved in files and read */
/* local_object->proxy_group == pointer to group dupli-object, saved in files and read */
@ -1499,7 +1504,7 @@ void where_is_object_time(Object *ob, float ctime)
pushdata(par, sizeof(Object));
pop= 1;
if(par->id.lib && par->proxy); // was a copied matrix, no where_is! bad...
if(par->proxy_from); // was a copied matrix, no where_is! bad...
else where_is_object_time(par, ctime);
}
@ -1966,8 +1971,8 @@ void minmax_object(Object *ob, float *min, float *max)
}
}
/* proxy rule: lib_object->proxy == the one we borrow from, only set temporal and cleared here */
/* local_object->proxy == pointer to library object, saved in files and read */
/* proxy rule: lib_object->proxy_from == the one we borrow from, only set temporal and cleared here */
/* local_object->proxy == pointer to library object, saved in files and read */
/* function below is polluted with proxy exceptions, cleanup will follow! */
@ -1978,13 +1983,19 @@ void object_handle_update(Object *ob)
if(ob->recalc & OB_RECALC) {
if(ob->recalc & OB_RECALC_OB) {
if(OB_COPY_PROXY(ob)) {
if(ob->proxy->proxy_group) {/* transform proxy into group space */
Mat4Invert(ob->proxy->proxy_group->imat, ob->proxy->proxy_group->obmat);
Mat4MulMat4(ob->obmat, ob->proxy->obmat, ob->proxy->proxy_group->imat);
// printf("recalcob %s\n", ob->id.name+2);
/* handle proxy copy for target */
if(ob->id.lib && ob->proxy_from) {
// printf("ob proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
if(ob->proxy_from->proxy_group) {/* transform proxy into group space */
Object *obg= ob->proxy_from->proxy_group;
Mat4Invert(obg->imat, obg->obmat);
Mat4MulMat4(ob->obmat, ob->proxy_from->obmat, obg->imat);
}
else
Mat4CpyMat4(ob->obmat, ob->proxy->obmat);
Mat4CpyMat4(ob->obmat, ob->proxy_from->obmat);
}
else
where_is_object(ob);
@ -2012,8 +2023,10 @@ void object_handle_update(Object *ob)
if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC))
armature_rebuild_pose(ob, ob->data);
if(OB_COPY_PROXY(ob))
copy_pose_result(ob->pose, ob->proxy->pose);
if(ob->id.lib && ob->proxy_from) {
copy_pose_result(ob->pose, ob->proxy_from->pose);
// printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
}
else {
do_all_pose_actions(ob);
where_is_pose(ob);
@ -2022,9 +2035,10 @@ void object_handle_update(Object *ob)
}
/* the no-group proxy case, we call update */
if(OB_DO_PROXY(ob)) {
if(ob->proxy && ob->proxy_group==NULL) {
/* set pointer in library proxy target, for copying, but restore it */
ob->proxy->proxy= ob;
ob->proxy->proxy_from= ob;
// printf("call update, lib ob %s proxy %s\n", ob->proxy->id.name, ob->id.name);
object_handle_update(ob->proxy);
}
@ -2032,9 +2046,9 @@ void object_handle_update(Object *ob)
}
/* the case when this is a group proxy, object_update is called in group.c */
if(OB_IS_PROXY(ob)) {
ob->proxy->proxy= ob;
//printf("set proxy pointer for later group stuff %s\n", ob->id.name);
if(ob->proxy) {
ob->proxy->proxy_from= ob;
// printf("set proxy pointer for later group stuff %s\n", ob->id.name);
}
}

@ -277,29 +277,28 @@ void set_scene_bg(Scene *sce)
scene_check_setscene(G.scene);
/* deselect objects (for dataselect) */
ob= G.main->object.first;
while(ob) {
for(ob= G.main->object.first; ob; ob= ob->id.next)
ob->flag &= ~(SELECT|OB_FROMGROUP);
ob= ob->id.next;
}
/* group flags again */
group= G.main->group.first;
while(group) {
for(group= G.main->group.first; group; group= group->id.next) {
go= group->gobject.first;
while(go) {
if(go->ob) go->ob->flag |= OB_FROMGROUP;
go= go->next;
}
group= group->id.next;
}
/* sort baselist */
DAG_scene_sort(sce);
/* ensure dags are built for sets */
for(sce= sce->set; sce; sce= sce->set)
if(sce->theDag==NULL)
DAG_scene_sort(sce);
/* copy layers and flags from bases to objects */
base= G.scene->base.first;
while(base) {
for(base= G.scene->base.first; base; base= base->next) {
ob= base->object;
ob->lay= base->lay;
@ -311,7 +310,6 @@ void set_scene_bg(Scene *sce)
ob->flag= base->flag;
ob->ctime= -1234567.0; /* force ipo to be calculated later */
base= base->next;
}
/* no full animation update, this to enable render code to work (render code calls own animation updates) */

@ -486,7 +486,7 @@ static Main *blo_find_main(ListBase *mainlist, const char *name, const char *rel
char *libname= (m->curlib)?m->curlib->filename:m->name;
if (BLI_streq(name1, libname)) {
printf("blo_find_main: found library %s\n", libname);
if(G.f & G_DEBUG) printf("blo_find_main: found library %s\n", libname);
return m;
}
}
@ -500,7 +500,7 @@ static Main *blo_find_main(ListBase *mainlist, const char *name, const char *rel
m->curlib= lib;
printf("blo_find_main: added new lib %s\n", name);
if(G.f & G_DEBUG) printf("blo_find_main: added new lib %s\n", name);
return m;
}
@ -2588,20 +2588,23 @@ static void lib_link_object(FileData *fd, Main *main)
ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
if(ob->id.lib) {
/* no proxy in library data, is default local data */
ob->proxy= NULL; ob->proxy_group= NULL;
}
else {
ob->proxy= newlibadr_us(fd, ob->id.lib, ob->proxy);
if(ob->proxy) {
ob->proxy= newlibadr_us(fd, ob->id.lib, ob->proxy);
if(ob->proxy) {
/* paranoia check, actually a proxy_from pointer should never be written... */
if(ob->proxy->id.lib==NULL) {
ob->proxy->proxy_from= NULL;
ob->proxy= NULL;
}
else {
/* this triggers object_update to always use a copy */
ob->proxy->proxy= ob;
ob->proxy->proxy_from= ob;
/* force proxy updates after load/undo, a bit weak */
ob->recalc= ob->proxy->recalc= OB_RECALC;
}
ob->proxy_group= newlibadr(fd, ob->id.lib, ob->proxy_group);
}
}
ob->proxy_group= newlibadr(fd, ob->id.lib, ob->proxy_group);
poin= ob->data;
ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
@ -6335,13 +6338,13 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
if(id==0) {
read_libblock(fd, mainvar, bhead, LIB_READ+LIB_INDIRECT, NULL);
printf("expand_doit: other lib %s\n", lib->name);
if(G.f & G_DEBUG) printf("expand_doit: other lib %s\n", lib->name);
}
else {
//oldnewmap_insert(fd->libmap, bhead->old, id, 1);
change_idid_adr_fd(fd, bhead->old, id);
printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
if(G.f & G_DEBUG) printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
}
}
}
@ -6727,6 +6730,11 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
if(ob->dup_group)
expand_doit(fd, mainvar, ob->dup_group);
if(ob->proxy)
expand_doit(fd, mainvar, ob->proxy);
if(ob->proxy_group)
expand_doit(fd, mainvar, ob->proxy_group);
sens= ob->sensors.first;
while(sens) {
@ -7246,7 +7254,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
if(fd==NULL) {
BlendReadError err;
printf("read_libraries: lib %s\n", mainptr->curlib->name);
printf("read library: lib %s\n", mainptr->curlib->name);
fd= blo_openblenderfile(mainptr->curlib->filename, &err);
if (fd) {
if (fd->libmap)

@ -82,12 +82,10 @@ typedef struct bPoseChannel {
typedef struct bPose{
ListBase chanbase;
int flag;
short flag, proxy_layer; /* proxy layer: copy from armature, gets synced */
float ctime; /* local action time of this pose */
float stride_offset[3]; /* applied to object */
float cyclic_offset[3]; /* result of match and cycles, applied in where_is_pose() */
short proxy_layer, pad1;
int pad2;
} bPose;
typedef struct bActionChannel {

@ -90,7 +90,10 @@ typedef struct Object {
int par1, par2, par3; /* can be vertexnrs */
char parsubstr[32]; /* String describing subobject info */
void *pardata;
struct Object *parent, *track, *proxy, *proxy_group;
struct Object *parent, *track;
/* if ob->proxy (or proxy_group), this object is proxy for object ob->proxy */
/* proxy_from is set in target back to the proxy. */
struct Object *proxy, *proxy_group, *proxy_from;
struct Ipo *ipo;
struct Path *path;
struct BoundBox *bb;

@ -2768,7 +2768,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
/* update all objects, ipos, matrices, displists, etc. Flags set by depgraph or manual,
no layer check here, gets correct flushed */
for(base= G.scene->base.first; base; base= base->next) {
for(SETLOOPER(G.scene, base)) {
object_handle_update(base->object); // bke_object.h
}
@ -2857,8 +2857,6 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
for(SETLOOPER(G.scene->set, base)) {
if(v3d->lay & base->lay) {
object_handle_update(base->object);
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
draw_object(base, DRAW_CONSTCOLOR);

@ -620,7 +620,7 @@ void add_constraint(int only_IK)
if(pchanact==NULL) return;
/* check protection */
if(OB_IS_PROXY(ob) && (pchanact->bone->layer & arm->layer_protected)) {
if(ob->proxy && (pchanact->bone->layer & arm->layer_protected)) {
error("Bone is Proxy protected");
return;
}

@ -177,7 +177,7 @@ static int pose_has_protected_selected(Object *ob, int only_selected)
{
/* check protection */
if(OB_IS_PROXY(ob)) {
if(ob->proxy) {
bPoseChannel *pchan;
bArmature *arm= ob->data;