Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2005-12-11 16:23:30 +0300
committerTon Roosendaal <ton@blender.org>2005-12-11 16:23:30 +0300
commitd7bee8c1172f5d1f27fa51c740b0ae2d29996caf (patch)
tree3f9546167324da0880bab5c7daec1e853575f242 /source
parent485dd1d37673d229db9062d8cad98e624d79c8ec (diff)
Big commit with work on Groups & Libraries:
-> 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... :)
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_anim.h10
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h2
-rw-r--r--source/blender/blenkernel/BKE_displist.h3
-rw-r--r--source/blender/blenkernel/BKE_font.h9
-rw-r--r--source/blender/blenkernel/BKE_group.h17
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c2
-rw-r--r--source/blender/blenkernel/intern/action.c3
-rw-r--r--source/blender/blenkernel/intern/anim.c217
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c23
-rw-r--r--source/blender/blenkernel/intern/displist.c19
-rw-r--r--source/blender/blenkernel/intern/font.c89
-rw-r--r--source/blender/blenkernel/intern/group.c151
-rw-r--r--source/blender/blenkernel/intern/mball.c8
-rw-r--r--source/blender/blenkernel/intern/nla.c3
-rw-r--r--source/blender/blenkernel/intern/object.c23
-rw-r--r--source/blender/blenkernel/intern/scene.c39
-rw-r--r--source/blender/blenloader/intern/readfile.c16
-rw-r--r--source/blender/include/BIF_outliner.h2
-rw-r--r--source/blender/include/BSE_drawview.h3
-rw-r--r--source/blender/makesdna/DNA_group_types.h2
-rw-r--r--source/blender/makesdna/DNA_nla_types.h3
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h12
-rw-r--r--source/blender/render/intern/source/rendercore.c1
-rw-r--r--source/blender/renderconverter/intern/convertBlenderScene.c32
-rw-r--r--source/blender/src/butspace.c2
-rw-r--r--source/blender/src/drawnla.c20
-rw-r--r--source/blender/src/drawobject.c76
-rw-r--r--source/blender/src/drawview.c121
-rw-r--r--source/blender/src/editgroup.c5
-rw-r--r--source/blender/src/editnla.c486
-rw-r--r--source/blender/src/editobject.c24
-rw-r--r--source/blender/src/filesel.c7
-rw-r--r--source/blender/src/header_info.c3
-rw-r--r--source/blender/src/outliner.c131
-rw-r--r--source/blender/src/toolbox.c103
-rw-r--r--source/blender/src/view.c26
36 files changed, 944 insertions, 749 deletions
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index e4cd8e39aca..69fb83aac30 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -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
diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h
index 5dd820d5a79..294f61e54bd 100644
--- a/source/blender/blenkernel/BKE_depsgraph.h
+++ b/source/blender/blenkernel/BKE_depsgraph.h
@@ -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
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 2dcf4bfe1be..05a1cfc5376 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -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);
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
index 00a994672be..05621a4d9b2 100644
--- a/source/blender/blenkernel/BKE_font.h
+++ b/source/blender/blenkernel/BKE_font.h
@@ -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);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 2d42a9e284c..db4c83040a8 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -37,15 +37,20 @@
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
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 04c4d180927..a0713d3a7dd 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -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) {
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index d5fa6958dff..211e552f493 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -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) ) {
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 5b5f1fabdf2..5700be0fcbc 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -49,17 +49,20 @@
#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) {
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 36071d39207..18c8de24feb 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -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 */
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 219ef69d6d2..c27245fc11e 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -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));
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 2ab13fe328a..b5ed7fb3688 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -73,13 +73,6 @@
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);
-}
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 0ae6208c9de..5e2d0d6fc6d 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -32,19 +32,24 @@
#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;
+}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index ea1608d8a18..09408e4a220 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 5adde76accc..5fefc41f77c 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -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;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 7af6ef21e32..e7cf3577a99 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -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);
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index fd0a6288dbe..df9e626abbf 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -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;
}
-
}
}
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index aef5f82f6f6..f8185b229ae 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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);
}
diff --git a/source/blender/include/BIF_outliner.h b/source/blender/include/BIF_outliner.h
index 1a33b3d0810..442247864b5 100644
--- a/source/blender/include/BIF_outliner.h
+++ b/source/blender/include/BIF_outliner.h
@@ -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
diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h
index b0e40699f42..4a9876705e6 100644
--- a/source/blender/include/BSE_drawview.h
+++ b/source/blender/include/BSE_drawview.h
@@ -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);
diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h
index 2ee699839ed..09ecc3a68c1 100644
--- a/source/blender/makesdna/DNA_group_types.h
+++ b/source/blender/makesdna/DNA_group_types.h
@@ -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;
diff --git a/source/blender/makesdna/DNA_nla_types.h b/source/blender/makesdna/DNA_nla_types.h
index bf3d7820dae..fa1a4fbe456 100644
--- a/source/blender/makesdna/DNA_nla_types.h
+++ b/source/blender/makesdna/DNA_nla_types.h
@@ -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) */
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index bf4f44a421d..3e1628a658c 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -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;
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 0d6e141df5f..f5b14fccaed 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -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) {
diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c
index 3b694813e91..f50a95bcbc9 100644
--- a/source/blender/renderconverter/intern/convertBlenderScene.c
+++ b/source/blender/renderconverter/intern/convertBlenderScene.c
@@ -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),
diff --git a/source/blender/src/butspace.c b/source/blender/src/butspace.c
index 752e831c2b4..43813f7f907 100644
--- a/source/blender/src/butspace.c
+++ b/source/blender/src/butspace.c
@@ -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;
diff --git a/source/blender/src/drawnla.c b/source/blender/src/drawnla.c
index 2b0ba1a7ad3..bb6e77bc507 100644
--- a/source/blender/src/drawnla.c
+++ b/source/blender/src/drawnla.c
@@ -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");
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index 10fdbee4dba..b4bdd066ed4 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -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);
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
index dcb5e391046..87bdb5f8e1f 100644
--- a/source/blender/src/drawview.c
+++ b/source/blender/src/drawview.c
@@ -122,7 +122,6 @@
#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);
diff --git a/source/blender/src/editgroup.c b/source/blender/src/editgroup.c
index f946a952b5b..67d6701b13e 100644
--- a/source/blender/src/editgroup.c
+++ b/source/blender/src/editgroup.c
@@ -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
diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c
index ea7821bc977..e05d3b149ff 100644
--- a/source/blender/src/editnla.c
+++ b/source/blender/src/editnla.c
@@ -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
@@ -27,11 +24,12 @@
*
* 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);
+}
+
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 894f787a2d2..32f42644625 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -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;
}
diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c
index db4c981eba2..269e4bc04d7 100644
--- a/source/blender/src/filesel.c
+++ b/source/blender/src/filesel.c
@@ -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) {
diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c
index 01c1ddc194d..dbb32bf9358 100644
--- a/source/blender/src/header_info.c
+++ b/source/blender/src/header_info.c
@@ -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;
}
diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c
index 7fe1ac4cbf7..077d43d7a5a 100644
--- a/source/blender/src/outliner.c
+++ b/source/blender/src/outliner.c
@@ -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"
@@ -110,7 +111,7 @@
#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);
diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c
index 6238d253d35..82839fcdeb9 100644
--- a/source/blender/src/toolbox.c
+++ b/source/blender/src/toolbox.c
@@ -55,10 +55,11 @@
#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"
@@ -67,13 +68,14 @@
#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);
}
diff --git a/source/blender/src/view.c b/source/blender/src/view.c
index 6f6a01de09b..5de5e134c4b 100644
--- a/source/blender/src/view.c
+++ b/source/blender/src/view.c
@@ -61,10 +61,11 @@
#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++;
}
}