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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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++;
}
}