Big commit with work on Groups & Libraries:
authorTon Roosendaal <ton@blender.org>
Sun, 11 Dec 2005 13:23:30 +0000 (13:23 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 11 Dec 2005 13:23:30 +0000 (13:23 +0000)
-> Any Group Duplicate now can get local timing and local NLA override. This
   enables to control the entire animation system of the Group.

Two methods for this have been implemented.
1) The quick way: just give the duplicator a "Startframe" offset.
2) Advanced: in the NLA Editor you can add ActionStrips to the duplicator
   to override NLA/action of any Grouped Object.

For "Group NLA" to work, an ActionStrip needs to know which Object in a
group it controls. On adding a strip, the code checks if an Action was
already used by an Object in the Group, and assigns it automatic to that
Object.
You can also set this in the Nkey "Properties" panel for the strip.

Change in NLA: the SHIFT+A "Add strip" command now always adds strips to
the active Object. (It used to check where mouse was). This allows to add
NLA strips to Objects that didn't have actions/nla yet.

Important note: In Blender, duplicates are fully procedural and generated
on the fly for each redraw. This means that redraw speed equals to stepping
through frames, when using animated Duplicated Groups.

-> Recoded entire duplicator system

The old method was antique and clumsy, using globals and full temporal
copies of Object. The new system is nicer in control, faster, and since it
doesn't use temporal object copies anymore, it works better with Derived
Mesh and DisplayList and rendering.

By centralizing the code for duplicating, more options can be easier added.
Features to note:

- Duplicates now draw selected/unselected based on its Duplicator setting.
- Same goes for the drawtype (wire, solid, selection outline, etc)
- Duplicated Groups can be normally selected too

Bonus goodie: SHIFT+A (Toolbox) now has entry "Add group" too, with a
listing of all groups, allowing to add Group instances immediate.

-> Library System

- SHIFT+F4 data browse now shows the entire path for linked data
- Outliner draws Library Icons to denote linked data
- Outliner operation added: "Make Local" for library data.
- Outliner now also draws Groups in regular view, allowing to unlink too.

-> Fixes

- depsgraph missed signal update for bone-parented Objects
- on reading file, the entire database was tagged to "recalc" fully,
  causing unnecessary slowdown on reading.

Might have missed stuff... :)

36 files changed:
source/blender/blenkernel/BKE_anim.h
source/blender/blenkernel/BKE_depsgraph.h
source/blender/blenkernel/BKE_displist.h
source/blender/blenkernel/BKE_font.h
source/blender/blenkernel/BKE_group.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/font.c
source/blender/blenkernel/intern/group.c
source/blender/blenkernel/intern/mball.c
source/blender/blenkernel/intern/nla.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/include/BIF_outliner.h
source/blender/include/BSE_drawview.h
source/blender/makesdna/DNA_group_types.h
source/blender/makesdna/DNA_nla_types.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/render/intern/source/rendercore.c
source/blender/renderconverter/intern/convertBlenderScene.c
source/blender/src/butspace.c
source/blender/src/drawnla.c
source/blender/src/drawobject.c
source/blender/src/drawview.c
source/blender/src/editgroup.c
source/blender/src/editnla.c
source/blender/src/editobject.c
source/blender/src/filesel.c
source/blender/src/header_info.c
source/blender/src/outliner.c
source/blender/src/toolbox.c
source/blender/src/view.c

index e4cd8e39acad62a79771c917e5bc85e195ce9fbc..69fb83aac3075dcdd4f16418ab5309e06cf420d4 100644 (file)
@@ -39,12 +39,18 @@ struct Object;
 struct PartEff;
 struct Scene;
 
+typedef struct DupliObject {
+       struct DupliObject *next, *prev;
+       struct Object *ob;
+       float mat[4][4], omat[4][4];
+} DupliObject;
+
 void free_path(struct Path *path);
 void calc_curvepath(struct Object *ob);
 int interval_test(int min, int max, int p1, int cycl);
 int where_on_path(struct Object *ob, float ctime, float *vec, float *dir);
-void free_duplilist(void);
-void make_duplilist(struct Scene *sce, struct Object *ob);
+
+ListBase *object_duplilist(struct Scene *sce, struct Object *ob);
 int count_duplilist(struct Object *ob);
 
 #endif
index 5dd820d5a79a7f89a487c526bc98556d7fbb6afb..294f61e54bdc0acb36c3c9441f550b3e0fea883a 100644 (file)
@@ -109,5 +109,5 @@ void        DAG_scene_flush_update(struct Scene *sce, unsigned int lay);
 void   DAG_object_flush_update(struct Scene *sce, struct Object *ob, short flag);
 
 void   DAG_pose_sort(struct Object *ob);
-
+               
 #endif
index 2dcf4bfe1be60d100da34b268204c20e2ad219b4..05a1cfc5376941c3025549e80da8d78c8a2257ff 100644 (file)
@@ -75,6 +75,7 @@ if( (cyclv) && a==sizev-1) {                      \
 
 /* prototypes */
 
+struct Base;
 struct Object;
 struct Curve;
 struct ListBase;
@@ -144,7 +145,7 @@ extern void makeDispListMesh(struct Object *ob);
 extern void makeDispListSurf(struct Object *ob, struct ListBase *dispbase, int forRender);
 extern void makeDispListCurveTypes(struct Object *ob, int forOrco);
 extern void makeDispListMBall(struct Object *ob);
-extern void shadeDispList(struct Object *ob);
+extern void shadeDispList(struct Base *base);
 void freefastshade(void);
 void imagestodisplist(void);
 void reshadeall_displist(void);
index 00a994672bef1176460ef040debb9f156992664e..05621a4d9b2c53934dc052fa31b7afff75f5aeaa 100644 (file)
@@ -41,6 +41,13 @@ struct Object;
 struct Curve;
 struct objfnt;
 
+struct chartrans {
+       float xof, yof;
+       float rot;
+       short linenr,charnr;
+       char dobreak;
+};
+
 typedef struct SelBox {
        float x, y, w, h;
 } SelBox;
@@ -55,7 +62,7 @@ struct VFont *load_vfont(char *name);
 struct chartrans *text_to_curve(struct Object *ob, int mode);
 int style_to_sel(int style, int toggle);
 int mat_to_sel(void);
-void font_duplilist(struct Object *par);
+
 int getselection(int *start, int *end);
 
 void chtoutf8(unsigned long c, char *o);
index 2d42a9e284cce63771174112edfa7d18b8e0fe4f..db4c83040a8d3a3cab096173329d8e2cf2aab17d 100644 (file)
 struct Group;
 struct GroupObject;
 struct Object;
+struct bAction;
 
-void free_group_object(struct GroupObject *go);
-void free_group(struct Group *group);
+void           free_group_object(struct GroupObject *go);
+void           free_group(struct Group *group);
+void           unlink_group(struct Group *group);
 struct Group *add_group(void);
-void add_to_group(struct Group *group, struct Object *ob);
-void rem_from_group(struct Group *group, struct Object *ob);
+void           add_to_group(struct Group *group, struct Object *ob);
+void           rem_from_group(struct Group *group, struct Object *ob);
 struct Group *find_group(struct Object *ob);
-int object_in_group(struct Object *ob, struct Group *group);
-void group_tag_recalc(struct Group *group);
+int                    object_in_group(struct Object *ob, struct Group *group);
+
+void           group_tag_recalc(struct Group *group);
+void           group_handle_recalc_and_update(struct Object *parent, struct Group *group);
+struct Object *group_get_member_with_action(struct Group *group, struct bAction *act);
 
 #endif
 
index 04c4d180927141d9ed11c37d6f6ede86f8c9eec8..a0713d3a7ddb89aa2d14d1a1489464776be4c74c 100644 (file)
@@ -1823,8 +1823,6 @@ static void mesh_build_data(Object *ob)
        Mesh *me = ob->data;
        float min[3], max[3];
 
-       if(ob->flag&OB_FROMDUPLI) return;
-
        clear_mesh_caches(ob);
 
        if(ob!=G.obedit) {
index d5fa6958dff4c966a557c6a14de407f0dcb71f13..211e552f493ca2f892c1d4ce6c530c7c848a2c59 100644 (file)
@@ -816,7 +816,7 @@ static void do_nla(Object *ob, int blocktype)
                        actlength = strip->actend-strip->actstart;
                        striptime = (G.scene->r.cfra-(strip->start)) / length;
                        stripframe = (G.scene->r.cfra-(strip->start)) ;
-
+                       
                        if (striptime>=0.0){
                                
                                if(blocktype==ID_AR) 
@@ -979,6 +979,7 @@ void do_all_pose_actions(Object *ob)
 void do_all_object_actions(Object *ob)
 {
        if(ob==NULL) return;
+       if(ob->dup_group) return;       /* prevent conflicts, might add smarter check later */
        
        /* Do local action */
        if(ob->action && ((ob->nlaflag & OB_NLA_OVERRIDE)==0 || ob->nlastrips.first==NULL) ) {
index 5b5f1fabdf27a02dd7dd5ed944d21344acfeb2fb..5700be0fcbc6f25e8e7b6b5c6f005457dd6fdf0f 100644 (file)
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_view3d_types.h"
+#include "DNA_vfont_types.h"
 
+#include "BKE_anim.h"
 #include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_font.h"
+#include "BKE_group.h"
 #include "BKE_global.h"
-#include "BKE_utildefines.h"
-#include "BKE_anim.h"
 #include "BKE_ipo.h"
-#include "BKE_object.h"
-#include "BKE_displist.h"
 #include "BKE_key.h"
-#include "BKE_font.h"
-#include "BKE_effect.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
 
 #include "BKE_bad_level_calls.h"
 
@@ -272,53 +275,40 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir)        /* returns OK
        return 1;
 }
 
-static Object *new_dupli_object(ListBase *lb, Object *ob, Object *par, int clearpar)
-{
-       Object *newob;
-       
-       newob= MEM_mallocN(sizeof(Object), "newobj dupli");
-
-       memcpy(newob, ob, sizeof(Object));
-       newob->flag |= OB_FROMDUPLI;
-       newob->id.newid= (ID *)par;     /* store duplicator */
-       
-       /* only basis-ball gets displist */
-       if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= NULL;
+/* ****************** DUPLICATOR ************** */
 
-       if(clearpar) {  // dupliverts, particle
-               newob->parent= NULL;
-               newob->track= NULL;
-       }       
-       BLI_addtail(lb, newob);
-       
-       return newob;
+static void new_dupli_object(ListBase *lb, Object *ob, float mat[][4])
+{
+       DupliObject *dob= MEM_mallocN(sizeof(DupliObject), "dupliobject");
+       BLI_addtail(lb, dob);
+       dob->ob= ob;
+       Mat4CpyMat4(dob->mat, mat);
+       Mat4CpyMat4(dob->omat, ob->obmat);
 }
 
-static void group_duplilist(Object *ob)
+static void group_duplilist(ListBase *lb, Object *ob)
 {
-       Object *newob;
        GroupObject *go;
        float mat[4][4];
        
        if(ob->dup_group==NULL) return;
        
+       /* handles animated groups, and */
+       /* we need to check update for objects that are not in scene... */
+       group_handle_recalc_and_update(ob, ob->dup_group);
+       
        for(go= ob->dup_group->gobject.first; go; go= go->next) {
                if(go->ob!=ob) {
-                       /* we need to check update for objects that are not in scene... */
-                       if(go->ob->recalc)
-                               object_handle_update(go->ob);   // bke_object.h
-                       
-                       newob= new_dupli_object(&duplilist, go->ob, ob, 0);
-                       Mat4CpyMat4(mat, newob->obmat);
-                       Mat4MulMat4(newob->obmat, mat, ob->obmat);
+                       Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
+                       new_dupli_object(lb, go->ob, mat);
                }
        }
 }
 
-static void frames_duplilist(Object *ob)
+static void frames_duplilist(ListBase *lb, Object *ob)
 {
        extern int enable_cu_speed;     /* object.c */
-       Object *newob, copyob;
+       Object copyob;
        int cfrao, ok;
        
        cfrao= G.scene->r.cfra;
@@ -337,10 +327,9 @@ static void frames_duplilist(Object *ob)
                        else ok= 0;
                }
                if(ok) {
-                       newob= new_dupli_object(&duplilist, ob, ob, 0);
-
-                       do_ob_ipo(newob);
-                       where_is_object_time(newob, (float)G.scene->r.cfra);
+                       do_ob_ipo(ob);
+                       where_is_object_time(ob, (float)G.scene->r.cfra);
+                       new_dupli_object(lb, ob, ob->obmat);
                }
        }
 
@@ -350,6 +339,7 @@ static void frames_duplilist(Object *ob)
 }
 
 struct vertexDupliData {
+       ListBase *lb;
        float pmat[4][4];
        Object *ob, *par;
 };
@@ -357,16 +347,15 @@ struct vertexDupliData {
 static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
 {
        struct vertexDupliData *vdd= userData;
-       Object *newob;
-       float vec[3], *q2, mat[3][3], tmat[4][4];
+       float vec[3], *q2, mat[3][3], tmat[4][4], obmat[4][4];
        
        VECCOPY(vec, co);
        Mat4MulVecfl(vdd->pmat, vec);
        VecSubf(vec, vec, vdd->pmat[3]);
        VecAddf(vec, vec, vdd->ob->obmat[3]);
        
-       newob= new_dupli_object(&duplilist, vdd->ob, vdd->par, 1);
-       VECCOPY(newob->obmat[3], vec);
+       Mat4CpyMat4(obmat, vdd->ob->obmat);
+       VECCOPY(obmat[3], vec);
        
        if(vdd->par->transflag & OB_DUPLIROT) {
                
@@ -375,13 +364,13 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n
                q2= vectoquat(vec, vdd->ob->trackflag, vdd->ob->upflag);
                
                QuatToMat3(q2, mat);
-               Mat4CpyMat4(tmat, newob->obmat);
-               Mat4MulMat43(newob->obmat, tmat, mat);
+               Mat4CpyMat4(tmat, obmat);
+               Mat4MulMat43(obmat, tmat, mat);
        }
-       
+       new_dupli_object(vdd->lb, vdd->ob, obmat);
 }
 
-static void vertex_duplilist(Scene *sce, Object *par)
+static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par)
 {
        Object *ob;
        Base *base;
@@ -411,6 +400,7 @@ static void vertex_duplilist(Scene *sce, Object *par)
                                        struct vertexDupliData vdd;
                                        
                                        ob= base->object;
+                                       vdd.lb= lb;
                                        vdd.ob= ob;
                                        vdd.par= par;
                                        Mat4CpyMat4(vdd.pmat, pmat);
@@ -442,9 +432,9 @@ static void vertex_duplilist(Scene *sce, Object *par)
                dm->release(dm);
 }
 
-static void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
+static void particle_duplilist(ListBase *lb, Scene *sce, Object *par, PartEff *paf)
 {
-       Object *ob, *newob;
+       Object *ob, copyob;
        Base *base;
        Particle *pa;
        float ctime, vec1[3];
@@ -460,21 +450,20 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
        }
        
        ctime= bsystem_time(par, 0, (float)G.scene->r.cfra, 0.0);
-
+       
        lay= G.scene->lay;
 
-       base= sce->base.first;
-       while(base) {
-               
+       for(base= sce->base.first; base; base= base->next) {
                if(base->object->type>0 && (base->lay & lay) && G.obedit!=base->object) {
                        ob= base->object->parent;
                        while(ob) {
                                if(ob==par) {
                                
                                        ob= base->object;
+                                       /* temp copy, to have ipos etc to work OK */
+                                       copyob= *ob;
                                        
-                                       pa= paf->keys;
-                                       for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
+                                       for(a=0, pa= paf->keys; a<paf->totpart; a++, pa+=paf->totkey) {
                                                
                                                if(paf->flag & PAF_STATIC) {
                                                        float mtime;
@@ -483,13 +472,12 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
                                                        mtime= pa->time+pa->lifetime;
                                                        
                                                        for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
-                                                               newob= new_dupli_object(&duplilist, ob, par, 1);
                                                                
                                                                /* make sure hair grows until the end.. */ 
                                                                if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
                                                                
                                                                /* to give ipos in object correct offset */
-                                                               where_is_object_time(newob, ctime-pa->time);
+                                                               where_is_object_time(ob, ctime-pa->time);
 
                                                                where_is_particle(paf, pa, ctime, vec); // makes sure there's always a vec
                                                                Mat4MulVecfl(par->obmat, vec);
@@ -502,11 +490,12 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
                                                                        q2= vectoquat(vec1, ob->trackflag, ob->upflag);
                                                                        
                                                                        QuatToMat3(q2, mat);
-                                                                       Mat4CpyMat4(tmat, newob->obmat);
-                                                                       Mat4MulMat43(newob->obmat, tmat, mat);
+                                                                       Mat4CpyMat4(tmat, ob->obmat);
+                                                                       Mat4MulMat43(ob->obmat, tmat, mat);
                                                                }
                                                                
-                                                               VECCOPY(newob->obmat[3], vec);
+                                                               VECCOPY(ob->obmat[3], vec);
+                                                               new_dupli_object(lb, ob, ob->obmat);
                                                        }
                                                }
                                                else { // non static particles
@@ -515,10 +504,9 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
                                                        if((paf->flag & PAF_DIED)==0 && ctime > pa->time+pa->lifetime) continue;
 
                                                        //if(ctime < pa->time+pa->lifetime) {
-                                                       newob= new_dupli_object(&duplilist, ob, par, 1);
 
                                                        /* to give ipos in object correct offset */
-                                                       where_is_object_time(newob, ctime-pa->time);
+                                                       where_is_object_time(ob, ctime-pa->time);
                                                        
                                                        where_is_particle(paf, pa, ctime, vec);
                                                        if(paf->stype==PAF_VECT) {
@@ -528,56 +516,129 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
                                                                q2= vectoquat(vec1, ob->trackflag, ob->upflag);
                                        
                                                                QuatToMat3(q2, mat);
-                                                               Mat4CpyMat4(tmat, newob->obmat);
-                                                               Mat4MulMat43(newob->obmat, tmat, mat);
+                                                               Mat4CpyMat4(tmat, ob->obmat);
+                                                               Mat4MulMat43(ob->obmat, tmat, mat);
                                                        }
 
-                                                       VECCOPY(newob->obmat[3], vec);
+                                                       VECCOPY(ob->obmat[3], vec);
+                                                       new_dupli_object(lb, ob, ob->obmat);
                                                }                                       
                                        }
+                                       /* temp copy, to have ipos etc to work OK */
+                                       *ob= copyob;
+                                       
                                        break;
                                }
                                ob= ob->parent;
                        }
                }
-               base= base->next;
        }
 }
 
