New feature: Face Duplicators. Like vertex-duplicator, but now on a face
center, rotated according to face edges, and optionally with scale of the face. http://www.blender3d.org/cms/Face_Duplicator.828.0.html Also: bugfix in undo/redo for relinking data to the UI. It was not checking for Library data, accidentally linking non-library data with same names.
This commit is contained in:
@@ -872,7 +872,7 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
|
||||
|
||||
/* store vertexes indices in tmp union */
|
||||
for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
|
||||
ev->tmp.l = (long) i++;
|
||||
ev->tmp.l = (long) i;
|
||||
|
||||
for( ; ef; ef = ef->next, ++face_r) {
|
||||
face_r->mat_nr = ef->mat_nr;
|
||||
|
||||
@@ -457,6 +457,107 @@ static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par)
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
|
||||
{
|
||||
Object *ob;
|
||||
Base *base;
|
||||
DerivedMesh *dm;
|
||||
MFace *mface;
|
||||
MVert *mvert;
|
||||
float pmat[4][4];
|
||||
int lay, totface, a;
|
||||
|
||||
Mat4CpyMat4(pmat, par->obmat);
|
||||
|
||||
lay= G.scene->lay;
|
||||
|
||||
if(par==G.obedit) {
|
||||
int totvert;
|
||||
dm= editmesh_get_derived_cage();
|
||||
|
||||
totface= dm->getNumFaces(dm);
|
||||
mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp");
|
||||
dm->copyFaceArray(dm, mface);
|
||||
totvert= dm->getNumVerts(dm);
|
||||
mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp");
|
||||
dm->copyVertArray(dm, mvert);
|
||||
}
|
||||
else {
|
||||
dm = mesh_get_derived_deform(par);
|
||||
|
||||
totface= dm->getNumFaces(dm);
|
||||
mface= dm->getFaceArray(dm);
|
||||
mvert= dm->getVertArray(dm);
|
||||
}
|
||||
|
||||
|
||||
for(base= sce->base.first; base; base= base->next) {
|
||||
|
||||
if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) {
|
||||
ob= base->object->parent;
|
||||
while(ob) {
|
||||
if(ob==par) {
|
||||
|
||||
ob= base->object;
|
||||
|
||||
/* mballs have a different dupli handling */
|
||||
if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */
|
||||
|
||||
for(a=0; a<totface; a++) {
|
||||
float *v1= mvert[ mface[a].v1 ].co;
|
||||
float *v2= mvert[ mface[a].v2 ].co;
|
||||
float *v3= mvert[ mface[a].v3 ].co;
|
||||
float *v4= mface[a].v4?mvert[ mface[a].v4 ].co:NULL;
|
||||
float cent[3], quat[4], mat[3][3], tmat[4][4], obmat[4][4];
|
||||
|
||||
/* translation */
|
||||
if(v4)
|
||||
CalcCent4f(cent, v1, v2, v3, v4);
|
||||
else
|
||||
CalcCent3f(cent, v1, v2, v3);
|
||||
Mat4MulVecfl(pmat, cent);
|
||||
|
||||
VecSubf(cent, cent, pmat[3]);
|
||||
VecAddf(cent, cent, ob->obmat[3]);
|
||||
|
||||
Mat4CpyMat4(obmat, ob->obmat);
|
||||
VECCOPY(obmat[3], cent);
|
||||
|
||||
/* rotation */
|
||||
triatoquat(v1, v2, v3, quat);
|
||||
QuatToMat3(quat, mat);
|
||||
|
||||
/* scale */
|
||||
if(par->transflag & OB_DUPLIFACES_SCALE) {
|
||||
float size= v4?AreaQ3Dfl(v1, v2, v3, v4):AreaT3Dfl(v1, v2, v3);
|
||||
size= sqrt(size);
|
||||
Mat3MulFloat(mat[0], size);
|
||||
}
|
||||
|
||||
Mat4CpyMat4(tmat, obmat);
|
||||
Mat4MulMat43(obmat, tmat, mat);
|
||||
|
||||
new_dupli_object(lb, ob, obmat, lay, a);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
ob= ob->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(par==G.obedit) {
|
||||
MEM_freeN(mface);
|
||||
MEM_freeN(mvert);
|
||||
}
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void particle_duplilist(ListBase *lb, Scene *sce, Object *par, PartEff *paf)
|
||||
{
|
||||
Object *ob, copyob;
|
||||
@@ -670,16 +771,20 @@ ListBase *object_duplilist(Scene *sce, Object *ob)
|
||||
if(ob->transflag & OB_DUPLI) {
|
||||
if(ob->transflag & OB_DUPLIVERTS) {
|
||||
if(ob->type==OB_MESH) {
|
||||
if(ob->transflag & OB_DUPLIVERTS) {
|
||||
PartEff *paf;
|
||||
if( (paf=give_parteff(ob)) ) particle_duplilist(&duplilist, sce, ob, paf);
|
||||
else vertex_duplilist(&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(&duplilist, ob);
|
||||
}
|
||||
}
|
||||
else if(ob->transflag & OB_DUPLIFACES) {
|
||||
if(ob->type==OB_MESH)
|
||||
face_duplilist(&duplilist, sce, ob);
|
||||
}
|
||||
else if(ob->transflag & OB_DUPLIFRAMES)
|
||||
frames_duplilist(&duplilist, ob);
|
||||
else if(ob->transflag & OB_DUPLIGROUP) {
|
||||
|
||||
@@ -538,7 +538,8 @@ ID *find_id(char *type, char *name) /* type: "OB" or "MA" etc */
|
||||
|
||||
id= lb->first;
|
||||
while(id) {
|
||||
if( strcmp(id->name+2, name)==0 ) return id;
|
||||
if(id->name[2]==name[0] && strcmp(id->name+2, name)==0 )
|
||||
return id;
|
||||
id= id->next;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -3419,26 +3419,30 @@ static void lib_link_screen(FileData *fd, Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
/* Only for undo files, or to restore a screen after reading without UI... */
|
||||
static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
|
||||
{
|
||||
ListBase *lb;
|
||||
ID *idn=NULL;
|
||||
|
||||
if(id) {
|
||||
lb= wich_libbase(mainp, GS(id->name));
|
||||
ListBase *lb= wich_libbase(mainp, GS(id->name));
|
||||
|
||||
if(lb) { // there's still risk of checking corrupt mem (freed Ids in oops)
|
||||
idn= lb->first;
|
||||
ID *idn= lb->first;
|
||||
char *name= id->name+2;
|
||||
|
||||
while(idn) {
|
||||
if( strcmp(idn->name, id->name)==0) {
|
||||
if(user && idn->us==0) idn->us++;
|
||||
break;
|
||||
if(idn->name[2]==name[0] && strcmp(idn->name+2, name)==0) {
|
||||
if(idn->lib==id->lib) {
|
||||
if(user && idn->us==0) idn->us++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
idn= idn->next;
|
||||
}
|
||||
return idn;
|
||||
}
|
||||
}
|
||||
return idn;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* called from kernel/blender.c */
|
||||
|
||||
@@ -253,6 +253,11 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
|
||||
|
||||
#define B_RECALCPATH 1401
|
||||
#define B_TRACKBUTS 1402
|
||||
#define B_DUPLI_FRAME 1403
|
||||
#define B_DUPLI_VERTS 1404
|
||||
#define B_DUPLI_FACES 1405
|
||||
#define B_DUPLI_GROUP 1406
|
||||
|
||||
|
||||
#define B_PRINTSPEED 1413
|
||||
#define B_PRINTLEN 1414
|
||||
|
||||
@@ -266,16 +266,18 @@ extern Object workob;
|
||||
#define PARSLOW 16
|
||||
|
||||
/* (short) transflag */
|
||||
#define OB_OFFS_LOCAL 1
|
||||
#define OB_QUAT 2
|
||||
#define OB_NEG_SCALE 4
|
||||
#define OB_DUPLI (8+16+256)
|
||||
#define OB_DUPLIFRAMES 8
|
||||
#define OB_DUPLIVERTS 16
|
||||
#define OB_DUPLIROT 32
|
||||
#define OB_DUPLINOSPEED 64
|
||||
#define OB_POWERTRACK 128
|
||||
#define OB_DUPLIGROUP 256
|
||||
#define OB_OFFS_LOCAL 1
|
||||
#define OB_QUAT 2
|
||||
#define OB_NEG_SCALE 4
|
||||
#define OB_DUPLI (8+16+256+512)
|
||||
#define OB_DUPLIFRAMES 8
|
||||
#define OB_DUPLIVERTS 16
|
||||
#define OB_DUPLIROT 32
|
||||
#define OB_DUPLINOSPEED 64
|
||||
#define OB_POWERTRACK 128
|
||||
#define OB_DUPLIGROUP 256
|
||||
#define OB_DUPLIFACES 512
|
||||
#define OB_DUPLIFACES_SCALE 1024
|
||||
|
||||
/* (short) ipoflag */
|
||||
#define OB_DRAWKEY 1
|
||||
|
||||
@@ -1530,10 +1530,11 @@ void do_object_panels(unsigned short event)
|
||||
Effect *eff;
|
||||
|
||||
ob= OBACT;
|
||||
|
||||
if(ob==NULL)
|
||||
return;
|
||||
|
||||
switch(event) {
|
||||
case B_TRACKBUTS:
|
||||
ob= OBACT;
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
@@ -1541,9 +1542,29 @@ void do_object_panels(unsigned short event)
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
case B_DUPLI_FRAME:
|
||||
ob->transflag &= ~(OB_DUPLIVERTS|OB_DUPLIFACES|OB_DUPLIGROUP);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
break;
|
||||
case B_DUPLI_VERTS:
|
||||
ob->transflag &= ~(OB_DUPLIFRAMES|OB_DUPLIFACES|OB_DUPLIGROUP);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
break;
|
||||
case B_DUPLI_FACES:
|
||||
ob->transflag &= ~(OB_DUPLIVERTS|OB_DUPLIFRAMES|OB_DUPLIGROUP);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
break;
|
||||
case B_DUPLI_GROUP:
|
||||
ob->transflag &= ~(OB_DUPLIVERTS|OB_DUPLIFRAMES|OB_DUPLIFACES);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
break;
|
||||
|
||||
case B_PRINTSPEED:
|
||||
ob= OBACT;
|
||||
if(ob) {
|
||||
{
|
||||
float vec[3];
|
||||
CFRA++;
|
||||
do_ob_ipo(ob);
|
||||
@@ -1558,8 +1579,7 @@ void do_object_panels(unsigned short event)
|
||||
}
|
||||
break;
|
||||
case B_PRINTLEN:
|
||||
ob= OBACT;
|
||||
if(ob && ob->type==OB_CURVE) {
|
||||
if(ob->type==OB_CURVE) {
|
||||
Curve *cu=ob->data;
|
||||
|
||||
if(cu->path) prlen= cu->path->totdist; else prlen= -1.0;
|
||||
@@ -1571,24 +1591,20 @@ void do_object_panels(unsigned short event)
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWIPO, 0);
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
||||
break;
|
||||
case B_CURVECHECK:
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
|
||||
case B_SOFTBODY_CHANGE:
|
||||
ob= OBACT;
|
||||
if(ob) {
|
||||
ob->softflag |= OB_SB_REDO;
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
}
|
||||
ob->softflag |= OB_SB_REDO;
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
case B_SOFTBODY_DEL_VG:
|
||||
ob= OBACT;
|
||||
if(ob && ob->soft) {
|
||||
if(ob->soft) {
|
||||
ob->soft->vertgroup= 0;
|
||||
ob->softflag |= OB_SB_REDO;
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
@@ -1596,23 +1612,19 @@ void do_object_panels(unsigned short event)
|
||||
}
|
||||
break;
|
||||
case B_SOFTBODY_BAKE:
|
||||
ob= OBACT;
|
||||
if(ob && ob->soft) softbody_bake(ob);
|
||||
if(ob->soft) softbody_bake(ob);
|
||||
break;
|
||||
case B_SOFTBODY_BAKE_FREE:
|
||||
ob= OBACT;
|
||||
if(ob && ob->soft) sbObjectToSoftbody(ob);
|
||||
if(ob->soft) sbObjectToSoftbody(ob);
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
case B_FLUIDSIM_BAKE:
|
||||
ob= OBACT;
|
||||
/* write config files (currently no simulation) */
|
||||
fluidsimBake(ob);
|
||||
break;
|
||||
case B_FLUIDSIM_MAKEPART:
|
||||
ob= OBACT;
|
||||
if(1) {
|
||||
{
|
||||
PartEff *paf= NULL;
|
||||
/* prepare fluidsim particle display */
|
||||
// simplified delete effect, create new - recalc some particles...
|
||||
@@ -1634,9 +1646,9 @@ void do_object_panels(unsigned short event)
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
break;
|
||||
case B_FLUIDSIM_SELDIR: {
|
||||
case B_FLUIDSIM_SELDIR:
|
||||
{
|
||||
ScrArea *sa = closest_bigger_area();
|
||||
ob= OBACT;
|
||||
/* choose dir for surface files */
|
||||
areawinset(sa->win);
|
||||
activate_fileselect(FILE_SPECIAL, "Select Directory", ob->fluidsimSettings->surfdataPath, fluidsimFilesel);
|
||||
@@ -1649,26 +1661,23 @@ void do_object_panels(unsigned short event)
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
||||
break;
|
||||
case B_GROUP_RELINK:
|
||||
group_relink_nla_objects(OBACT);
|
||||
group_relink_nla_objects(ob);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
|
||||
ob= OBACT;
|
||||
if(ob) {
|
||||
int a=B_SELEFFECT;
|
||||
int a=B_SELEFFECT;
|
||||
|
||||
eff= ob->effect.first;
|
||||
while(eff) {
|
||||
if(event==a) eff->flag |= SELECT;
|
||||
else eff->flag &= ~SELECT;
|
||||
|
||||
eff= ob->effect.first;
|
||||
while(eff) {
|
||||
if(event==a) eff->flag |= SELECT;
|
||||
else eff->flag &= ~SELECT;
|
||||
|
||||
a++;
|
||||
eff= eff->next;
|
||||
}
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
a++;
|
||||
eff= eff->next;
|
||||
}
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1839,13 +1848,18 @@ static void object_panel_anim(Object *ob)
|
||||
uiDefButBitS(block, TOG, PARSLOW, 0, "SlowPar", 260,155,56,19, &ob->partype, 0, 0, 0, 0, "Create a delay in the parent relationship");
|
||||
uiBlockBeginAlign(block);
|
||||
|
||||
uiDefButBitS(block, TOG, OB_DUPLIFRAMES, REDRAWVIEW3D, "DupliFrames", 24,130,89,20, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
|
||||
uiDefButBitS(block, TOG, OB_DUPLIVERTS, REDRAWVIEW3D, "DupliVerts", 114,130,82,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
|
||||
uiDefButBitS(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot", 200,130,31,20, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to vertnormal");
|
||||
uiDefButBitS(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed", 234,130,82,20, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame");
|
||||
|
||||
uiDefButBitS(block, TOG, OB_DUPLIGROUP, REDRAWVIEW3D, "DupliGroup", 24,110,150,20, &ob->transflag, 0, 0, 0, 0, "Enable group instancing");
|
||||
uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_GROUP_RELINK, "GR:", 174,110,142,20, &ob->dup_group, "Instance an existing group");
|
||||
uiDefButBitS(block, TOG, OB_DUPLIFRAMES, B_DUPLI_FRAME, "DupliFrames", 24,130,95,20, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
|
||||
uiDefButBitS(block, TOG, OB_DUPLIVERTS, B_DUPLI_VERTS, "DupliVerts", 119,130,95,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
|
||||
uiDefButBitS(block, TOG, OB_DUPLIFACES, B_DUPLI_FACES, "DupliFaces", 214,130,102,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all faces");
|
||||
uiDefButBitS(block, TOG, OB_DUPLIGROUP, B_DUPLI_GROUP, "DupliGroup", 24,110,150,20, &ob->transflag, 0, 0, 0, 0, "Enable group instancing");
|
||||
if(ob->transflag & OB_DUPLIFRAMES)
|
||||
uiDefButBitS(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed", 174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame");
|
||||
else if(ob->transflag & OB_DUPLIVERTS)
|
||||
uiDefButBitS(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot", 174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to vertex normal");
|
||||
else if(ob->transflag & OB_DUPLIFACES)
|
||||
uiDefButBitS(block, TOG, OB_DUPLIFACES_SCALE, REDRAWVIEW3D, "Scale", 174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Scale dupli based on face size");
|
||||
else
|
||||
uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_GROUP_RELINK, "GR:", 174,110,142,20, &ob->dup_group, "Instance an existing group");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
/* DupSta and DupEnd are both shorts, so the maxframe is greater then their range
|
||||
|
||||
Reference in New Issue
Block a user