Next level of Proxy support for animation: Proxy for duplicated groups.
authorTon Roosendaal <ton@blender.org>
Tue, 14 Nov 2006 15:27:43 +0000 (15:27 +0000)
committerTon Roosendaal <ton@blender.org>
Tue, 14 Nov 2006 15:27:43 +0000 (15:27 +0000)
Notes:
- Only referenced groups (from other files)
- Only 1 group (no more duplicates using same group yet)
- Only Proxy working well for Armature or Empty

Is going to be reviewed in Plumiferos team; but target is that this will
solve a major animation pipeline bottleneck :)

Usage; select group, alt+ctrl+p, pick an object you want to proxify.

source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/group.c
source/blender/blenkernel/intern/object.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_object_types.h
source/blender/src/editobject.c
source/blender/src/transform_generics.c

index 26f129ae2a5103bddf88dd870f5174885a3adaf5..fde33723cc47fe1b333e0418eae3f733ba474124 100644 (file)
 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;
 struct BoundBox;
 struct View3D;
 struct SoftBody;
+struct Group;
 
 void clear_workob(void);
 void copy_baseflags(void);
@@ -55,7 +66,7 @@ void free_object(struct Object *ob);
 void object_free_display(struct Object *ob);
 void object_free_modifiers(struct Object *ob);
 
-void object_make_proxy(struct Object *ob, struct Object *target);
+void object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob);
 
 void unlink_object(struct Object *ob);
 int exist_object(struct Object *obtest);
index 59293d3c48ae118b1e160ebef1e9e848d060005a..bf1b573afe5930c340278b6c9d376df2550bbc11 100644 (file)
@@ -183,7 +183,7 @@ void group_tag_recalc(Group *group)
        
        for(go= group->gobject.first; go; go= go->next) {
                if(go->ob) 
-                       go->ob->recalc= OB_RECALC;
+                       go->ob->recalc= go->recalc;
        }
 }
 
index 0e98d494c800eeadcc7d7c444d374b1d510ce525..f2815d428f8e074c5544083111224c8df756defc 100644 (file)
@@ -893,7 +893,6 @@ Object *copy_object(Object *ob)
        
        if(ob->bb) obn->bb= MEM_dupallocN(ob->bb);
        obn->path= NULL;
-       obn->proxy= NULL;
        obn->flag &= ~OB_FROMGROUP;
        
        copy_effects(&obn->effect, &ob->effect);
@@ -1047,8 +1046,9 @@ void make_local_object(Object *ob)
 
 /* proxy rule: lib_object->proxy == 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 */
 
-void object_make_proxy(Object *ob, Object *target)
+void object_make_proxy(Object *ob, Object *target, Object *gob)
 {
        /* paranoia checks */
        if(ob->id.lib || target->id.lib==NULL) {
@@ -1057,14 +1057,22 @@ void object_make_proxy(Object *ob, Object *target)
        }
        
        ob->proxy= target;
-       target->proxy= ob;
+       ob->proxy_group= gob;
+       id_lib_extern(&target->id);
        
        ob->recalc= target->recalc= OB_RECALC;
        
        /* copy transform */
-       VECCOPY(ob->loc, target->loc);
-       VECCOPY(ob->rot, target->rot);
-       VECCOPY(ob->size, target->size);
+       if(gob) {
+               VECCOPY(ob->loc, gob->loc);
+               VECCOPY(ob->rot, gob->rot);
+               VECCOPY(ob->size, gob->size);
+       }
+       else {
+               VECCOPY(ob->loc, target->loc);
+               VECCOPY(ob->rot, target->rot);
+               VECCOPY(ob->size, target->size);
+       }
        
        ob->parent= target->parent;     /* libdata */
        Mat4CpyMat4(ob->parentinv, target->parentinv);
@@ -1649,7 +1657,6 @@ void solve_tracking (Object *ob, float targetmat[][4])
 
 void where_is_object(Object *ob)
 {
-       
        where_is_object_time(ob, (float)G.scene->r.cfra);
 }
 
@@ -1949,9 +1956,10 @@ void minmax_object(Object *ob, float *min, float *max)
        }
 }
 