-void free_duplilist()
+static Object *find_family_object(Object **obar, char *family, char ch)
 {
        Object *ob;
+       int flen;
+       
+       if( obar[ch] ) return obar[ch];
        
-       while( (ob= duplilist.first) ) {
-               BLI_remlink(&duplilist, ob);
-               MEM_freeN(ob);
+       flen= strlen(family);
+       
+       ob= G.main->object.first;
+       while(ob) {
+               if( ob->id.name[flen+2]==ch ) {
+                       if( strncmp(ob->id.name+2, family, flen)==0 ) break;
+               }
+               ob= ob->id.next;
        }
        
+       obar[ch]= ob;
+       
+       return ob;
 }
 
-void make_duplilist(Scene *sce, Object *ob)
+
+static void font_duplilist(ListBase *lb, Object *par)
 {
-       PartEff *paf;
+       Object *ob, *obar[256];
+       Curve *cu;
+       struct chartrans *ct, *chartransdata;
+       float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
+       int slen, a;
+       
+       Mat4CpyMat4(pmat, par->obmat);
+       
+       /* in par the family name is stored, use this to find the other objects */
+       
+       chartransdata= text_to_curve(par, FO_DUPLI);
+       if(chartransdata==0) return;
+       
+       memset(obar, 0, 256*sizeof(void *));
+       
+       cu= par->data;
+       slen= strlen(cu->str);
+       fsize= cu->fsize;
+       xof= cu->xof;
+       yof= cu->yof;
+       
+       ct= chartransdata;
+       
+       for(a=0; a<slen; a++, ct++) {
+               
+               ob= find_family_object(obar, cu->family, cu->str[a]);
+               if(ob) {
+                       vec[0]= fsize*(ct->xof - xof);
+                       vec[1]= fsize*(ct->yof - yof);
+                       vec[2]= 0.0;
+                       
+                       Mat4MulVecfl(pmat, vec);
+                       
+                       Mat4CpyMat4(obmat, par->obmat);
+                       VECCOPY(obmat[3], vec);
+                       
+                       new_dupli_object(lb, ob, obmat);
+               }
+               
+       }
+       
+       MEM_freeN(chartransdata);
+}
+
+/* ***************************** */
 
+ListBase *object_duplilist(Scene *sce, Object *ob)
+{
+       static ListBase duplilist={NULL, NULL};
+       
+       if(duplilist.first) {
+               printf("wrong call to object_duplilist\n");
+               return &duplilist;
+       }
+       duplilist.first= duplilist.last= NULL;
+       
        if(ob->transflag & OB_DUPLI) {
                if(ob->transflag & OB_DUPLIVERTS) {
                        if(ob->type==OB_MESH) {
                                if(ob->transflag & OB_DUPLIVERTS) {
-                                       if( (paf=give_parteff(ob)) ) particle_duplilist(sce, ob, paf);
-                                       else vertex_duplilist(sce, ob);
+                                       PartEff *paf;
+                                       if( (paf=give_parteff(ob)) ) particle_duplilist(&duplilist, sce, ob, paf);
+                                       else vertex_duplilist(&duplilist, sce, ob);
                                }
                        }
                        else if(ob->type==OB_FONT) {
-                               font_duplilist(ob);
+                               font_duplilist(&duplilist, ob);
                        }
                }
                else if(ob->transflag & OB_DUPLIFRAMES) 
-                       frames_duplilist(ob);
+                       frames_duplilist(&duplilist, ob);
                else if(ob->transflag & OB_DUPLIGROUP)
-                       group_duplilist(ob);
+                       group_duplilist(&duplilist, ob);
        }
+       
+       return &duplilist;
 }
 
+
 int count_duplilist(Object *ob)
 {
        if(ob->transflag & OB_DUPLI) {
index 36071d392073c52c51d95e93c4ff9aa942572aa5..18c8de24febb41b8cc7e53fd8aa71cc07d9267fe 100644 (file)
@@ -1546,14 +1546,15 @@ static int exists_channel(Object *ob, char *name)
        return 0;
 }
 
-static void object_time_update_flags(Object *ob)
+static void dag_object_time_update_flags(Object *ob)
 {
        
        if(ob->ipo) ob->recalc |= OB_RECALC_OB;
        else if(ob->constraints.first) ob->recalc |= OB_RECALC_OB;
        else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB;
        else if(ob->parent) {
-               if(ob->parent->type==OB_CURVE) ob->recalc |= OB_RECALC_OB;
+               /* motion path or bone child */
+               if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB;
        }
        
        if(ob->action || ob->nlastrips.first) {
@@ -1632,7 +1633,7 @@ void DAG_scene_update_flags(Scene *sce, unsigned int lay)
                
                /* now if DagNode were part of base, the node->lay could be checked... */
                /* we do all now, since the scene_flush checks layers and clears recalc flags even */
-               object_time_update_flags(ob);
+               dag_object_time_update_flags(ob);
                
                /* handled in next loop */
                if(ob->dup_group) 
@@ -1640,16 +1641,28 @@ void DAG_scene_update_flags(Scene *sce, unsigned int lay)
                
        }
        
+       /* we do groups each once */
        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) {
-                               object_time_update_flags(go->ob);
+                               dag_object_time_update_flags(go->ob);
                        }
-                       group->id.flag &= ~LIB_DOIT;
                }
        }
        
        DAG_scene_flush_update(sce, lay);
+       
+       /* and store the info in groubobject */
+       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);
+                       }
+                       group->id.flag &= ~LIB_DOIT;
+               }
+       }
+       
 }
 
 /* for depgraph updating, all layers visible in a screen */
index 219ef69d6d24da856be01ad3e14cec623148ce45..c27245fc11e1a5fcd774ba9fed816e4b45e424c0 100644 (file)
@@ -840,8 +840,10 @@ void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r
 
 }
 
-void shadeDispList(Object *ob)
+/* has base pointer, to check for layer */
+void shadeDispList(Base *base)
 {
+       Object *ob= base->object;
        DispList *dl, *dlob;
        Material *ma = NULL;
        Curve *cu;
@@ -850,8 +852,6 @@ void shadeDispList(Object *ob)
        unsigned int *col1;
        int a;
 
-       if(ob->flag & OB_FROMDUPLI) return;
-
        dl = find_displist(&ob->disp, DL_VERTCOL);
        if (dl) {
                BLI_remlink(&ob->disp, dl);
@@ -986,16 +986,13 @@ void reshadeall_displist(void)
        
        freefastshade();
        
-       base= G.scene->base.first;
-       while(base) {
+       for(base= G.scene->base.first; base; base= base->next) {
+               ob= base->object;
+               freedisplist(&ob->disp);
                if(base->lay & G.scene->lay) {
-                       ob= base->object;
-                       
                        /* Metaballs have standard displist at the Object */
-                       if(ob->type==OB_MBALL) shadeDispList(ob);
-                       else freedisplist(&ob->disp);
+                       if(ob->type==OB_MBALL) shadeDispList(base);
                }
-               base= base->next;
        }
 }
 
@@ -1388,7 +1385,7 @@ static float calc_taper(Object *taperobj, int cur, int tot)
 
 void makeDispListMBall(Object *ob)
 {
-       if(!ob || (ob->flag&OB_FROMDUPLI) || ob->type!=OB_MBALL) return;
+       if(!ob || ob->type!=OB_MBALL) return;
 
        freedisplist(&(ob->disp));
        
index 2ab13fe328aebc59778ecea55e6b9b6f4618f43e..b5ed7fb36887d49675d0f5edc51d824cbfdb8d21 100644 (file)
  
 struct SelBox *selboxes= NULL;
 
-struct chartrans {
-       float xof, yof;
-       float rot;
-       short linenr,charnr;
-       char dobreak;
-};
-
 /* UTF-8 <-> wchar transformations */
 void
 chtoutf8(unsigned long c, char *o)
@@ -1190,86 +1183,4 @@ struct chartrans *text_to_curve(Object *ob, int mode)
        return 0;
 }
 
-/* ***************** DUPLI  ***************** */
-
-static Object *find_family_object(Object **obar, char *family, char ch)
-{
-       Object *ob;
-       int flen;
-       
-       if( obar[ch] ) return obar[ch];
-       
-       flen= strlen(family);
-       
-       ob= G.main->object.first;
-       while(ob) {
-               if( ob->id.name[flen+2]==ch ) {
-                       if( strncmp(ob->id.name+2, family, flen)==0 ) break;
-               }
-               ob= ob->id.next;
-       }
-       
-       obar[ch]= ob;
-       
-       return ob;
-}
-
-
-void font_duplilist(Object *par)
-{
-       extern ListBase duplilist;
-       Object *ob, *newob, *obar[256];
-       Curve *cu;
-       struct chartrans *ct, *chartransdata;
-       float vec[3], pmat[4][4], fsize, xof, yof;
-       int slen, a;
-       
-       Mat4CpyMat4(pmat, par->obmat);
-
-       /* in par the family name is stored, use this to find the other objects */
-
-       chartransdata= text_to_curve(par, FO_DUPLI);
-       if(chartransdata==0) return;
-       
-       memset(obar, 0, 256*4);
-       
-       cu= par->data;
-       slen= strlen(cu->str);
-       fsize= cu->fsize;
-       xof= cu->xof;
-       yof= cu->yof;
-       
-       ct= chartransdata;
-
-       for(a=0; a<slen; a++, ct++) {
-       
-               ob= find_family_object(obar, cu->family, cu->str[a]);
-               if(ob) {
-                               /* not clear if this free line here is still needed */
-                       freedisplist(&ob->disp);
-                       
-                       vec[0]= fsize*(ct->xof - xof);
-                       vec[1]= fsize*(ct->yof - yof);
-                       vec[2]= 0.0;
-       
-                       Mat4MulVecfl(pmat, vec);
-                       
-                       newob= MEM_mallocN(sizeof(Object), "newobj dupli");
-                       memcpy(newob, ob, sizeof(Object));
-                       newob->flag |= OB_FROMDUPLI;
-                       newob->id.newid= (ID *)par;             /* keep duplicator */
-                       newob->totcol= par->totcol;     /* for give_current_material */
-                       
-                       Mat4CpyMat4(newob->obmat, par->obmat);
-                       VECCOPY(newob->obmat[3], vec);
-                       
-                       newob->parent= 0;
-                       newob->track= 0;
-                       
-                       BLI_addtail(&duplilist, newob);
-               }
-               
-       }
 
-       MEM_freeN(chartransdata);
-}
index 0ae6208c9de0e347747798f491fe39c8eda3945b..5e2d0d6fc6d12cf3927f7e8d52ba786e96f3ad11 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
-#include "DNA_ID.h"
+#include "DNA_action_types.h"
+#include "DNA_effect_types.h"
 #include "DNA_group_types.h"
-#include "DNA_object_types.h"
+#include "DNA_ID.h"
 #include "DNA_ipo_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_scene_types.h"
 
 #include "BLI_blenlib.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
 
-#include "BKE_library.h"
+#include "BKE_global.h"
 #include "BKE_group.h"
-#include "BKE_object.h"
 #include "BKE_ipo.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -68,6 +73,34 @@ void free_group(Group *group)
        }
 }
 
+void unlink_group(Group *group)
+{
+       Material *ma;
+       Object *ob;
+       
+       for(ma= G.main->mat.first; ma; ma= ma->id.next) {
+               if(ma->group==group)
+                       ma->group= NULL;
+       }
+       for(ob= G.main->object.first; ob; ob= ob->id.next) {
+               bActionStrip *strip;
+               PartEff *paf;
+               
+               if(ob->dup_group==group)
+                       ob->dup_group= NULL;
+               for(strip= ob->nlastrips.first; strip; strip= strip->next) {
+                       if(strip->object==ob)
+                               strip->object= NULL;
+               }
+               for(paf= ob->effect.first; paf; paf= paf->next) {
+                       if(paf->type==EFF_PARTICLE) {
+                               if(paf->group)
+                                       paf->group= NULL;
+                       }
+               }
+       }
+}
+
 Group *add_group()
 {
        Group *group;
@@ -150,3 +183,109 @@ void group_tag_recalc(Group *group)
        }
 }
 
+/* only replaces object strips or action when parent nla instructs it */
+/* keep checking nla.c though, in case internal structure of strip changes */
+static void group_replaces_nla(Object *parent, Object *target, char mode)
+{
+       static ListBase nlastrips={NULL, NULL};
+       static bAction *action= NULL;
+       static int done= 0;
+       bActionStrip *strip, *nstrip;
+       
+       if(mode=='s') {
+               
+               for(strip= parent->nlastrips.first; strip; strip= strip->next) {
+                       if(strip->object==target) {
+                               if(done==0) {
+                                       /* clear nla & action from object */
+                                       nlastrips= target->nlastrips;
+                                       target->nlastrips.first= target->nlastrips.last= NULL;
+                                       action= target->action;
+                                       target->action= NULL;
+                                       target->nlaflag |= OB_NLA_OVERRIDE;
+                                       done= 1;
+                               }
+                               nstrip= MEM_dupallocN(strip);
+                               BLI_addtail(&target->nlastrips, nstrip);
+                       }
+               }
+       }
+       else if(mode=='e') {
+               if(done) {
+                       BLI_freelistN(&target->nlastrips);
+                       target->nlastrips= nlastrips;
+                       target->action= action;
+                       
+                       nlastrips.first= nlastrips.last= NULL;  /* not needed, but yah... :) */
+                       action= NULL;
+                       done= 0;
+               }
+       }
+}
+
+
+/* puts all group members in local timing system, after this call
+you can draw everything, leaves tags in objects to signal it needs further updating */
+void group_handle_recalc_and_update(Object *parent, Group *group)
+{
+       GroupObject *go;
+       
+       /* if animated group... */
+       if(parent->sf != 0.0f || parent->nlastrips.first) {
+               int cfrao;
+               
+               /* switch to local time */
+               cfrao= G.scene->r.cfra;
+               G.scene->r.cfra -= (int)parent->sf;
+               
+               /* we need a DAG per group... */
+               for(go= group->gobject.first; go; go= go->next) {
+                       if(go->ob && go->recalc) {
+                               go->ob->recalc= go->recalc;
+                               
+                               group_replaces_nla(parent, go->ob, 's');
+                               object_handle_update(go->ob);
+                               group_replaces_nla(parent, go->ob, 'e');
+                               
+                               /* leave recalc tags in case group members are in normal scene */
+                               go->ob->recalc= go->recalc;
+                       }
+               }
+               
+               /* restore */
+               G.scene->r.cfra= cfrao;
+       }
+       else {
+               /* only do existing tags, as set by regular depsgraph */
+               for(go= group->gobject.first; go; go= go->next) {
+                       if(go->ob) {
+                               if(go->ob->recalc) {
+                                       object_handle_update(go->ob);
+                               }
+                       }
+               }
+       }
+}
+
+Object *group_get_member_with_action(Group *group, bAction *act)
+{
+       GroupObject *go;
+       
+       if(group==NULL || act==NULL) return NULL;
+       
+       for(go= group->gobject.first; go; go= go->next) {
+               if(go->ob) {
+                       if(go->ob->action==act)
+                               return go->ob;
+                       if(go->ob->nlastrips.first) {
+                               bActionStrip *strip;
+                               
+                               for(strip= go->ob->nlastrips.first; strip; strip= strip->next) {
+                                       if(strip->act==act)
+                                               return go->ob;
+                               }
+                       }
+               }
+       }
+       return NULL;
+}
index ea1608d8a18bcc55851e20412b1d7ef1884f4d55..09408e4a220af9a3b5b1ee9903fb50b5b2f3c79a 100644 (file)
@@ -1437,11 +1437,12 @@ float init_meta(Object *ob)     /* return totsize */
        Object *bob;
        MetaBall *mb;
        MetaElem *ml;
-       float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], vec[3];
+       float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], obmat[4][4], vec[3];
        float temp1[4][4], temp2[4][4], temp3[4][4]; //max=0.0;
        int a, obnr, zero_size=0;
        char obname[32];
        
+       Mat4CpyMat4(obmat, ob->obmat);  /* to cope with duplicators from next_object */
        Mat4Invert(obinv, ob->obmat);
        a= 0;
        
@@ -1456,7 +1457,7 @@ float init_meta(Object *ob)       /* return totsize */
                        zero_size= 0;
                        ml= NULL;
 
-                       if(bob==ob) {
+                       if(bob==ob && (base->flag & OB_FROMDUPLI)==0) {
                                mat= imat= 0;
                                mb= ob->data;
        
@@ -1471,7 +1472,6 @@ float init_meta(Object *ob)       /* return totsize */
                                splitIDname(bob->id.name+2, name, &nr);
                                if( strcmp(obname, name)==0 ) {
                                        mb= bob->data;
-                                       
                                        if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb) 
                                                ml= editelems.first;
                                        else ml= mb->elems.first;
@@ -1535,7 +1535,7 @@ float init_meta(Object *ob)       /* return totsize */
                                        imat= new_pgn_element(4*4*sizeof(float));
                                        
                                        /* mat is the matrix to transform from mball into the basis-mball */
-                                       Mat4Invert(obinv, ob->obmat);
+                                       Mat4Invert(obinv, obmat);
                                        Mat4MulMat4(temp2, bob->obmat, obinv);
                                        /* MetaBall transformation */
                                        Mat4MulMat4(mat, temp1, temp2);
index 5adde76acccec725cd9ccc7abd7d37bb5dbd996a..5fefc41f77c0f2cb4c5dc7491567923a306560c1 100644 (file)
@@ -46,6 +46,9 @@
 #include <config.h>
 #endif
 
+/* NOTE: in group.c the strips get copied for group-nla override, this assumes
+   that strips are one single block, without additional data to be copied */
+
 void copy_actionstrip (bActionStrip **dst, bActionStrip **src){
        bActionStrip *dstrip;
        bActionStrip *sstrip = *src;
index 7af6ef21e32bc1a9475d6d9ea11a89456a3fe5c9..e7cf3577a998a154558f4f929a336e1113d779e0 100644 (file)
@@ -208,6 +208,7 @@ void free_object(Object *ob)
        ob->path= 0;
        if(ob->ipo) ob->ipo->id.us--;
        if(ob->action) ob->action->id.us--;
+       if(ob->dup_group) ob->dup_group->id.us--;
        if(ob->defbase.first)
                BLI_freelistN(&ob->defbase);
        if(ob->pose) {
@@ -255,6 +256,7 @@ void unlink_object(Object *ob)
        Ipo *ipo;
        Group *group;
        bConstraint *con;
+       bActionStrip *strip;
        int a;
        char *str;
        
@@ -315,6 +317,7 @@ void unlink_object(Object *ob)
                                        obt->recalc |= OB_RECALC_OB;
                                }
                        }
+                       
                        /* object is deflector or field */
                        if(ob->pd) {
                                if(give_parteff(obt))
@@ -322,6 +325,12 @@ void unlink_object(Object *ob)
                                else if(obt->soft)
                                        obt->recalc |= OB_RECALC_DATA;
                        }
+                       
+                       /* strips */
+                       for(strip= ob->nlastrips.first; strip; strip= strip->next) {
+                               if(strip->object==ob)
+                                       strip->object= NULL;
+                       }
                }
                obt= obt->id.next;
        }
@@ -999,15 +1008,10 @@ float bsystem_time(Object *ob, Object *par, float cfra, float ofs)
                if(R.r.mode & R_FIELDSTILL); else cfra+= .5;
        }
 
+       cfra+= bluroffs;
 
-       if(ob && (ob->flag & OB_FROMDUPLI));
-       else {
-                       /* motion blur */
-               cfra+= bluroffs;
-       
-               /* global time */
-               cfra*= G.scene->r.framelen;     
-       }
+       /* global time */
+       cfra*= G.scene->r.framelen;     
        
        if(no_speed_curve==0) if(ob && ob->ipo) cfra= calc_ipo_time(ob->ipo, cfra);
        
@@ -1522,9 +1526,6 @@ void solve_tracking (Object *ob, float targetmat[][4])
 void where_is_object(Object *ob)
 {
        
-       /* these have been mem copied */
-       if(ob->flag & OB_FROMDUPLI) return;
-       
        where_is_object_time(ob, (float)G.scene->r.cfra);
 }
 
index fd0a6288dbeacd24a7fd191938a7751b618ccba9..df9e626abbf9b7d09adc206eb4b841b6f40c5df6 100644 (file)
@@ -76,7 +76,7 @@
 #include "BKE_utildefines.h"
 
 #include "BPY_extern.h"
-
+#include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 
 #include "nla.h"
@@ -277,13 +277,10 @@ void set_scene_bg(Scene *sce)
                
                ob->flag= base->flag;
                
-               ob->recalc= OB_RECALC;
-               if(ob->dup_group) group_tag_recalc(ob->dup_group);      /* for lib-linked stuff */
-               
                ob->ctime= -1234567.0;  /* force ipo to be calculated later */
                base= base->next;
        }
-       // full update
+       // full animation update
        scene_update_for_newframe(sce, sce->lay);
        
        /* do we need FRAMECHANGED in set_scene? */
@@ -309,23 +306,21 @@ void set_scene_name(char *name)
  */
 int next_object(int val, Base **base, Object **ob)
 {
-       extern ListBase duplilist;
-       static Object *dupob;
+       static ListBase *duplilist= NULL;
+       static DupliObject *dupob;
        static int fase;
        int run_again=1;
        
        /* init */
        if(val==0) {
                fase= F_START;
-               dupob= 0;
+               dupob= NULL;
        }
        else {
 
                /* run_again is set when a duplilist has been ended */
                while(run_again) {
                        run_again= 0;
-                       
-                               
 
                        /* the first base */
                        if(fase==F_START) {
@@ -360,30 +355,40 @@ int next_object(int val, Base **base, Object **ob)
                                }
                        }
                        
-                       if(*base == 0) fase= F_START;
+                       if(*base == NULL) fase= F_START;
                        else {
                                if(fase!=F_DUPLI) {
                                        if( (*base)->object->transflag & OB_DUPLI) {
                                                
-                                               make_duplilist(G.scene, (*base)->object);
-                                               dupob= duplilist.first;
+                                               duplilist= object_duplilist(G.scene, (*base)->object);
+                                               
+                                               dupob= duplilist->first;
                                                
                                        }
                                }
                                /* handle dupli's */
                                if(dupob) {
                                        
-                                       *ob= dupob;
+                                       Mat4CpyMat4(dupob->ob->obmat, dupob->mat);
+                                       
+                                       (*base)->flag |= OB_FROMDUPLI;
+                                       *ob= dupob->ob;
                                        fase= F_DUPLI;
                                        
-                                       dupob= dupob->id.next;
+                                       dupob= dupob->next;
                                }
                                else if(fase==F_DUPLI) {
                                        fase= F_SCENE;
-                                       free_duplilist();
+                                       (*base)->flag &= ~OB_FROMDUPLI;
+                                       
+                                       for(dupob= duplilist->first; dupob; dupob= dupob->next) {
+                                               Mat4CpyMat4(dupob->ob->obmat, dupob->omat);
+                                       }
+                                       
+                                       BLI_freelistN(duplilist);
+                                       duplilist= NULL;
                                        run_again= 1;
                                }
-                               
                        }
                }
        }
index aef5f82f6f6d16f2b5d94285e2d9915ae41320c6..f8185b229ae9b15eff7892260e52084b186cbe96 100644 (file)
@@ -1254,6 +1254,7 @@ static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist)
        bActionStrip *strip;
 
        for (strip=striplist->first; strip; strip=strip->next){
+               strip->object = newlibadr(fd, id->lib, strip->object);
                strip->act = newlibadr_us(fd, id->lib, strip->act);
                strip->ipo = newlibadr(fd, id->lib, strip->ipo);
        }