-/* proxy rule: lib_object->proxy == the one we borrow from, set on read */
+/* 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 */
 
+/* function below is polluted with proxy exceptions, cleanup will follow! */
 
 /* the main object update call, for object matrix, constraints, keys and displist (modifiers) */
 /* requires flags to be set! */
@@ -1960,8 +1968,14 @@ void object_handle_update(Object *ob)
        if(ob->recalc & OB_RECALC) {
                
                if(ob->recalc & OB_RECALC_OB) {
-                       if(ob->id.lib && ob->proxy)
-                               Mat4CpyMat4(ob->obmat, ob->proxy->obmat);
+                       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);
+                               }
+                               else
+                                       Mat4CpyMat4(ob->obmat, ob->proxy->obmat);
+                       }
                        else
                                where_is_object(ob);
                }
@@ -1988,7 +2002,7 @@ void object_handle_update(Object *ob)
                                if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC))
                                        armature_rebuild_pose(ob, ob->data);
                                
-                               if(ob->id.lib && ob->proxy)
+                               if(OB_COPY_PROXY(ob))
                                        copy_pose_result(ob->pose, ob->proxy->pose);
                                else {
                                        do_all_pose_actions(ob);
@@ -1997,11 +2011,21 @@ void object_handle_update(Object *ob)
                        }
                }
        
-               if(ob->id.lib==NULL && ob->proxy)
+               /* the no-group proxy case, we call update */
+               if(OB_DO_PROXY(ob)) {
+                       /* set pointer in library proxy target, for copying, but restore it */
+                       ob->proxy->proxy= ob;
                        object_handle_update(ob->proxy);
-               
+               }
+       
                ob->recalc &= ~OB_RECALC;
        }
+
+       /* 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);
+       }
 }
 
 
index fd80536dea1718682e6bf1aee548114d7335ec4c..24e8204ef9512cdf710502d4b4e59991b3ea4ae9 100644 (file)
@@ -2425,11 +2425,12 @@ static void lib_link_object(FileData *fd, Main *main)
                        else {
                                ob->proxy= newlibadr_us(fd, ob->id.lib, ob->proxy);
                                if(ob->proxy) {
+                                       /* this triggers object_update to always use a copy */
                                        ob->proxy->proxy= ob;
                                        /* force proxy updates after load/undo, a bit weak */
                                        ob->recalc= ob->proxy->recalc= OB_RECALC;
                                }
-                               ob->proxy_group= newlibadr_us(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);
index 8a4ef6cda37c29be530c3b5e1b78e6bb7236398a..78908a33faa209406a53089a7ac5f0db30627aaa 100644 (file)
@@ -86,8 +86,7 @@ typedef struct Object {
        int par1, par2, par3;   /* can be vertexnrs */
        char parsubstr[32];     /* String describing subobject info */
        void *pardata;
-       struct Object *parent, *track, *proxy;
-       struct Group *proxy_group;
+       struct Object *parent, *track, *proxy, *proxy_group;
        struct Ipo *ipo;
        struct Path *path;
        struct BoundBox *bb;
index 5d578f47297fc4ffc26cecbd3b6dfad97f3086f9..63dadb6e6c141d3c01f10fe04fe4826cbc1b45ac 100644 (file)
@@ -1245,24 +1245,71 @@ void make_vertex_parent(void)
        /* BIF_undo_push(str); not, conflicts with editmode undo... */
 }
 