@@ -3155,24 +3156,28 @@ static void lib_link_group(FileData *fd, Main *main)
 {
        Group *group= main->group.first;
        GroupObject *go;
-
+       int add_us;
+       
        while(group) {
                if(group->id.flag & LIB_NEEDLINK) {
                        group->id.flag -= LIB_NEEDLINK;
-
+                       
+                       add_us= 0;
+                       
                        go= group->gobject.first;
                        while(go) {
                                go->ob= newlibadr(fd, group->id.lib, go->ob);
                                if(go->ob) {
-                                       /* groups have inverse users... */
-                                       if(group->id.us==0)
-                                               group->id.us= 1;
+                                       /* if group has an object, it increments user... */
+                                       add_us= 1;
                                        if(go->ob->id.us==0) 
                                                go->ob->id.us= 1;
                                }
                                go= go->next;
                        }
+                       if(add_us) group->id.us++;
                        rem_from_group(group, NULL);    /* removes NULL entries */
+                       
                }
                group= group->id.next;
        }
@@ -5580,6 +5585,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
        expand_constraint_channels(fd, mainvar, &ob->constraintChannels);
 
        for (strip=ob->nlastrips.first; strip; strip=strip->next){
+               expand_doit(fd, mainvar, strip->object);
                expand_doit(fd, mainvar, strip->act);
                expand_doit(fd, mainvar, strip->ipo);
        }
index 1a33b3d0810e49575f99de368308b8b8d231e73d..442247864b535585935dad2e00a463793d91503b 100644 (file)
@@ -62,7 +62,7 @@ typedef struct TreeElement {
 #define TSE_CONSTRAINT         8
 #define TSE_MODIFIER_BASE      9
 #define TSE_MODIFIER           10
-#define TSE_MODIFIER_OB                11
+#define TSE_LINKED_OB          11
 #define TSE_SCRIPT_BASE                12
 #define TSE_POSE_BASE          13
 #define TSE_POSE_CHANNEL       14
index b0e40699f428810f2297ede6b58db9a1a475f1e4..4a9876705e637202b0d1b9e34ef88486c8ae4135 100644 (file)
@@ -46,6 +46,9 @@ void circ(float x, float y, float rad);
 
 void do_viewbuts(unsigned short event);
 
+/* View3DAfter->type */
+#define V3D_XRAY       1
+#define V3D_TRANSP     2
 void add_view3d_after(struct View3D *v3d, struct Base *base, int type);
 
 void backdrawview3d(int test);
index 2ee699839edc1518b037a2a192912519bb82c30e..09ecc3a68c189d2299f83710a139211609f4feb0 100644 (file)
@@ -43,6 +43,8 @@ typedef struct GroupObject {
        struct GroupObject *next, *prev;
        struct Object *ob;
        void *lampren;          /* used while render */
+       int recalc;                     /* copy of ob->recalc, used to set animated groups OK */
+       int pad;
 } GroupObject;
 
 
index bf3d7820daecdd3a4c62f62066d936c14a62ec41..fa1a4fbe456a4b140f91b9deeef16385aacc90ee 100644 (file)
@@ -35,6 +35,7 @@
 
 struct bAction;
 struct Ipo;
+struct Object;
 
 typedef struct bActionStrip {
        struct bActionStrip *next, *prev;
@@ -43,7 +44,7 @@ typedef struct bActionStrip {
 
        struct  Ipo *ipo;                       /* Blending ipo */
        struct  bAction *act;           /* The action referenced by this strip */
-
+       struct  Object *object;         /* For groups, the actual object being nla'ed */
        float   start, end;                     /* The range of frames covered by this strip */
        float   actstart, actend;       /* The range of frames taken from the action */
        float   stridelen;                      /* The stridelength (considered when flag & ACT_USESTRIDE) */
index bf4f44a421d50e44478420f1154f952befd7ad75..3e1628a658c16175acd5ef64b99d17b2a6422287 100644 (file)
@@ -63,18 +63,6 @@ typedef struct BGpic {
        unsigned int *rect;
 } BGpic;
 
-#
-#
-typedef struct View3DAfter {
-       struct View3DAfter *next, *prev;
-       struct Base *base;
-       int type;
-} View3DAfter;
-
-/* View3DAfter->type */
-#define V3D_XRAY       1
-#define V3D_TRANSP     2
-
 typedef struct View3D {
        struct SpaceLink *next, *prev;
        int spacetype;
index 0d6e141df5f57c4c53396398f707be3129cbff7c..f5b14fccaed5d6cb7e01ceca247014938aa2caac 100644 (file)
@@ -2518,6 +2518,7 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, floa
                
                VECADD(col, shr.diff, shr.spec);
                
+               /* NOTE: this is not correct here, sky from raytrace gets corrected... */
                /* exposure correction */
                if(R.wrld.exp!=0.0 || R.wrld.range!=1.0) {
                        if((shi.mat->mode & MA_SHLESS)==0) {
index 3b694813e91dc60bb3e99b686ca915b8a98929d1..f50a95bcbc988e10070a089c8a54fa2d77138947 100644 (file)
@@ -2683,7 +2683,7 @@ extern ListBase duplilist;
 void RE_rotateBlenderScene(void)
 {
        Base *base;
-       Object *ob, *obd;
+       Object *ob;
        Scene *sce;
        unsigned int lay;
        float mat[4][4];
@@ -2776,6 +2776,7 @@ void RE_rotateBlenderScene(void)
                        if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & G.scene->lay)) ) {
 
                                if(ob->transflag & OB_DUPLI) {
+                                       
                                        /* exception: mballs! */
                                        /* yafray: Include at least one copy of a dupliframe object for yafray in the renderlist.
                                           mballs comment above true as well for yafray, they are not included, only all other object types */
@@ -2793,28 +2794,17 @@ void RE_rotateBlenderScene(void)
                                                }
                                        }
                                        
-                                       make_duplilist(sce, ob);
                                        if(ob->type==OB_MBALL) {
                                                init_render_object(ob);
                                        }
                                        else {
-                                               obd= duplilist.first;
-                                               if(obd) {
-                                                       /* exception, in background render it doesnt make the displist */
-                                                       if ELEM(obd->type, OB_CURVE, OB_SURF) {
-                                                               Curve *cu;
-
-                                                               cu= obd->data;
-                                                               if(cu->disp.first==NULL) {
-                                                                       obd->flag &= ~OB_FROMDUPLI;
-                                                                       makeDispListCurveTypes(obd, 0);
-                                                                       obd->flag |= OB_FROMDUPLI;
-                                                               }
-                                                       }
-                                               }
-
-                                               obd= duplilist.first;
-                                               while(obd) {
+                                               DupliObject *dob;
+                                               ListBase *lb= object_duplilist(sce, ob);
+                                               
+                                               for(dob= lb->first; dob; dob= dob->next) {
+                                                       Object *obd= dob->ob;
+                                                       Mat4CpyMat4(obd->obmat, dob->mat);
+                                                       
                                                        if(obd->type!=OB_MBALL) {
                                                                /* yafray: special handling of duplivert objects for yafray:
                                                                   only the matrix is stored, together with the source object name.
@@ -2829,10 +2819,10 @@ void RE_rotateBlenderScene(void)
                                                                }
                                                                else init_render_object(obd);
                                                        }
-                                                       obd= obd->id.next;
+                                                       Mat4CpyMat4(obd->obmat, dob->omat);
                                                }
+                                               BLI_freelistN(lb);
                                        }
-                                       free_duplilist();
                                }
                                else {
                                        /* yafray: if there are linked data objects (except lamps, empties or armatures),
index 752e831c2b4b43b6ea8268555b266bc990f9f77a..43813f7f907fb7a35f82970b1d4f21b4eb2541ae 100644 (file)
@@ -117,6 +117,7 @@ void test_actionpoin_but(char *name, ID **idpp)
        id= G.main->action.first;
        while(id) {
                if( strcmp(name, id->name+2)==0 ) {
+                       id_lib_extern(id);      /* checks lib data, sets correct flag for saving then */
                        *idpp= id;
                        return;
                }
@@ -140,6 +141,7 @@ void test_obpoin_but(char *name, ID **idpp)
        while(id) {
                if( strcmp(name, id->name+2)==0 ) {
                        *idpp= id;
+                       id_lib_extern(id);      /* checks lib data, sets correct flag for saving then */
                        return;
                }
                id= id->next;
index 2b0ba1a7ad3eeea414cbb5756feeaec3a42cf4b2..bb6e77bc50728d6cffb080d8e747b0eb1057ef5b 100644 (file)
@@ -79,6 +79,7 @@
 #include "BDR_editcurve.h"
 
 #include "blendef.h"
+#include "butspace.h"
 #include "mydevice.h"
 
 #define TESTBASE_SAFE(base)    ((base)->flag & SELECT)
@@ -460,8 +461,8 @@ static void nla_panel_properties(short cntrl)       // NLA_HANDLER_PROPERTIES
        
        /* first labels, for simpler align code :) */
        uiDefBut(block, LABEL, 0, "Timeline Range:",    10,180,300,19, 0, 0, 0, 0, 0, "");
-       uiDefBut(block, LABEL, 0, "Blending:",                  10,120,300,19, 0, 0, 0, 0, 0, "");
-       uiDefBut(block, LABEL, 0, "Options:",                   10,80,300,19, 0, 0, 0, 0, 0, "");
+       uiDefBut(block, LABEL, 0, "Blending:",                  10,120,150,19, 0, 0, 0, 0, 0, "");
+       uiDefBut(block, LABEL, 0, "Options:",                   160,120,150,19, 0, 0, 0, 0, 0, "");
        uiDefBut(block, LABEL, 0, "Stride Support:",    10,40,300,19, 0, 0, 0, 0, 0, "");
 
        uiBlockBeginAlign(block);
@@ -482,13 +483,18 @@ static void nla_panel_properties(short cntrl)     // NLA_HANDLER_PROPERTIES
        }
        
        uiBlockBeginAlign(block);
-       uiDefButF(block, NUM, B_NLA_PANEL, "Blendin:",  10,100,150,19, &strip->blendin, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-in");
-       uiDefButF(block, NUM, B_NLA_PANEL, "Blendout:", 160,100,150,19, &strip->blendout, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-out");
+       uiDefButF(block, NUM, B_NLA_PANEL, "Blendin:",  10,100,156,19, &strip->blendin, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-in");
+       uiDefButF(block, NUM, B_NLA_PANEL, "Blendout:", 10,80,145,19, &strip->blendout, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-out");
 
        uiBlockBeginAlign(block);
-       uiDefButF(block, NUM, B_NLA_PANEL, "Repeat:",   10,60,150,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat");
-       uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_NLA_PANEL, "Hold",   160,60,75,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip");
-       uiDefButS(block, TOG, B_NLA_PANEL, "Add",                                                               230,60,75,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode");
+       uiDefButF(block, NUM, B_NLA_PANEL, "Repeat:",   160,100,150,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat");
+       uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_NLA_PANEL, "Hold",   160,80,75,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip");
+       uiDefButS(block, TOG, B_NLA_PANEL, "Add",                                                               235,80,75,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode");
+       uiBlockEndAlign(block);
+       
+       if(ob->dup_group) {
+               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_NLA_PANEL, "Target:", 160, 50, 150, 19, &strip->object, "Target Object in this group"); 
+       }
        
        uiBlockBeginAlign(block);
        uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_NLA_PANEL, "Stride Path",        10,20,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride");
index 10fdbee4dbad0cb91a83dedc972c69c339d7d379..b4bdd066ed48718defe45a8acc99c1fe79e4f249 100644 (file)
@@ -158,7 +158,7 @@ static int set_gl_material(int nr)
 }
 
 /* returns 1: when there's alpha needed to be drawn in a 2nd pass */
-static int init_gl_materials(Object *ob)
+static int init_gl_materials(Object *ob, int check_alpha)
 {
        extern Material defmaterial;    // render module abuse...
        Material *ma;
@@ -189,7 +189,7 @@ static int init_gl_materials(Object *ob)
                        matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b;
                        
                        /* draw transparent, not in pick-select, nor editmode */
-                       if(!(G.f & G_PICKSEL) && (ob->dtx & OB_DRAWTRANSP) && !(G.obedit && G.obedit->data==ob->data)) {
+                       if(check_alpha && !(G.f & G_PICKSEL) && (ob->dtx & OB_DRAWTRANSP) && !(G.obedit && G.obedit->data==ob->data)) {
                                if(G.vd->transp) {      // drawing the transparent pass
                                        if(ma->alpha==1.0) matbuf[a][0][3]= 0.0;        // means skip solid
                                        else matbuf[a][0][3]= ma->alpha;
@@ -1754,8 +1754,9 @@ static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmoot
        return 1;
 }
 
-static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, int dt)
+static void draw_mesh_fancy(Base *base, DerivedMesh *baseDM, DerivedMesh *dm, int dt)
 {
+       Object *ob= base->object;
        Mesh *me = ob->data;
        Material *ma= give_current_material(ob, 1);
        int hasHaloMat = (ma && (ma->mode&MA_HALO));
@@ -1780,7 +1781,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in
        }
        else if( (ob==OBACT && (G.f & G_FACESELECT)) || (G.vd->drawtype==OB_TEXTURE && dt>OB_SOLID)) {
                
-               if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !(G.f&(G_FACESELECT|G_PICKSEL)) && !draw_wire) {
+               if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&(G_FACESELECT|G_PICKSEL)) && !draw_wire) {
                        draw_mesh_object_outline(ob, dm);
                }
 
@@ -1788,7 +1789,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in
        }
        else if(dt==OB_SOLID ) {
                
-               if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !draw_wire) {
+               if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
                        draw_mesh_object_outline(ob, dm);
                }
 
@@ -1802,7 +1803,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in
                glFrontFace(GL_CCW);
                glDisable(GL_LIGHTING);
 
-               if(ob->flag & SELECT) {
+               if(base->flag & SELECT) {
                        BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
                } else {
                        BIF_ThemeColor(TH_WIRE);
@@ -1836,11 +1837,11 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in
                else {
                        dl = ob->disp.first;
                        if (!dl || !dl->col1) {
-                               shadeDispList(ob);
+                               shadeDispList(base);
                                dl = find_displist(&ob->disp, DL_VERTCOL);
                        }
 
-                       if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !draw_wire) {
+                       if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
                                draw_mesh_object_outline(ob, dm);
                        }
 
@@ -1852,7 +1853,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in
                                dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
                        }
 
-                       if(ob->flag & SELECT) {
+                       if(base->flag & SELECT) {
                                BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
                        } else {
                                BIF_ThemeColor(TH_WIRE);
@@ -1866,7 +1867,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in
                                * overlaying the wires.
                                */
                if (dt!=OB_WIRE) {
-                       if(ob->flag & SELECT) {
+                       if(base->flag & SELECT) {
                                BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
                        } else {
                                BIF_ThemeColor(TH_WIRE);
@@ -1914,7 +1915,7 @@ static int draw_mesh_object(Base *base, int dt)
                        cageDM = editmesh_get_derived_cage_and_final(&finalDM, &cageNeedsFree, &finalNeedsFree);
                }
 
-               if(dt>OB_WIRE) init_gl_materials(ob);   // no transp in editmode, the fancy draw over goes bad then
+               if(dt>OB_WIRE) init_gl_materials(ob, 0);        // no transp in editmode, the fancy draw over goes bad then
                draw_em_fancy(ob, G.editMesh, cageDM, finalDM, dt);
 
                if (cageNeedsFree) cageDM->release(cageDM);
@@ -1928,8 +1929,8 @@ static int draw_mesh_object(Base *base, int dt)
                        DerivedMesh *baseDM = mesh_get_derived_deform(ob, &baseDMneedsFree);
                        DerivedMesh *realDM = mesh_get_derived_final(ob, &realDMneedsFree);
 
-                       if(dt==OB_SOLID) has_alpha= init_gl_materials(ob);
-                       if(baseDM && realDM) draw_mesh_fancy(ob, baseDM, realDM, dt);
+                       if(dt==OB_SOLID) has_alpha= init_gl_materials(ob, (base->flag & OB_FROMDUPLI)==0);
+                       if(baseDM && realDM) draw_mesh_fancy(base, baseDM, realDM, dt);
                        
                        if(me->totvert==0) retval= 1;
                        
@@ -2352,8 +2353,9 @@ static void drawDispListshaded(ListBase *lb, Object *ob)
 }
 
 /* returns 1 when nothing was drawn */
-static int drawDispList(Object *ob, int dt)
+static int drawDispList(Base *base, int dt)
 {
+       Object *ob= base->object;
        ListBase *lb=0;
        DispList *dl;
        Curve *cu;
@@ -2382,11 +2384,11 @@ static int drawDispList(Object *ob, int dt)
                        }
                        else {
                                if(dt==OB_SHADED) {
-                                       if(ob->disp.first==0) shadeDispList(ob);
+                                       if(ob->disp.first==0) shadeDispList(base);
                                        drawDispListshaded(lb, ob);
                                }
                                else {
-                                       init_gl_materials(ob);
+                                       init_gl_materials(ob, 0);
                                        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
                                        drawDispListsolid(lb, ob);
                                }
@@ -2416,11 +2418,11 @@ static int drawDispList(Object *ob, int dt)
                        if(dl->nors==NULL) addnormalsDispList(ob, lb);
                        
                        if(dt==OB_SHADED) {
-                               if(ob->disp.first==NULL) shadeDispList(ob);
+                               if(ob->disp.first==NULL) shadeDispList(base);
                                drawDispListshaded(lb, ob);
                        }
                        else {
-                               init_gl_materials(ob);
+                               init_gl_materials(ob, 0);
                                glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
                        
                                drawDispListsolid(lb, ob);
@@ -2441,11 +2443,11 @@ static int drawDispList(Object *ob, int dt)
                                
                                if(dt==OB_SHADED) {
                                        dl= lb->first;
-                                       if(dl && dl->col1==0) shadeDispList(ob);
+                                       if(dl && dl->col1==0) shadeDispList(base);
                                        drawDispListshaded(lb, ob);
                                }
                                else {
-                                       init_gl_materials(ob);
+                                       init_gl_materials(ob, 0);
                                        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
                                
                                        drawDispListsolid(lb, ob);      
@@ -2789,15 +2791,16 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
        }
 }
 
-static void drawnurb(Object *ob, Nurb *nurb, int dt)
+static void drawnurb(Base *base, Nurb *nurb, int dt)
 {
+       Object *ob= base->object;
        Curve *cu = ob->data;
        Nurb *nu;
        BevList *bl;
 
        /* DispList */
        BIF_ThemeColor(TH_WIRE);
-       drawDispList(ob, dt);
+       drawDispList(base, dt);
 
        if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
        
@@ -3066,8 +3069,9 @@ void drawcircball(int mode, float *cent, float rad, float tmat[][4])
 }
 
 /* return 1 if nothing was drawn */
-static int drawmball(Object *ob, int dt)
+static int drawmball(Base *base, int dt)
 {
+       Object *ob= base->object;
        MetaBall *mb;
        MetaElem *ml;
        float imat[4][4], tmat[4][4];
@@ -3077,11 +3081,12 @@ static int drawmball(Object *ob, int dt)
 
        if(ob==G.obedit) {
                BIF_ThemeColor(TH_WIRE);
-               if((G.f & G_PICKSEL)==0 ) drawDispList(ob, dt);
+               if((G.f & G_PICKSEL)==0 ) drawDispList(base, dt);
                ml= editelems.first;
        }
        else {
-               drawDispList(ob, dt);
+               if((base->flag & OB_FROMDUPLI)==0) 
+                       drawDispList(base, dt);
                ml= mb->elems.first;
        }
 
@@ -3406,7 +3411,8 @@ static void drawSolidSelect(Base *base)
                        drawDispListwire(&cu->disp);
                }
        } else if (ob->type==OB_MBALL) {
-               drawDispListwire(&ob->disp);
+               if((base->flag & OB_FROMDUPLI)==0) 
+                       drawDispListwire(&ob->disp);
        }
        else if(ob->type==OB_ARMATURE) {
                if(!(ob->flag & OB_POSEMODE)) {
@@ -3495,7 +3501,7 @@ void draw_object(Base *base, int flag)
        ob= base->object;
 
        /* xray delay? */
-       if((flag & DRAW_PICKING)==0 && (ob->flag & OB_FROMDUPLI)==0) {
+       if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) {
                /* xray and transp are set when it is drawing the 2nd/3rd pass */
                if(!G.vd->xray && !G.vd->transp && (ob->dtx & OB_DRAWXRAY)) {
                        add_view3d_after(G.vd, base, V3D_XRAY);
@@ -3703,10 +3709,10 @@ void draw_object(Base *base, int flag)
                        if (cu->flag & CU_FAST) {
                                cpack(0xFFFFFF);
                                set_inverted_drawing(1);
-                               drawDispList(ob, OB_WIRE);
+                               drawDispList(base, OB_WIRE);
                                set_inverted_drawing(0);
                        } else {
-                               drawDispList(ob, dt);
+                               drawDispList(base, dt);
                        }
 
                        if (cu->linewidth != 0.0) {
@@ -3781,7 +3787,7 @@ void draw_object(Base *base, int flag)
                else if(dt==OB_BOUNDBOX) 
                        draw_bounding_volume(ob);
                else if(boundbox_clip(ob->obmat, cu->bb)) 
-                       empty_object= drawDispList(ob, dt);
+                       empty_object= drawDispList(base, dt);
                        
                break;
        case OB_CURVE:
@@ -3791,21 +3797,21 @@ void draw_object(Base *base, int flag)
                if (cu->disp.first==NULL) makeDispListCurveTypes(ob, 0);
                
                if(ob==G.obedit) {
-                       drawnurb(ob, editNurb.first, dt);
+                       drawnurb(base, editNurb.first, dt);
                }
                else if(dt==OB_BOUNDBOX) 
                        draw_bounding_volume(ob);
                else if(boundbox_clip(ob->obmat, cu->bb)) 
-                       empty_object= drawDispList(ob, dt);
+                       empty_object= drawDispList(base, dt);
                
                break;
        case OB_MBALL:
                if(ob==G.obedit) 
-                       drawmball(ob, dt);
+                       drawmball(base, dt);
                else if(dt==OB_BOUNDBOX) 
                        draw_bounding_volume(ob);
                else 
-                       empty_object= drawmball(ob, dt);
+                       empty_object= drawmball(base, dt);
                break;
        case OB_EMPTY:
                drawaxes(1.0, flag);
@@ -4155,7 +4161,7 @@ void draw_object_instance(Object *ob, int dt, int outline)
                        draw_mesh_object_outline(ob, dm?dm:edm);
 
                if(dm)
-                       init_gl_materials(ob);
+                       init_gl_materials(ob, 0);
                else {
                        glEnable(GL_COLOR_MATERIAL);
                        BIF_ThemeColor(TH_BONE_SOLID);
index dcb5e39104647aeb0c691ef0623fa694982ad3a3..87bdb5f8e1ffed5ebd754d515a59126e5c25c927 100644 (file)
 #include "BSE_view.h"
 
 #include "RE_renderconverter.h"
-
 #include "BPY_extern.h"
 
 #include "blendef.h"
@@ -2046,6 +2045,14 @@ static void view3d_blockhandlers(ScrArea *sa)
 
 }
 
+/* ****************** View3d afterdraw *************** */
+
+typedef struct View3DAfter {
+       struct View3DAfter *next, *prev;
+       struct Base *base;
+       int type;
+} View3DAfter;
+
 /* temp storage of Objects that need to be drawn as last */
 void add_view3d_after(View3D *v3d, Base *base, int type)
 {
@@ -2103,6 +2110,41 @@ static void view3d_draw_transp(View3D *v3d, int flag)
 
 }
 
+/* *********************** */
+
+static void draw_dupli_objects(View3D *v3d, Base *base)
+{
+       ListBase *lb;
+       DupliObject *dob;
+       Base tbase;
+       int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
+       char dt, dtx;
+       
+       tbase.flag= OB_FROMDUPLI|base->flag;
+       lb= object_duplilist(G.scene, base->object);
+
+       for(dob= lb->first; dob; dob= dob->next) {
+               tbase.object= dob->ob;
+               
+               Mat4CpyMat4(dob->ob->obmat, dob->mat);
+               /* extra service: draw the duplicator in drawtype of parent */
+               dt= tbase.object->dt; tbase.object->dt= base->object->dt;
+               dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
+               
+               BIF_ThemeColorBlend(color, TH_BACK, 0.5);
+               draw_object(&tbase, DRAW_CONSTCOLOR);
+               
+               /* restore */
+               Mat4CpyMat4(dob->ob->obmat, dob->omat);
+               tbase.object->dt= dt;
+               tbase.object->dtx= dtx;
+       }
+       /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
+
+       BLI_freelistN(lb);
+                               
+}
+
 void drawview3dspace(ScrArea *sa, void *spacedata)
 {
        View3D *v3d= spacedata;
@@ -2203,26 +2245,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
                                draw_object(base, DRAW_CONSTCOLOR);
 
                                if(base->object->transflag & OB_DUPLI) {
-                                       extern ListBase duplilist;
-                                       Base tbase;
-                                       
-                                       tbase= *base;
-                                       
-                                       tbase.flag= OB_FROMDUPLI;
-                                       make_duplilist(G.scene->set, base->object);
-                                       ob= duplilist.first;
-                                       while(ob) {
-                                               tbase.object= ob;
-                                               BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.4f);
-                                               draw_object(&tbase, DRAW_CONSTCOLOR);
-                                               ob= ob->id.next;
-                                       }
-                                       
-                                       /* Transp afterdraw */
-                                       view3d_draw_transp(v3d, DRAW_CONSTCOLOR);
-                                       
-                                       free_duplilist();
-                                       
+                                       draw_dupli_objects(v3d, base);
                                }
                        }
                        base= base->next;
@@ -2244,23 +2267,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
                        
                        /* dupli drawing */
                        if(base->object->transflag & OB_DUPLI) {
-                               extern ListBase duplilist;
-                               Base tbase;
-
-                               tbase.flag= OB_FROMDUPLI;
-                               make_duplilist(G.scene, base->object);
-
-                               ob= duplilist.first;
-                               while(ob) {
-                                       tbase.object= ob;
-                                       BIF_ThemeColorBlend(TH_BACK, TH_WIRE, 0.5);
-                                       draw_object(&tbase, DRAW_CONSTCOLOR);
-                                       ob= ob->id.next;
-                               }
-                               /* Transp afterdraw stuff */
-                               view3d_draw_transp(v3d, DRAW_CONSTCOLOR);
-                               
-                               free_duplilist();
+                               draw_dupli_objects(v3d, base);
                        }
                        if((base->flag & SELECT)==0) {
                                if(base->object!=G.obedit) draw_object(base, 0);
@@ -2348,7 +2355,6 @@ void drawview3d_render(struct View3D *v3d)
 {
        extern short v3d_windowmode;
        Base *base;
-       Object *ob;
 
        update_for_newframe_muted();    /* first, since camera can be animated */
 
@@ -2405,21 +2411,7 @@ void drawview3d_render(struct View3D *v3d)
                                        draw_object(base, DRAW_CONSTCOLOR);
        
                                        if(base->object->transflag & OB_DUPLI) {
-                                               extern ListBase duplilist;
-                                               Base tbase;
-                                               
-                                               tbase.flag= OB_FROMDUPLI;
-                                               make_duplilist(G.scene->set, base->object);
-                                               ob= duplilist.first;
-                                               while(ob) {
-                                                       tbase.object= ob;
-                                                       draw_object(&tbase, DRAW_CONSTCOLOR);
-                                                       ob= ob->id.next;
-                                               }
-                                               /* Transp afterdraw stuff */
-                                               view3d_draw_transp(v3d, DRAW_CONSTCOLOR);
-                                               
-                                               free_duplilist();
+                                               draw_dupli_objects(v3d, base);
                                        }
                                }
                        }
@@ -2440,26 +2432,7 @@ void drawview3d_render(struct View3D *v3d)
                        else {
        
                                if(base->object->transflag & OB_DUPLI) {
-                                       extern ListBase duplilist;
-                                       Base tbase;
-                                       
-                                       draw_object(base, 0);
-                                       
-                                       BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5f);
-                                       
-                                       tbase.flag= OB_FROMDUPLI;
-                                       make_duplilist(G.scene, base->object);
-                                       ob= duplilist.first;
-                                       while(ob) {
-                                               tbase.object= ob;
-                                               draw_object(&tbase, DRAW_CONSTCOLOR);
-                                               ob= ob->id.next;
-                                       }
-                                       
-                                       /* Transp afterdraw stuff */
-                                       view3d_draw_transp(v3d, DRAW_CONSTCOLOR);
-                                       
-                                       free_duplilist();
+                                       draw_dupli_objects(v3d, base);
                                }
                                else if((base->flag & SELECT)==0) {
                                        draw_object(base, 0);
index f946a952b5baa1428621b3737ccd1fd995cb70bb..67d6701b13e7c1915055a0fb958a744ef7789859 100644 (file)
@@ -112,6 +112,11 @@ void group_operation_with_menu(void)
                }
        }
        
+       if(group && group->id.lib) {
+               error("Cannot edit library data");
+               return;
+       }
+       
        if(base)
                mode= pupmenu("Groups %t|Add to current Group %x3|Add to New Group %x1|Remove from all Groups %x2");
        else
index ea7821bc977d421464268c4e2870c50bbc62a671..e05d3b149ff71362eb6ef659c33fb28c30aff298 100644 (file)
@@ -1,15 +1,12 @@
 /**
-* $Id$
-*
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * $Id$
+ *
+ * ***** BEGIN GPL BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version. 
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
-* This file is a horrible mess: An attmept to cram some
-* final functionality into blender before it is too late.
-*
-* Hopefully it can be tidied up at a later date...
+ * ***** END GPL *****
+ *
+ * This file is a horrible mess: An attmept to cram some
+ * final functionality into blender before it is too late.
+ *
+ * Hopefully it can be tidied up at a later date...
 */
 
 #include <stdlib.h>
@@ -57,6 +55,7 @@
 
 #include "BKE_action.h"
 #include "BKE_depsgraph.h"
+#include "BKE_group.h"
 #include "BKE_global.h"
 #include "BKE_ipo.h"
 #include "BKE_library.h"
@@ -97,7 +96,6 @@ static Base *get_nearest_nlachannel_ob_key (float *index, short *sel);
 static bAction *get_nearest_nlachannel_ac_key (float *index, short *sel);
 static Base *get_nearest_nlastrip (bActionStrip **rstrip, short *sel);
 static void mouse_nlachannels(short mval[2]);
-static void add_nlablock(short mval[2]);
 static void convert_nla(short mval[2]);
 
 /* ******************** SPACE: NLA ********************** */
@@ -249,189 +247,6 @@ void snap_action_strips(void)
        allqueue (REDRAWNLA, 0);
 }
 
-void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
-{
-       unsigned short event= evt->event;
-       short val= evt->val;
-       SpaceNla *snla = curarea->spacedata.first;
-       int doredraw= 0;
-       short   mval[2];
-       float dx,dy;
-       int     cfra;
-       short mousebut = L_MOUSE;
-       
-       if (curarea->win==0) return;
-       if (!snla) return;
-       
-       if(val) {
-               if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
-               
-               /* swap mouse buttons based on user preference */
-               if (U.flag & USER_LMOUSESELECT) {
-                       if (event == LEFTMOUSE) {
-                               event = RIGHTMOUSE;
-                               mousebut = L_MOUSE;
-                       } else if (event == RIGHTMOUSE) {
-                               event = LEFTMOUSE;
-                               mousebut = R_MOUSE;
-                       }
-               }
-               
-               getmouseco_areawin(mval);
-               
-               switch(event) {
-               case UI_BUT_EVENT:
-                       do_nlabuts(val); // in drawnla.c
-                       break;
-               
-               case HOMEKEY:
-                       do_nla_buttons(B_NLAHOME);
-                       break;
-
-               case EQUALKEY:
-               case PAGEUPKEY:
-                       shift_nlastrips_up();
-                       break;
-
-               case MINUSKEY:
-               case PAGEDOWNKEY:
-                       shift_nlastrips_down();
-                       break;
-
-               case AKEY:
-                       if (G.qual & LR_SHIFTKEY){
-                               add_nlablock(mval);
-                               allqueue (REDRAWNLA, 0);
-                               allqueue (REDRAWVIEW3D, 0);
-                       }
-                       else{
-                               if (mval[0]>=NLAWIDTH)
-                                       deselect_nlachannel_keys(1);
-                               else{
-                                       deselect_nlachannels(1);
-                                       allqueue (REDRAWVIEW3D, 0);
-                               }
-                               allqueue (REDRAWNLA, 0);
-                               allqueue (REDRAWIPO, 0);
-                               BIF_undo_push("(De)select all NLA");
-                       }
-                       break;
-
-               case BKEY:
-                       borderselect_nla();
-                       break;
-
-               case CKEY:
-                       convert_nla(mval);
-                       break;
-                       
-               case DKEY:
-                       if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){
-                               duplicate_nlachannel_keys();
-                               update_for_newframe_muted();
-                       }
-                       break;
-
-               case GKEY:
-                       if (mval[0]>=NLAWIDTH)
-                               transform_nlachannel_keys ('g', 0);
-                       update_for_newframe_muted();
-                       break;
-
-               case NKEY:
-                       if(G.qual==0) {
-                               toggle_blockhandler(curarea, NLA_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
-                               scrarea_queue_winredraw(curarea);
-                       }
-                       break;
-
-               case SKEY:
-                       if(G.qual==LR_ALTKEY) {
-                               val= pupmenu("Action Strip Scale%t|Clear Strip Size%x1|Remap Start/End%x2");
-                               if(val==1)
-                                       reset_action_strips(1);
-                               else if(val==2)
-                                       reset_action_strips(2);
-                       }
-                       else if(G.qual & LR_SHIFTKEY) {
-                               if(okee("Snap Strips to Frame"))
-                                       snap_action_strips();
-                       }
-                       else {
-                               if (mval[0]>=NLAWIDTH)
-                                       transform_nlachannel_keys ('s', 0);
-                               update_for_newframe_muted();
-                       }
-                       break;
-
-               case DELKEY:
-               case XKEY:
-                       if (mval[0]>=NLAWIDTH)
-                               delete_nlachannel_keys ();
-
-                       update_for_newframe_muted();
-                       break;
-                       
-               /* LEFTMOUSE and RIGHTMOUSE event codes can be swapped above,
-                * based on user preference USER_LMOUSESELECT
-                */
-               case LEFTMOUSE:
-                       if(view2dmove(LEFTMOUSE))
-                               break; // only checks for sliders
-                       else if (mval[0]>=snla->v2d.mask.xmin) {
-                               do {
-                                       getmouseco_areawin(mval);
-                                       
-                                       areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
-                                       
-                                       cfra= (int)dx;
-                                       if(cfra< 1) cfra= 1;
-                                       
-                                       if( cfra!=CFRA ) {
-                                               CFRA= cfra;
-                                               update_for_newframe();
-                                               force_draw_all(0);
-                                       }
-                                       else PIL_sleep_ms(30);
-                                       
-                               } while(get_mbut() & mousebut);
-                               break;
-                       }
-                       /* else pass on! */
-               case RIGHTMOUSE:
-                       if (mval[0]>=snla->v2d.mask.xmin) {
-                               if(G.qual & LR_SHIFTKEY)
-                                       mouse_nla(SELECT_INVERT);
-                               else
-                                       mouse_nla(SELECT_REPLACE);
-                       }
-                       else
-                               mouse_nlachannels(mval);
-                       break;
-
-               case PADPLUSKEY:
-                       view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy);
-                       test_view2d(G.v2d, sa->winx, sa->winy);
-                       view2d_do_locks(curarea, V2D_LOCK_COPY);
-                       doredraw= 1;
-                       break;
-               case PADMINUS:
-                       view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy);
-                       test_view2d(G.v2d, sa->winx, sa->winy);
-                       view2d_do_locks(curarea, V2D_LOCK_COPY);
-                       doredraw= 1;
-                       break;
-               case MIDDLEMOUSE:
-               case WHEELUPMOUSE:
-               case WHEELDOWNMOUSE:
-                       view2dmove(event);      /* in drawipo.c */
-                       break;
-               }
-       }
-       
-       if(doredraw) scrarea_queue_winredraw(curarea);
-}
-
 static void set_active_strip(Object *ob, bActionStrip *act)
 {
        bActionStrip *strip;
@@ -444,9 +259,13 @@ static void set_active_strip(Object *ob, bActionStrip *act)
        
                if(ob->action!=act->act) {
                        if(ob->action) ob->action->id.us--;
-                       ob->action= act->act;
-                       ob->action->id.us++;
-                       
+                       if(act->act->id.lib) {
+                               ob->action= NULL;
+                       }
+                       else {
+                               ob->action= act->act;
+                               id_us_plus(&ob->action->id);
+                       }                       
                        allqueue(REDRAWIPO, 0);
                        allqueue(REDRAWVIEW3D, 0);
                        allqueue(REDRAWACTION, 0);
@@ -556,11 +375,9 @@ static void convert_nla(short mval[2])
        }
 }
 
-
-static Base *nla_base=NULL;    /* global, bad, bad! put it in nla space later, or recode the 2 functions below (ton) */
-
 static void add_nla_block(short event)
 {
+       Object *ob= OBACT;
        bAction *act=NULL;
        bActionStrip *strip;
        int             cur;
@@ -585,23 +402,24 @@ static void add_nla_block(short event)
        
        /* Link the action to the strip */
        strip->act = act;
+       id_us_plus(&act->id);
        calc_action_range(strip->act, &strip->actstart, &strip->actend);
        strip->start = G.scene->r.cfra;         /* could be mval[0] another time... */
        strip->end = strip->start + (strip->actend-strip->actstart);
                /* simple prevention of zero strips */
        if(strip->start>strip->end-2) 
                strip->end= strip->start+100;
-       
-       strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION;
-       
-       find_stridechannel(nla_base->object, strip);
-       set_active_strip(nla_base->object, strip);
-       
        strip->repeat = 1.0;
        
-       act->id.us++;
+       strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION;
        
-       BLI_addtail(&nla_base->object->nlastrips, strip);
+       find_stridechannel(ob, strip);
+       set_active_strip(ob, strip);
+       strip->object= group_get_member_with_action(ob->dup_group, act);
+       if(strip->object)
+               id_lib_extern(&strip->object->id);      /* checks lib data, sets correct flag for saving then */
+
+       BLI_addtail(&ob->nlastrips, strip);
 
        BIF_undo_push("Add NLA strip");
 }
@@ -611,70 +429,29 @@ static void add_nla_databrowse_callback(unsigned short val)
        /* val is not used, databrowse needs it to optional pass an event */
        short event;
        
-       if(nla_base==NULL) return;
+       if(OBACT==NULL) return;
        
        event= G.snla->menunr;  /* set by databrowse or pupmenu */
        
        add_nla_block(event);
 }
 
-static void add_nlablock(short mval[2])
+/* Adds strip to to active Object */
+static void add_nlablock(void)
 {
-       /* Make sure we are over an object with action */
-       Base *base;
-       rctf    rectf;
-       float ymin, ymax;
-       float x, y;
+       Object *ob= OBACT;
        short event;
        short nr;
-       char *str;
-
-       areamouseco_to_ipoco(G.v2d, mval, &x, &y);
-       
-       mval[0]-=7;
-       areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
+       char *str, title[64];
        
-       mval[0]+=14;
-       areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
-
-       ymax = count_nla_levels();      
-       ymax*= (NLACHANNELHEIGHT + NLACHANNELSKIP);
-       ymax+= NLACHANNELHEIGHT/2;
-
-       for (base=G.scene->base.first; base; base=base->next){
-               /* Handle object ipo selection */
-               if (nla_filter(base)) {
-                       
-                       /* Area that encloses object name (or ipo) */
-                       ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP);
-
-                       /* Area that encloses action */
-                       if (base->object->action)
-                               ymin-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
-
-                       /* Area that encloses nla strips */
-                       ymin-=(NLACHANNELHEIGHT+NLACHANNELSKIP)*
-                               (BLI_countlist(&base->object->nlastrips));
-
-                       /* Test to see the mouse is in an action area */
-                       if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
-                               break;          
-                       
-                       ymax=ymin;
-               }
-       }       
-       
-       /* global... for the call above, because the NLA system seems not to have an 'active strip' stored */
-       nla_base= base;
-       
-       /* Make sure we have an action */
-       if (!base){
-               error ("Object has not an Action");
+       if(ob==NULL) {
+               error("Need active Object to add NLA strips");
                return;
        }
        
        /* Popup action menu */
-       IDnames_to_pupstring(&str, "Add Action", NULL, &G.main->action, (ID *)G.scene, &nr);
+       sprintf(title, "Add Action strip to %s", ob->id.name+2);
+       IDnames_to_pupstring(&str, title, NULL, &G.main->action, (ID *)G.scene, &nr);
        
        if(strncmp(str+13, "DataBrow", 8)==0) {
                MEM_freeN(str);
@@ -689,11 +466,6 @@ static void add_nlablock(short mval[2])
                MEM_freeN(str);
                add_nla_block(event);
        }
-       
-       /* Ton: this is a callback for databrowse too
-          Hos: no, I don't think it is
-          add_nla_block(0);
-       */
 }
 
 /* Left hand side of channels display, selects objects */
@@ -1761,3 +1533,187 @@ void deselect_nlachannels(int test)
                base->object->flag= base->flag;
        }       
 }
+
+void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
+{
+       unsigned short event= evt->event;
+       short val= evt->val;
+       SpaceNla *snla = curarea->spacedata.first;
+       int doredraw= 0;
+       short   mval[2];
+       float dx,dy;
+       int     cfra;
+       short mousebut = L_MOUSE;
+       
+       if (curarea->win==0) return;
+       if (!snla) return;
+       
+       if(val) {
+               if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+               
+               /* swap mouse buttons based on user preference */
+               if (U.flag & USER_LMOUSESELECT) {
+                       if (event == LEFTMOUSE) {
+                               event = RIGHTMOUSE;
+                               mousebut = L_MOUSE;
+                       } else if (event == RIGHTMOUSE) {
+                               event = LEFTMOUSE;
+                               mousebut = R_MOUSE;
+                       }
+               }
+               
+               getmouseco_areawin(mval);
+               
+               switch(event) {
+                       case UI_BUT_EVENT:
+                               do_nlabuts(val); // in drawnla.c
+                               break;
+                               
+                       case HOMEKEY:
+                               do_nla_buttons(B_NLAHOME);
+                               break;
+                               
+                       case EQUALKEY:
+                       case PAGEUPKEY:
+                               shift_nlastrips_up();
+                               break;
+                               
+                       case MINUSKEY:
+                       case PAGEDOWNKEY:
+                               shift_nlastrips_down();
+                               break;
+                               
+                       case AKEY:
+                               if (G.qual & LR_SHIFTKEY){
+                                       add_nlablock();
+                                       allqueue (REDRAWNLA, 0);
+                                       allqueue (REDRAWVIEW3D, 0);
+                               }
+                               else{
+                                       if (mval[0]>=NLAWIDTH)
+                                               deselect_nlachannel_keys(1);
+                                       else{
+                                               deselect_nlachannels(1);
+                                               allqueue (REDRAWVIEW3D, 0);
+                                       }
+                                       allqueue (REDRAWNLA, 0);
+                                       allqueue (REDRAWIPO, 0);
+                                       BIF_undo_push("(De)select all NLA");
+                               }
+                               break;
+                               
+                       case BKEY:
+                               borderselect_nla();
+                               break;
+                               
+                       case CKEY:
+                               convert_nla(mval);
+                               break;
+                               
+                       case DKEY:
+                               if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){
+                                       duplicate_nlachannel_keys();
+                                       update_for_newframe_muted();
+                               }
+                               break;
+                               
+                       case GKEY:
+                               if (mval[0]>=NLAWIDTH)
+                                       transform_nlachannel_keys ('g', 0);
+                               update_for_newframe_muted();
+                               break;
+                               
+                       case NKEY:
+                               if(G.qual==0) {
+                                       toggle_blockhandler(curarea, NLA_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
+                                       scrarea_queue_winredraw(curarea);
+                               }
+                               break;
+                               
+                       case SKEY:
+                               if(G.qual==LR_ALTKEY) {
+                                       val= pupmenu("Action Strip Scale%t|Clear Strip Size%x1|Remap Start/End%x2");
+                                       if(val==1)
+                                               reset_action_strips(1);
+                                       else if(val==2)
+                                               reset_action_strips(2);
+                               }
+                               else if(G.qual & LR_SHIFTKEY) {
+                                       if(okee("Snap Strips to Frame"))
+                                               snap_action_strips();
+                               }
+                               else {
+                                       if (mval[0]>=NLAWIDTH)
+                                               transform_nlachannel_keys ('s', 0);
+                                       update_for_newframe_muted();
+                               }
+                               break;
+                               
+                       case DELKEY:
+                       case XKEY:
+                               if (mval[0]>=NLAWIDTH)
+                                       delete_nlachannel_keys ();
+                               
+                               update_for_newframe_muted();
+                               break;
+                               
+                               /* LEFTMOUSE and RIGHTMOUSE event codes can be swapped above,
+                               * based on user preference USER_LMOUSESELECT
+                               */
+                       case LEFTMOUSE:
+                               if(view2dmove(LEFTMOUSE))
+                                       break; // only checks for sliders
+                               else if (mval[0]>=snla->v2d.mask.xmin) {
+                                       do {
+                                               getmouseco_areawin(mval);
+                                               
+                                               areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
+                                               
+                                               cfra= (int)dx;
+                                               if(cfra< 1) cfra= 1;
+                                               
+                                               if( cfra!=CFRA ) {
+                                                       CFRA= cfra;
+                                                       update_for_newframe();
+                                                       force_draw_all(0);
+                                               }
+                                               else PIL_sleep_ms(30);
+                                               
+                                       } while(get_mbut() & mousebut);
+                                       break;
+                               }
+                                       /* else pass on! */
+                               case RIGHTMOUSE:
+                                       if (mval[0]>=snla->v2d.mask.xmin) {
+                                               if(G.qual & LR_SHIFTKEY)
+                                                       mouse_nla(SELECT_INVERT);
+                                               else
+                                                       mouse_nla(SELECT_REPLACE);
+                                       }
+                                       else
+                                               mouse_nlachannels(mval);
+                                       break;
+                                       
+                               case PADPLUSKEY:
+                                       view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy);
+                                       test_view2d(G.v2d, sa->winx, sa->winy);
+                                       view2d_do_locks(curarea, V2D_LOCK_COPY);
+                                       doredraw= 1;
+                                       break;
+                               case PADMINUS:
+                                       view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy);
+                                       test_view2d(G.v2d, sa->winx, sa->winy);
+                                       view2d_do_locks(curarea, V2D_LOCK_COPY);
+                                       doredraw= 1;
+                                       break;
+                               case MIDDLEMOUSE:
+                               case WHEELUPMOUSE:
+                               case WHEELDOWNMOUSE:
+                                       view2dmove(event);      /* in drawipo.c */
+                                       break;
+               }
+       }
+       
+       if(doredraw) scrarea_queue_winredraw(curarea);
+}
+
index 894f787a2d2b8c38a2a7db764fd1a804bbad2200..32f42644625d1962f796df63c849844565f0d231 100644 (file)
@@ -3133,7 +3133,7 @@ void make_duplilist_real()
 {
        Base *base, *basen;
        Object *ob;
-       extern ListBase duplilist;
+//     extern ListBase duplilist;
        
        if(okee("Make dupli objects real")==0) return;
        
@@ -3142,11 +3142,11 @@ void make_duplilist_real()
                if TESTBASELIB(base) {
 
                        if(base->object->transflag & OB_DUPLI) {
-                               
-                               make_duplilist(G.scene, base->object);
-                               ob= duplilist.first;
-                               while(ob) {
-                                       
+                               ListBase *lb= object_duplilist(G.scene, base->object);
+                               DupliObject *dob;
+
+                               for(dob= lb->first; dob; dob= dob->next) {
+                                       ob= copy_object(dob->ob);
                                        /* font duplis can have a totcol without material, we get them from parent
                                         * should be implemented better...
                                         */
@@ -3155,19 +3155,17 @@ void make_duplilist_real()
                                        basen= MEM_dupallocN(base);
                                        basen->flag &= ~OB_FROMDUPLI;
                                        BLI_addhead(&G.scene->base, basen);     /* addhead: othwise eternal loop */
+                                       basen->object= ob;
                                        ob->ipo= NULL;          /* make sure apply works */
                                        ob->parent= ob->track= NULL;
                                        ob->disp.first= ob->disp.last= NULL;
-                                       ob->transflag &= ~OB_DUPLI;
-                                       basen->object= copy_object(ob);
-                                       basen->object->flag &= ~OB_FROMDUPLI;
-                                       
-                                       apply_obmat(basen->object);
+                                       ob->transflag &= ~OB_DUPLI;     
                                        
-                                       ob= ob->id.next;
+                                       Mat4CpyMat4(ob->obmat, dob->mat);
+                                       apply_obmat(ob);
                                }
                                
-                               free_duplilist();
+                               BLI_freelistN(lb);
                                
                                base->object->transflag &= ~OB_DUPLI;   
                        }
index db4c981eba25d741c88bfaec1248fe983d190d7a..269e4bc04d7437beab9ad549467dfaf3147698c7 100644 (file)
@@ -2617,7 +2617,12 @@ void main_to_filelist(SpaceFile *sfile)
                
                                if (hide==0 || id->name[2] != '.') {
                                        memset( files, 0 , sizeof(struct direntry));
-                                       files->relname= BLI_strdup(id->name+2);
+                                       if(id->lib==NULL)
+                                               files->relname= BLI_strdup(id->name+2);
+                                       else {
+                                               files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib");
+                                               sprintf(files->relname, "%s | %s", id->lib->name, id->name+2);
+                                       }
                                        
                                        if(sfile->returnfunc==0) { /* F4 DATA BROWSE */
                                                if(idcode==ID_OB) {
index 01c1ddc194d1d039cda3b0dbd4c56afd6d153c46..dbb32bf93586a65db84f3ad505eda60a85d9944a 100644 (file)
@@ -1216,6 +1216,9 @@ void do_info_addmenu(void *arg, int event)
                        /* Lattice */
                        add_object_draw(OB_LATTICE);
                        break;
+               case 10:
+                       /* group instance not yet */
+                       break;
                default:
                        break;
        }
index 7fe1ac4cbf766a5d8130dfc48577d3a8afc00830..077d43d7a5aa824578e03fba232b31f19711f810 100644 (file)
@@ -61,6 +61,7 @@
 #include "BKE_constraint.h"
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
+#include "BKE_group.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
 
 #define TS_CHUNK       128
 
-#define TREESTORE(a) soops->treestore->data+(a)->store_index
+#define TREESTORE(a) ((a)?soops->treestore->data+(a)->store_index:NULL)
 
 /* ******************** PERSISTANT DATA ***************** */
 
@@ -511,13 +512,13 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                                                te->name= md->name;
 
                                                if (md->type==eModifierType_Lattice) {
-                                                       outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_MODIFIER_OB, 0);
+                                                       outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_LINKED_OB, 0);
                                                } else if (md->type==eModifierType_Curve) {
-                                                       outliner_add_element(soops, &te->subtree, ((CurveModifierData*) md)->object, te, TSE_MODIFIER_OB, 0);
+                                                       outliner_add_element(soops, &te->subtree, ((CurveModifierData*) md)->object, te, TSE_LINKED_OB, 0);
                                                } else if (md->type==eModifierType_Armature) {
-                                                       outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_MODIFIER_OB, 0);
+                                                       outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_LINKED_OB, 0);
                                                } else if (md->type==eModifierType_Hook) {
-                                                       outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_MODIFIER_OB, 0);
+                                                       outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_LINKED_OB, 0);
                                                }
                                        }
                                }
@@ -543,6 +544,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                                                outliner_add_element(soops, &tenla->subtree, ob->scriptlink.scripts[a], te, 0, 0);
                                        }
                                }
+                               
+                               if(ob->dup_group)
+                                       outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);
+                               
                                if(ob->nlastrips.first) {
                                        bActionStrip *strip;
                                        TreeElement *ten;
@@ -775,16 +780,18 @@ static void outliner_build_tree(SpaceOops *soops)
                GroupObject *go;
                
                for(group= G.main->group.first; group; group= group->id.next) {
-                       te= outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
-                       tselem= TREESTORE(te);
-                       
-                       for(go= group->gobject.first; go; go= go->next) {
-                               ten= outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
-                               ten->directdata= NULL;
+                       if(group->id.us) {
+                               te= outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
+                               tselem= TREESTORE(te);
+                               
+                               for(go= group->gobject.first; go; go= go->next) {
+                                       ten= outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
+                                       ten->directdata= NULL;
+                               }
+                               outliner_make_hierarchy(soops, &te->subtree);
+                               /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
+                               for(go= group->gobject.first; go; go= go->next) go->ob->id.newid= NULL;
                        }
-                       outliner_make_hierarchy(soops, &te->subtree);
-                       /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
-                       for(go= group->gobject.first; go; go= go->next) go->ob->id.newid= NULL;
                }
        }
        else if(soops->outlinevis == SO_SAME_TYPE) {
@@ -1425,7 +1432,7 @@ static int tree_element_type_active(SpaceOops *soops, TreeElement *te, TreeStore
                        return tree_element_active_ebone(te, tselem, set);
                case TSE_MODIFIER:
                        return tree_element_active_modifier(te, tselem, set);
-               case TSE_MODIFIER_OB:
+               case TSE_LINKED_OB:
                        if(set) tree_element_active_object(soops, te);
                        else if(tselem->id==(ID *)OBACT) return 1;
                        break;
@@ -1710,12 +1717,9 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb)
                                                
                                        case ID_ME: case ID_CU: case ID_MB: case ID_LT:
                                        case ID_LA: case ID_AR: case ID_CA:
-                                               idlevel= -2;
-                                               break;
-                                               
                                        case ID_MA: case ID_TE: case ID_IP: case ID_IM:
                                        case ID_SO: case ID_KE: case ID_WO: case ID_AC:
-                                       case ID_NLA: case ID_TXT:
+                                       case ID_NLA: case ID_TXT: case ID_GR:
                                                if(idlevel==0) idlevel= idcode;
                                                else if(idlevel!=idcode) idlevel= -1;
                                                        break;
@@ -1726,7 +1730,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb)
        }
 }
 
-static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep)
+static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
 {
        Material **matar=NULL;
        int a, totcol=0;
@@ -1760,7 +1764,7 @@ static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep)
        }
 }
 
-static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep)
+static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
 {
        MTex **mtex= NULL;
        int a;
@@ -1789,8 +1793,25 @@ static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep)
        }
 }
 
+static void unlink_group_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+       Group *group= (Group *)tselem->id;
+       
+       if(tsep) {
+               if( GS(tsep->id->name)==ID_OB) {
+                       Object *ob= (Object *)tsep->id;
+                       ob->dup_group= NULL;
+                       group->id.us--;
+               }
+       }
+       else {
+               unlink_group(group);
+               group->id.us= 0;
+       }
+}
+
 static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb, 
-                                                                                void (*operation_cb)(TreeElement *, TreeStoreElem *))
+                                                                                void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *))
 {
        TreeElement *te;
        TreeStoreElem *tselem;
@@ -1800,7 +1821,7 @@ static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb,
                if(tselem->flag & TSE_SELECTED) {
                        if(tselem->type==0) {
                                TreeStoreElem *tsep= TREESTORE(te->parent);
-                               operation_cb(te, tsep);
+                               operation_cb(te, tsep, tselem);
                        }
                }
                if((tselem->flag & TSE_CLOSED)==0) {
@@ -1811,7 +1832,7 @@ static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb,
 
 /* */
 
-static void object_select_cb(TreeElement *te, TreeStoreElem *tselem)
+static void object_select_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
 {
        Base *base= (Base *)te->directdata;
        
@@ -1822,7 +1843,7 @@ static void object_select_cb(TreeElement *te, TreeStoreElem *tselem)
        }
 }
 
-static void object_deselect_cb(TreeElement *te, TreeStoreElem *tselem)
+static void object_deselect_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
 {
        Base *base= (Base *)te->directdata;
        
@@ -1833,7 +1854,7 @@ static void object_deselect_cb(TreeElement *te, TreeStoreElem *tselem)
        }
 }
 