+static Object *group_objects_menu(Group *group)
+{
+       GroupObject *go;
+       int len= 0;
+       short a, nr;
+       char *str;
+               
+       for(go= group->gobject.first; go; go= go->next) {
+               if(go->ob)
+                       len++;
+       }
+       if(len==0) return NULL;
+       
+       str= MEM_callocN(40+32*len, "menu");
+       
+       strcpy(str, "Select a Group Object %t");
+       a= strlen(str);
+       for(nr=1, go= group->gobject.first; go; go= go->next, nr++) {
+               a+= sprintf(str+a, "|%s %%x%d", go->ob->id.name+2, nr);
+       }
+       
+       a= pupmenu_col(str, 20);
+       MEM_freeN(str);
+       if(a>0) {
+               go= BLI_findlink(&group->gobject, a-1);
+               return go->ob;
+       }
+       return NULL;
+}
+
+
 /* adds empty object to become local replacement data of a library-linked object */
 void make_proxy(void)
 {
        Object *ob= OBACT;
+       Object *gob= NULL;
        
        if(G.scene->id.lib) return;
        if(ob==NULL) return;
        
-       if(ob->id.lib==NULL) {
-               error("Can not make proxy for non-linked object");
+       
+       if(ob->dup_group && ob->dup_group->id.lib) {
+               gob= ob;
+               /* gives menu with list of objects in group */
+               ob= group_objects_menu(ob->dup_group);
        }
-       else if(okee("Make Proxy Object")) {
+       else if(ob->id.lib) {
+               if(okee("Make Proxy Object")==0)
+               return;
+       }
+       else {
+               error("Can only make proxy for a referenced object or group");
+               return;
+       }
+       
+       if(ob) {
                Object *newob;
                Base *newbase, *oldbase= BASACT;
                char name[32];
                
                newob= add_object(OB_EMPTY);
-               strcpy(name, ob->id.name+2);
+               if(gob)
+                       strcpy(name, gob->id.name+2);
+               else
+                       strcpy(name, ob->id.name+2);
                strcat(name, "_proxy");
                rename_id(&newob->id, name);
                
@@ -1272,12 +1319,14 @@ void make_proxy(void)
                newob->lay= newbase->lay;
                
                /* remove base, leave user count of object, it gets linked in object_make_proxy */
-               BLI_remlink(&G.scene->base, oldbase);
-               MEM_freeN(oldbase);
-               
-               object_make_proxy(newob, ob);
+               if(gob==NULL) {
+                       BLI_remlink(&G.scene->base, oldbase);
+                       MEM_freeN(oldbase);
+               }               
+               object_make_proxy(newob, ob, gob);
                
                DAG_scene_sort(G.scene);
+               DAG_object_flush_update(G.scene, newob, OB_RECALC);
                allqueue(REDRAWALL, 0);
                BIF_undo_push("Make Proxy Object");
        }
@@ -4718,19 +4767,21 @@ void adduplicate(int mode, int dupflag)
        base= FIRSTBASE;
        while(base) {
                if TESTBASELIB(base) {
-                       relink_constraints(&base->object->constraints);
-                       if (base->object->pose){
+                       ob= base->object;
+                       relink_constraints(&ob->constraints);
+                       if (ob->pose){
                                bPoseChannel *chan;
-                               for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){
+                               for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
                                        relink_constraints(&chan->constraints);
                                }
                        }
-                       modifiers_foreachIDLink(base->object,
-                                               adduplicate__forwardModifierLinks, NULL);
-                       ID_NEW(base->object->parent);
-                       ID_NEW(base->object->track);
+                       modifiers_foreachIDLink(ob, adduplicate__forwardModifierLinks, NULL);
+                       ID_NEW(ob->parent);
+                       ID_NEW(ob->track);
+                       ID_NEW(ob->proxy);
+                       ID_NEW(ob->proxy_group);
                        
-                       for(strip= base->object->nlastrips.first; strip; strip= strip->next) {
+                       for(strip= ob->nlastrips.first; strip; strip= strip->next) {
                                bActionModifier *amod;
                                for(amod= strip->modifiers.first; amod; amod= amod->next)
                                        ID_NEW(amod->ob);
index f9e75d2336a5340e040fdad0e3e88fba4a6722fb..1435cbff47e6903c27f127fce3522c024ded8bfb 100755 (executable)
@@ -72,6 +72,7 @@
 #include "BKE_displist.h"
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
+#include "BKE_group.h"
 #include "BKE_ipo.h"
 #include "BKE_lattice.h"
 #include "BKE_mesh.h"
@@ -355,6 +356,8 @@ void recalcData(TransInfo *t)
                        /* proxy exception */
                        if(ob->proxy)
                                ob->proxy->recalc |= ob->recalc;
+                       if(ob->proxy_group)
+                               group_tag_recalc(ob->proxy_group->dup_group);
                } 
        }