-static void object_delete_cb(TreeElement *te, TreeStoreElem *tselem)
+static void object_delete_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
 {
        Base *base= (Base *)te->directdata;
        
@@ -1853,9 +1874,17 @@ static void object_delete_cb(TreeElement *te, TreeStoreElem *tselem)
        }
 }
 
+static void id_local_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+       if(tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) {
+               tselem->id->lib= NULL;
+               tselem->id->flag= LIB_LOCAL;
+               new_id(0, tselem->id, 0);
+       }
+}
 
 static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb, 
-                                                                                void (*operation_cb)(TreeElement *, TreeStoreElem *))
+                                                                                void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *))
 {
        TreeElement *te;
        TreeStoreElem *tselem;
@@ -1868,7 +1897,7 @@ static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb,
                                Scene *sce= (Scene *)outliner_search_back(soops, te, ID_SCE);
                                if(sce && G.scene != sce) set_scene(sce);
                                
-                               operation_cb(te, tselem);
+                               operation_cb(te, NULL, tselem);
                        }
                }
                if((tselem->flag & TSE_CLOSED)==0) {
@@ -1959,7 +1988,7 @@ void outliner_operation_menu(ScrArea *sa)
                //else pupmenu("Scene Operations%t|Delete");
        }
        else if(objectlevel) {
-               short event= pupmenu("Object Operations%t|Select%x1|Deselect%x2|Delete%x4");
+               short event= pupmenu("Object Operations%t|Select%x1|Deselect%x2|Delete%x4|Make Local%x5");
                if(event>0) {
                        char *str="";
                        
@@ -1979,18 +2008,21 @@ void outliner_operation_menu(ScrArea *sa)
                                DAG_scene_sort(G.scene);
                                str= "Delete Objects";
                        }
+                       else if(event==5) {
+                               outliner_do_object_operation(soops, &soops->tree, id_local_cb);
+                               str= "Localized Objects";
+                       }
                        
                        countall();
                        
                        BIF_undo_push(str);
-                       allqueue(REDRAWALL, 0); // yah... to be sure :)
+                       allqueue(REDRAWALL, 0);
                }
        }
        else if(idlevel) {
                if(idlevel==-1 || datalevel) error("Mixed selection");
-               else if(idlevel==-2) error("No operations available");
                else {
-                       short event= pupmenu("Data Operations%t|Unlink");
+                       short event= pupmenu("Data Operations%t|Unlink %x1|Make Local %x2");
                        
                        if(event==1) {
                                switch(idlevel) {
@@ -2004,12 +2036,19 @@ void outliner_operation_menu(ScrArea *sa)
                                                allqueue(REDRAWBUTSSHADING, 1);
                                                BIF_undo_push("Unlink texture");
                                                break;
+                                       case ID_GR:
+                                               outliner_do_libdata_operation(soops, &soops->tree, unlink_group_cb);
+                                               BIF_undo_push("Unlink group");
+                                               break;
                                        default:
                                                error("Not yet...");
                                }
-                               allqueue(REDRAWOOPS, 0);
-                               allqueue(REDRAWBUTSALL, 0);
-                               allqueue(REDRAWVIEW3D, 0);
+                               allqueue(REDRAWALL, 0);
+                       }
+                       else if(event==2) {
+                               outliner_do_libdata_operation(soops, &soops->tree, id_local_cb);
+                               BIF_undo_push("Localized Data");
+                               allqueue(REDRAWALL, 0); 
                        }
                }
        }
@@ -2065,7 +2104,7 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
                                BIF_draw_icon(x, y, ICON_CONSTRAINT); break;
                        case TSE_MODIFIER_BASE:
                                BIF_draw_icon(x, y, ICON_MODIFIER); break;
-                       case TSE_MODIFIER_OB:
+                       case TSE_LINKED_OB:
                                BIF_draw_icon(x, y, ICON_OBJECT); break;
                        case TSE_MODIFIER:
                        {
@@ -2279,17 +2318,21 @@ static void outliner_draw_tree_element(SpaceOops *soops, TreeElement *te, int st
                        // icons a bit higher
                tselem_draw_icon(startx+offsx, *starty+2, tselem, te);
                offsx+= OL_X;
+               
+               if(tselem->id->lib && tselem->type==0) {
+                       glPixelTransferf(GL_ALPHA_SCALE, 0.5);
+                       if(tselem->id->flag & LIB_INDIRECT)
+                               BIF_draw_icon(startx+offsx, *starty+2, ICON_DATALIB);
+                       else
+                               BIF_draw_icon(startx+offsx, *starty+2, ICON_PARLIB);
+                       glPixelTransferf(GL_ALPHA_SCALE, 1.0);
+                       offsx+= OL_X;
+               }               
                glDisable(GL_BLEND);
 
                /* name */
-               if(tselem->id->lib) {
-                       if(active==1) glColor3ub(0xBB, 0xFF, 0xFF);
-                       else glColor3ub(0, 0x30, 0x30);
-               }
-               else {
-                       if(active==1) BIF_ThemeColor(TH_TEXT_HI); 
-                       else BIF_ThemeColor(TH_TEXT);
-               }               
+               if(active==1) BIF_ThemeColor(TH_TEXT_HI); 
+               else BIF_ThemeColor(TH_TEXT);
                glRasterPos2i(startx+offsx, *starty+5);
                BIF_RasterPos(startx+offsx, *starty+5);
                BIF_DrawString(G.font, te->name, 0);
index 6238d253d359c7bf6ea40768d17fe7c0e4054e96..82839fcdeb9f4d97ee905f5bf8a9621fdef5813d 100644 (file)
 #include "BIF_language.h"
 #include "BIF_resources.h"
 
+#include "DNA_group_types.h"
 #include "DNA_image_types.h"
-#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
 #include "DNA_lamp_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_userdef_types.h"
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 
-#include "BKE_depsgraph.h"
-#include "BKE_plugin_types.h"
-#include "BKE_utildefines.h"
-#include "BKE_mesh.h"
 #include "BKE_displist.h"
+#include "BKE_depsgraph.h"
 #include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
 #include "BKE_main.h"
+#include "BKE_plugin_types.h"
+#include "BKE_utildefines.h"
 
 #include "BIF_editnla.h"
 #include "BIF_editarmature.h"
@@ -2241,6 +2243,10 @@ static TBitem addmenu_armature[]= {
 {      0, "Bone",      8, NULL},
 {  -1, "",                     0, do_info_addmenu}};
 
+/* dynamic items */
+#define TB_ADD_GROUP   6
+#define TB_ADD_LAMP            9
+
 static TBitem tb_add[]= {
 {      0, "Mesh",              0, addmenu_mesh},
 {      0, "Curve",     1, addmenu_curve},
@@ -2248,6 +2254,7 @@ static TBitem tb_add[]= {
 {      0, "Meta",      3, addmenu_meta},
 {      0, "Text",              4, NULL},
 {      0, "Empty",     5, NULL},
+{      0, "Group",     10, NULL},
 {      0, "SEPR",              0, NULL},
 {      0, "Camera",    6, NULL},
 {      0, "Lamp",              7, addmenu_lamp},
@@ -2256,21 +2263,6 @@ static TBitem tb_add[]= {
 {      0, "Lattice",   9, NULL},
 {  -1, "",                     0, do_info_addmenu}};
 
-static TBitem tb_add_YF[]= {
-{      0, "Mesh",              0, addmenu_mesh},
-{      0, "Curve",     1, addmenu_curve},
-{      0, "Surface",   2, addmenu_surf},
-{      0, "Meta",      3, addmenu_meta},
-{      0, "Text",              4, NULL},
-{      0, "Empty",     5, NULL},
-{      0, "SEPR",              0, NULL},
-{      0, "Camera",    6, NULL},
-{      0, "Lamp",              7, addmenu_YF_lamp},
-{      0, "SEPR",              0, NULL},
-{      0, "Armature",  8, NULL},
-{      0, "Lattice",   9, NULL},
-{  -1, "",                     0, do_info_addmenu}};
-
 static TBitem tb_empty[]= {
 {      0, "Nothing...",        0, NULL},
 {  -1, "",             0, NULL}};
@@ -2361,13 +2353,57 @@ static void store_main(void *arg1, void *arg2)
        tb_mainy= (int)arg2;
 }
 
+static void do_group_addmenu(void *arg, int event)
+{
+       Object *ob;
+       
+       add_object_draw(OB_EMPTY);
+       ob= OBACT;
+       
+       ob->dup_group= BLI_findlink(&G.main->group, event);
+       if(ob->dup_group) {
+               id_us_plus((ID *)ob->dup_group);
+               ob->transflag |= OB_DUPLIGROUP;
+       }
+}
+                                                        
+/* example of dynamic toolbox sublevel */
+static TBitem *create_group_sublevel(void)
+{
+       static TBitem addmenu[]= { {    0, "No Groups",         0, NULL}, {  -1, "",                    0, NULL}};
+       TBitem *groupmenu;
+       Group *group;
+       int a;
+       
+       int tot= BLI_countlist(&G.main->group);
+       
+       if(tot==0) {
+               tb_add[TB_ADD_GROUP].poin= addmenu;
+               return NULL;
+       }
+       
+       groupmenu= MEM_callocN(sizeof(TBitem)*(tot+1), "group menu");
+       for(a=0, group= G.main->group.first; group; group= group->id.next, a++) {
+               groupmenu[a].name= group->id.name+2;
+               groupmenu[a].retval= a;
+       }
+       groupmenu[a].icon= -1;  /* end signal */
+       groupmenu[a].name= "";
+       groupmenu[a].retval= a;
+       groupmenu[a].poin= do_group_addmenu;
+       
+       tb_add[TB_ADD_GROUP].poin= groupmenu;
+       
+       return groupmenu;
+}
+
 void toolbox_n(void)
 {
        uiBlock *block;
        uiBut *but;
        TBitem *menu1=NULL, *menu2=NULL, *menu3=NULL; 
        TBitem *menu4=NULL, *menu5=NULL, *menu6=NULL;
-       TBitem *menu7=NULL;
+       TBitem *menu7=NULL, *groupmenu;
        int dx=0;
        short event, mval[2], tot=0;
        char *str1=NULL, *str2=NULL, *str3=NULL, *str4=NULL, *str5=NULL, *str6=NULL, *str7=NULL;
@@ -2389,16 +2425,19 @@ void toolbox_n(void)
        uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
        uiBlockSetCol(block, TH_MENU_ITEM);
        
+       /* dynamic menu entries */
+       groupmenu= create_group_sublevel();
+       
+       if (G.scene->r.renderer==R_YAFRAY)
+               tb_add[TB_ADD_LAMP].poin= addmenu_YF_lamp;
+       else
+               tb_add[TB_ADD_LAMP].poin= addmenu_lamp;
+       
        /* select context for main items */
        if(curarea->spacetype==SPACE_VIEW3D) {
 
                if(U.uiflag & USER_PLAINMENUS) {
-                       /* column layout menu */
-                       if (G.scene->r.renderer==R_YAFRAY) {
-                               menu1= tb_add_YF; str1= "Add";
-                       } else {
-                                menu1= tb_add; str1= "Add";
-                       }
+                       menu1= tb_add; str1= "Add";
                        menu2= tb_object_edit; str2= "Edit";
                        menu3= tb_object_select; str3= "Select";
                        menu4= tb_transform; str4= "Transform";
@@ -2411,11 +2450,7 @@ void toolbox_n(void)
                } else {
                        /* 3x2 layout menu */
                        menu1= tb_object; str1= "Object";
-                       if (G.scene->r.renderer==R_YAFRAY) {
-                               menu2= tb_add_YF; str2= "Add";
-                       } else {
-                               menu2= tb_add; str2= "Add";
-                       }
+                       menu2= tb_add; str2= "Add";
                        menu3= tb_object_select; str3= "Select";
                        menu4= tb_object_edit; str4= "Edit";
                        menu5= tb_transform; str5= "Transform";
@@ -2599,6 +2634,8 @@ void toolbox_n(void)
        uiBoundsBlock(block, 2);
        event= uiDoBlocks(&tb_listb, 0);
        
+       if(groupmenu) MEM_freeN(groupmenu);
+       
        mywinset(curarea->win);
 }
 
index 6f6a01de09b36c3a54aba387083f2c691a1ea4e1..5de5e134c4bd7f8f7d7411ed2cbfcd55c057872d 100644 (file)
 #include "DNA_userdef_types.h"
 #include "DNA_view3d_types.h"
 
-#include "BKE_utildefines.h"
-#include "BKE_object.h"
+#include "BKE_anim.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
 
 #include "BIF_gl.h"
 #include "BIF_space.h"
@@ -1012,6 +1013,27 @@ short  view3d_opengl_select(unsigned int *buffer, unsigned int bufsize, short x1
                                base->selcol= code;
                                glLoadName(code);
                                draw_object(base, DRAW_PICKING|DRAW_CONSTCOLOR);
+                               
+                               /* we draw group-duplicators for selection too */
+                               if((base->object->transflag & OB_DUPLI) && base->object->dup_group) {
+                                       ListBase *lb;
+                                       DupliObject *dob;
+                                       Base tbase;
+                                       
+                                       tbase.flag= OB_FROMDUPLI;
+                                       lb= object_duplilist(G.scene, base->object);
+                                       
+                                       for(dob= lb->first; dob; dob= dob->next) {
+                                               tbase.object= dob->ob;
+                                               Mat4CpyMat4(dob->ob->obmat, dob->mat);
+                                               
+                                               draw_object(&tbase, DRAW_PICKING|DRAW_CONSTCOLOR);
+                                               
+                                               Mat4CpyMat4(dob->ob->obmat, dob->omat);
+                                       }
+                                       BLI_freelistN(lb);
+                               }
+                               
                                code++;
                        }
                }