diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-07-13 04:40:20 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-07-13 04:40:20 +0400 |
commit | 26ef6da24b3324fb6f8ab6cfe12f101f0d7dedb4 (patch) | |
tree | 375aa10e98780325086c215454f71cdeaef2de4b /source/blender | |
parent | 6fb0181b50461b529bb960950870de941711041e (diff) |
2.5
* Objects now support up to 32767 material slots. It's easy to
increase this further, but I prefer not to increase the memory
usage of mesh faces, it seems unlikely that someone would
create 32767 distinct materials?
* Forward compatibility: the only thing you can potentially lose
reading a 2.5 file in 2.4 is object linking (instead of default
data), though usually that will go fine too. Reading files with
> 32 material slots in 2.4 can start giving issues.
* The ob->colbits variable is deprecated by the array ob->matbits
but I didn't remove the ob->colbits updates in very few places
it is set.
* I hope I changed all the relevant things, various places just
hardcoded the number 16 instead of using the MAXMAT define.
* Join Objects operator back. This is using the version from the
animsys2 branch coded by Joshua, which means it now supports
joining of shape keys.
* Fix for crash reading file saved during render.
Diffstat (limited to 'source/blender')
30 files changed, 683 insertions, 439 deletions
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index 4e7e76dfae3..c7a8b150d3a 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -1415,11 +1415,6 @@ static void displist_to_mesh(Scene *scene, DispList *dlfirst) return; } - if(totcol>16) { - //XXX error("Found more than 16 different colors"); - totcol= 16; - } - vec[0]= (min[0]+max[0])/2; vec[1]= (min[1]+max[1])/2; vec[2]= (min[2]+max[2])/2; @@ -1433,6 +1428,7 @@ static void displist_to_mesh(Scene *scene, DispList *dlfirst) /* colors */ if(totcol) { ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat"); + ob->matbits= MEM_callocN(sizeof(char)*totcol, "ob->matbits"); me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat"); me->totcol= totcol; ob->totcol= (unsigned char) me->totcol; @@ -1482,7 +1478,7 @@ static void displist_to_mesh(Scene *scene, DispList *dlfirst) dl= dlfirst; while(dl) { - colnr= (dl->col>15 ? 15: dl->col); + colnr= dl->col; if(colnr) colnr--; if(dl->type==DL_SURF) { @@ -2804,8 +2800,11 @@ static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer) if (!me) return; - if(ob) ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat"); - if(ob) ob->actcol= 1; + if(ob) { + ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat"); + ob->matbits= MEM_callocN(sizeof(char)*1, "ob->matbits"); + ob->actcol= 1; + } me->totcol= 1; me->mat= MEM_callocN(sizeof(void *)*1, "me->mat"); @@ -4053,7 +4052,6 @@ static void dxf_read(Scene *scene, char *filename) ob->type= OB_MESH; ob->dt= OB_SHADED; - if(U.flag & USER_MAT_ON_OB) ob->colbits= -1; ob->trackflag= OB_POSY; ob->upflag= OB_POSZ; @@ -4072,9 +4070,10 @@ static void dxf_read(Scene *scene, char *filename) VECCOPY(ob->rot, obrot); ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat"); + ob->matbits= MEM_callocN(sizeof(char)*1, "ob->matbits"); ob->totcol= (unsigned char) ((Mesh*)ob->data)->totcol; ob->actcol= 1; - + /* note: materials are either linked to mesh or object, if both then you have to increase user counts. below line is not needed. I leave it commented out here as warning (ton) */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 57b88bb0b3f..d1fdac65dbb 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -43,6 +43,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "DNA_userdef_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -445,7 +446,7 @@ Material *give_current_material(Object *ob, int act) if(act>ob->totcol) act= ob->totcol; else if(act<=0) act= 1; - if( BTST(ob->colbits, act-1) ) { /* in object */ + if(ob->matbits[act-1]) { /* in object */ ma= ob->mat[act-1]; } else { /* in data */ @@ -473,7 +474,7 @@ ID *material_from(Object *ob, int act) if(ob->totcol==0) return ob->data; if(act==0) act= 1; - if( BTST(ob->colbits, act-1) ) return (ID *)ob; + if(ob->matbits[act-1]) return (ID *)ob; else return ob->data; } @@ -498,6 +499,7 @@ void test_object_materials(ID *id) Curve *cu; MetaBall *mb; Material **newmatar; + char *newmatbits; int totcol=0; if(id==0) return; @@ -524,16 +526,22 @@ void test_object_materials(ID *id) if(totcol==0) { if(ob->totcol) { MEM_freeN(ob->mat); - ob->mat= 0; + MEM_freeN(ob->matbits); + ob->mat= NULL; + ob->matbits= NULL; } } else if(ob->totcol<totcol) { newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar"); + newmatbits= MEM_callocN(sizeof(char)*totcol, "newmatbits"); if(ob->totcol) { memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol); + memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol); MEM_freeN(ob->mat); + MEM_freeN(ob->matbits); } ob->mat= newmatar; + ob->matbits= newmatbits; } ob->totcol= totcol; if(ob->totcol && ob->actcol==0) ob->actcol= 1; @@ -547,6 +555,7 @@ void test_object_materials(ID *id) void assign_material(Object *ob, Material *ma, int act) { Material *mao, **matar, ***matarar; + char *matbits; short *totcolp; if(act>MAXMAT) return; @@ -559,29 +568,41 @@ void assign_material(Object *ob, Material *ma, int act) if(totcolp==0 || matarar==0) return; - if( act > *totcolp) { + if(act > *totcolp) { matar= MEM_callocN(sizeof(void *)*act, "matarray1"); - if( *totcolp) { - memcpy(matar, *matarar, sizeof(void *)*( *totcolp )); + + if(*totcolp) { + memcpy(matar, *matarar, sizeof(void *)*(*totcolp)); MEM_freeN(*matarar); } + *matarar= matar; *totcolp= act; } if(act > ob->totcol) { matar= MEM_callocN(sizeof(void *)*act, "matarray2"); + matbits= MEM_callocN(sizeof(char)*act, "matbits1"); if( ob->totcol) { memcpy(matar, ob->mat, sizeof(void *)*( ob->totcol )); + memcpy(matbits, ob->matbits, sizeof(char)*(*totcolp)); MEM_freeN(ob->mat); + MEM_freeN(ob->matbits); } ob->mat= matar; + ob->matbits= matbits; ob->totcol= act; + + /* copy object/mesh linking, or assign based on userpref */ + if(ob->actcol) + ob->matbits[act-1]= ob->matbits[ob->actcol-1]; + else + ob->matbits[act-1]= (U.flag & USER_MAT_ON_OB)? 1: 0; } /* do it */ - if( BTST(ob->colbits, act-1) ) { /* in object */ + if(ob->matbits[act-1]) { /* in object */ mao= ob->mat[act-1]; if(mao) mao->id.us--; ob->mat[act-1]= ma; @@ -591,6 +612,7 @@ void assign_material(Object *ob, Material *ma, int act) if(mao) mao->id.us--; (*matarar)[act-1]= ma; } + id_us_plus((ID *)ma); test_object_materials(ob->data); } @@ -630,12 +652,6 @@ void object_add_material_slot(Object *ob) ma->id.us= 0; /* eeh... */ - if(ob->actcol) { - if( BTST(ob->colbits, ob->actcol-1) ) { - ob->colbits= BSET(ob->colbits, ob->totcol); - } - } - assign_material(ob, ma, ob->totcol+1); ob->actcol= ob->totcol; } @@ -880,9 +896,8 @@ void object_remove_material_slot(Object *ob) if(mao) mao->id.us--; } - for(a=ob->actcol; a<ob->totcol; a++) { + for(a=ob->actcol; a<ob->totcol; a++) (*matarar)[a-1]= (*matarar)[a]; - } (*totcolp)--; if(*totcolp==0) { @@ -900,13 +915,18 @@ void object_remove_material_slot(Object *ob) mao= obt->mat[actcol-1]; if(mao) mao->id.us--; - for(a=actcol; a<obt->totcol; a++) obt->mat[a-1]= obt->mat[a]; + for(a=actcol; a<obt->totcol; a++) { + obt->mat[a-1]= obt->mat[a]; + obt->matbits[a-1]= obt->matbits[a]; + } obt->totcol--; if(obt->actcol > obt->totcol) obt->actcol= obt->totcol; if(obt->totcol==0) { MEM_freeN(obt->mat); + MEM_freeN(obt->matbits); obt->mat= 0; + obt->matbits= NULL; } } obt= obt->id.next; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7d6a83d7900..02c0d46a73f 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -243,7 +243,9 @@ void free_object(Object *ob) if(ob->mat[a]) ob->mat[a]->id.us--; } if(ob->mat) MEM_freeN(ob->mat); + if(ob->matbits) MEM_freeN(ob->matbits); ob->mat= 0; + ob->matbits= 0; if(ob->bb) MEM_freeN(ob->bb); ob->bb= 0; if(ob->path) free_path(ob->path); @@ -942,7 +944,6 @@ Object *add_only_object(int type, char *name) Mat4One(ob->parentinv); Mat4One(ob->obmat); ob->dt= OB_SHADED; - if(U.flag & USER_MAT_ON_OB) ob->colbits= -1; ob->empty_drawtype= OB_ARROWS; ob->empty_drawsize= 1.0; @@ -1170,6 +1171,7 @@ Object *copy_object(Object *ob) if(ob->totcol) { obn->mat= MEM_dupallocN(ob->mat); + obn->matbits= MEM_dupallocN(ob->matbits); } if(ob->bb) obn->bb= MEM_dupallocN(ob->bb); @@ -1397,7 +1399,9 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) /* copy material and index information */ ob->actcol= ob->totcol= 0; if(ob->mat) MEM_freeN(ob->mat); + if(ob->matbits) MEM_freeN(ob->matbits); ob->mat = NULL; + ob->matbits= NULL; if ((target->totcol) && (target->mat) && ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { //XXX OB_SUPPORT_MATERIAL int i; ob->colbits = target->colbits; @@ -1406,6 +1410,7 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) ob->totcol= target->totcol; ob->mat = MEM_dupallocN(target->mat); + ob->matbits = MEM_dupallocN(target->matbits); for(i=0; i<target->totcol; i++) { /* dont need to run test_object_materials since we know this object is new and not used elsewhere */ id_us_plus((ID *)ob->mat[i]); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 66f7fe8a44b..bcdea06936f 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -784,7 +784,7 @@ Tex *give_current_texture(Object *ob, int act) if(act>ob->totcol) act= ob->totcol; else if(act==0) act= 1; - if( BTST(ob->colbits, act-1) ) { /* in object */ + if(ob->matbits[act-1]) { /* in object */ ma= ob->mat[act-1]; } else { /* in data */ diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h index 758e3d136aa..56a20d8462a 100644 --- a/source/blender/blenlib/BLI_editVert.h +++ b/source/blender/blenlib/BLI_editVert.h @@ -125,10 +125,11 @@ typedef struct EditFace float fp; } tmp; float n[3], cent[3]; - unsigned char mat_nr, flag; + unsigned char flag; unsigned char f, f1, h; unsigned char fast; /* only 0 or 1, for editmesh_fastmalloc */ unsigned char fgonf; /* flag for fgon options */ + short mat_nr; void *data; /* custom face data */ } EditFace; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c2b19a804ee..21e173bd87d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3732,6 +3732,7 @@ static void direct_link_object(FileData *fd, Object *ob) ob->mat= newdataadr(fd, ob->mat); test_pointer_array(fd, (void **)&ob->mat); + ob->matbits= newdataadr(fd, ob->matbits); /* do it here, below old data gets converted */ direct_link_modifiers(fd, &ob->modifiers); @@ -4221,6 +4222,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) wm->paintcursors.first= wm->paintcursors.last= NULL; wm->queue.first= wm->queue.last= NULL; wm->reports.first= wm->reports.last= NULL; + wm->jobs.first= wm->jobs.last= NULL; wm->windrawable= NULL; wm->initialized= 0; @@ -9242,6 +9244,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ob->data = olddata; } + + if(ob->totcol && ob->matbits == NULL) { + int a; + + ob->matbits= MEM_callocN(sizeof(char)*ob->totcol, "ob->matbits"); + for(a=0; a<ob->totcol; a++) + ob->matbits[a]= ob->colbits & (1<<a); + } } for(ma = main->mat.first; ma; ma = ma->id.next) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 65a4a355717..ebec409ddf4 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1131,6 +1131,7 @@ static void write_objects(WriteData *wd, ListBase *idbase, int write_undo) /* direct data */ writedata(wd, DATA, sizeof(void *)*ob->totcol, ob->mat); + writedata(wd, DATA, sizeof(char)*ob->totcol, ob->matbits); /* write_effects(wd, &ob->effect); */ /* not used anymore */ write_properties(wd, &ob->prop); write_sensors(wd, &ob->sensors); diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 4312838cba5..d00f4c770d1 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -669,24 +669,21 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann } } -int join_armature(Scene *scene, View3D *v3d) +int join_armature_exec(bContext *C, wmOperator *op) { - Object *ob= scene->basact->object; // XXX context - bArmature *arm= ob->data; - Base *base, *nextbase; + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); + bArmature *arm= (ob)? ob->data: NULL; bPose *pose, *opose; bPoseChannel *pchan, *pchann; EditBone *curbone; float mat[4][4], oimat[4][4]; /* Ensure we're not in editmode and that the active object is an armature*/ - if (ob->type!=OB_ARMATURE) return 0; - if (arm->edbo) return 0; - - if (object_data_is_libdata(ob)) { - error_libdata(); - return 0; - } + if (!ob || ob->type!=OB_ARMATURE) + return OPERATOR_CANCELLED; + if (!arm || arm->edbo) + return OPERATOR_CANCELLED; /* Get editbones of active armature to add editbones to */ ED_armature_to_edit(ob); @@ -694,89 +691,89 @@ int join_armature(Scene *scene, View3D *v3d) /* get pose of active object and move it out of posemode */ pose= ob->pose; ob->flag &= ~OB_POSEMODE; - - for (base=FIRSTBASE; base; base=nextbase) { - nextbase = base->next; - if (TESTBASE(v3d, base)){ - if ((base->object->type==OB_ARMATURE) && (base->object!=ob)) { - bArmature *curarm= base->object->data; - - /* Make a list of editbones in current armature */ - ED_armature_to_edit(base->object); - - /* Get Pose of current armature */ - opose= base->object->pose; - base->object->flag &= ~OB_POSEMODE; - BASACT->flag &= ~OB_POSEMODE; + + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + if ((base->object->type==OB_ARMATURE) && (base->object!=ob)) { + bArmature *curarm= base->object->data; + + /* Make a list of editbones in current armature */ + ED_armature_to_edit(base->object); + + /* Get Pose of current armature */ + opose= base->object->pose; + base->object->flag &= ~OB_POSEMODE; + BASACT->flag &= ~OB_POSEMODE; + + /* Find the difference matrix */ + Mat4Invert(oimat, ob->obmat); + Mat4MulMat4(mat, base->object->obmat, oimat); + + /* Copy bones and posechannels from the object to the edit armature */ + for (pchan=opose->chanbase.first; pchan; pchan=pchann) { + pchann= pchan->next; + curbone= editbone_name_exists(curarm->edbo, pchan->name); - /* Find the difference matrix */ - Mat4Invert(oimat, ob->obmat); - Mat4MulMat4(mat, base->object->obmat, oimat); + /* Get new name */ + unique_editbone_name(arm->edbo, curbone->name, NULL); - /* Copy bones and posechannels from the object to the edit armature */ - for (pchan=opose->chanbase.first; pchan; pchan=pchann) { - pchann= pchan->next; - curbone= editbone_name_exists(curarm->edbo, pchan->name); + /* Transform the bone */ + { + float premat[4][4]; + float postmat[4][4]; + float difmat[4][4]; + float imat[4][4]; + float temp[3][3]; + float delta[3]; - /* Get new name */ - unique_editbone_name(arm->edbo, curbone->name, NULL); + /* Get the premat */ + VecSubf(delta, curbone->tail, curbone->head); + vec_roll_to_mat3(delta, curbone->roll, temp); - /* Transform the bone */ - { - float premat[4][4]; - float postmat[4][4]; - float difmat[4][4]; - float imat[4][4]; - float temp[3][3]; - float delta[3]; - - /* Get the premat */ - VecSubf(delta, curbone->tail, curbone->head); - vec_roll_to_mat3(delta, curbone->roll, temp); - - Mat4One(premat); /* Mat4MulMat34 only sets 3x3 part */ - Mat4MulMat34(premat, temp, mat); - - Mat4MulVecfl(mat, curbone->head); - Mat4MulVecfl(mat, curbone->tail); - - /* Get the postmat */ - VecSubf(delta, curbone->tail, curbone->head); - vec_roll_to_mat3(delta, curbone->roll, temp); - Mat4CpyMat3(postmat, temp); - - /* Find the roll */ - Mat4Invert(imat, premat); - Mat4MulMat4(difmat, postmat, imat); - - curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]); - } + Mat4One(premat); /* Mat4MulMat34 only sets 3x3 part */ + Mat4MulMat34(premat, temp, mat); - /* Fix Constraints and Other Links to this Bone and Armature */ - joined_armature_fix_links(ob, base->object, pchan, curbone); + Mat4MulVecfl(mat, curbone->head); + Mat4MulVecfl(mat, curbone->tail); - /* Rename pchan */ - BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name)); + /* Get the postmat */ + VecSubf(delta, curbone->tail, curbone->head); + vec_roll_to_mat3(delta, curbone->roll, temp); + Mat4CpyMat3(postmat, temp); - /* Jump Ship! */ - BLI_remlink(curarm->edbo, curbone); - BLI_addtail(arm->edbo, curbone); + /* Find the roll */ + Mat4Invert(imat, premat); + Mat4MulMat4(difmat, postmat, imat); - BLI_remlink(&opose->chanbase, pchan); - BLI_addtail(&pose->chanbase, pchan); + curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]); } - ED_base_object_free_and_unlink(scene, base); + /* Fix Constraints and Other Links to this Bone and Armature */ + joined_armature_fix_links(ob, base->object, pchan, curbone); + + /* Rename pchan */ + BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name)); + + /* Jump Ship! */ + BLI_remlink(curarm->edbo, curbone); + BLI_addtail(arm->edbo, curbone); + + BLI_remlink(&opose->chanbase, pchan); + BLI_addtail(&pose->chanbase, pchan); } + + ED_base_object_free_and_unlink(scene, base); } } + CTX_DATA_END; DAG_scene_sort(scene); // because we removed object(s) ED_armature_from_edit(scene, ob); ED_armature_edit_free(ob); + + WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); - return 1; + return OPERATOR_FINISHED; } /* Helper function for armature separating - link fixing */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index c437f35c484..51a9cf5c75a 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -4594,12 +4594,10 @@ void CURVE_OT_smooth_set(wmOperatorType *ot) /************** join operator, to be used externally? ****************/ -int join_curve(bContext *C, wmOperator *op, int type) +int join_curve_exec(bContext *C, wmOperator *op) { - View3D *v3d= CTX_wm_view3d(C); Scene *scene= CTX_data_scene(C); - Object *ob= CTX_data_edit_object(C); - Base *base, *nextb; + Object *ob= CTX_data_active_object(C); Curve *cu; Nurb *nu, *newnu; BezTriple *bezt; @@ -4608,64 +4606,51 @@ int join_curve(bContext *C, wmOperator *op, int type) float imat[4][4], cmat[4][4]; int a; - // XXX not integrated yet, to be called by object/ module? */ - - if(object_data_is_libdata(ob)) { - BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); - return OPERATOR_CANCELLED; - } - - if(ob->type!=type) - return 0; - tempbase.first= tempbase.last= 0; /* trasnform all selected curves inverse in obact */ Mat4Invert(imat, ob->obmat); - for(base= FIRSTBASE; base; base=nextb) { - nextb= base->next; - - if(TESTBASE(v3d, base)) { - if(base->object->type==type) { - if(base->object != ob) { - - cu= base->object->data; - - if(cu->nurb.first) { - /* watch it: switch order here really goes wrong */ - Mat4MulMat4(cmat, base->object->obmat, imat); + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + if(base->object->type==ob->type) { + if(base->object != ob) { + + cu= base->object->data; + + if(cu->nurb.first) { + /* watch it: switch order here really goes wrong */ + Mat4MulMat4(cmat, base->object->obmat, imat); + + nu= cu->nurb.first; + while(nu) { + newnu= duplicateNurb(nu); + BLI_addtail(&tempbase, newnu); - nu= cu->nurb.first; - while(nu) { - newnu= duplicateNurb(nu); - BLI_addtail(&tempbase, newnu); - - if( (bezt= newnu->bezt) ) { - a= newnu->pntsu; - while(a--) { - Mat4MulVecfl(cmat, bezt->vec[0]); - Mat4MulVecfl(cmat, bezt->vec[1]); - Mat4MulVecfl(cmat, bezt->vec[2]); - bezt++; - } + if( (bezt= newnu->bezt) ) { + a= newnu->pntsu; + while(a--) { + Mat4MulVecfl(cmat, bezt->vec[0]); + Mat4MulVecfl(cmat, bezt->vec[1]); + Mat4MulVecfl(cmat, bezt->vec[2]); + bezt++; } - if( (bp= newnu->bp) ) { - a= newnu->pntsu*nu->pntsv; - while(a--) { - Mat4MulVecfl(cmat, bp->vec); - bp++; - } + } + if( (bp= newnu->bp) ) { + a= newnu->pntsu*nu->pntsv; + while(a--) { + Mat4MulVecfl(cmat, bp->vec); + bp++; } - nu= nu->next; } + nu= nu->next; } - - ED_base_object_free_and_unlink(scene, base); } + + ED_base_object_free_and_unlink(scene, base); } } } + CTX_DATA_END; cu= ob->data; addlisttolist(&cu->nurb, &tempbase); @@ -4674,8 +4659,8 @@ int join_curve(bContext *C, wmOperator *op, int type) ED_object_enter_editmode(C, EM_WAITCURSOR); ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); - - // BIF_undo_push("Join"); + + WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 1df9182fc9b..a9823bd9ff1 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -34,6 +34,7 @@ struct Base; struct Bone; struct bArmature; struct bPoseChannel; +struct wmOperator; struct wmWindowManager; struct ListBase; struct View3D; @@ -100,6 +101,7 @@ void ED_armature_edit_remake(struct Object *obedit); int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short extend); void mouse_armature(struct bContext *C, short mval[2], int extend); +int join_armature_exec(struct bContext *C, struct wmOperator *op); struct Bone *get_indexed_bone (struct Object *ob, int index); float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3]); EditBone *ED_armature_bone_get_mirrored(struct ListBase *edbo, EditBone *ebo); // XXX this is needed for populating the context iterators diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index 2cebc6a572a..4149c6a9cca 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -35,6 +35,7 @@ struct Object; struct Scene; struct Text; struct View3D; +struct wmOperator; struct wmWindowManager; /* curve_ops.c */ @@ -55,6 +56,8 @@ struct Nurb *add_nurbs_primitive(struct bContext *C, int type, int newname); int isNurbsel (struct Nurb *nu);; +int join_curve_exec (struct bContext *C, struct wmOperator *op); + /* editfont.h */ void undo_push_font (struct bContext *C, char *name); void make_editText (struct Object *obedit); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index c4fde48c631..0face00f82b 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -36,6 +36,7 @@ struct EditVert; struct EditEdge; struct EditFace; struct bContext; +struct wmOperator; struct wmWindowManager; struct EditSelection; struct ViewContext; @@ -76,6 +77,8 @@ struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, struct EditMesh int mesh_get_x_mirror_vert(struct Object *ob, int index); int *mesh_get_x_mirror_faces(struct Object *ob, struct EditMesh *em); +int join_mesh_exec(struct bContext *C, struct wmOperator *op); + /* mesh_ops.c */ void ED_operatortypes_mesh(void); void ED_keymap_mesh(struct wmWindowManager *wm); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 768040597a4..5719aa63234 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -33,6 +33,7 @@ /* ******************* Registration Function ********************** */ struct wmWindowManager; +struct wmOperatorType; struct ListBase; struct wmEvent; struct bContext; diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c index cdd51a72f4f..6c66ae468fa 100644 --- a/source/blender/editors/mesh/editmesh.c +++ b/source/blender/editors/mesh/editmesh.c @@ -1132,7 +1132,7 @@ void load_editMesh(Scene *scene, Object *ob) else VECCOPY(mvert->co, eve->co); - mvert->mat_nr= 255; /* what was this for, halos? */ + mvert->mat_nr= 32767; /* what was this for, halos? */ /* vertex normal */ VECCOPY(nor, eve->no); @@ -1218,14 +1218,14 @@ void load_editMesh(Scene *scene, Object *ob) /* mat_nr in vertex */ if(me->totcol>1) { mvert= me->mvert+mface->v1; - if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr; + if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr; mvert= me->mvert+mface->v2; - if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr; + if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr; mvert= me->mvert+mface->v3; - if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr; + if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr; if(mface->v4) { mvert= me->mvert+mface->v4; - if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr; + if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr; } } @@ -1669,8 +1669,8 @@ typedef struct EditEdgeC typedef struct EditFaceC { int v1, v2, v3, v4; - unsigned char mat_nr, flag, f, h, fgonf; - short pad1; + unsigned char flag, f, h, fgonf, pad1; + short mat_nr; } EditFaceC; typedef struct EditSelectionC{ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index df3e2a5685c..c10fdbcfd8f 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -38,16 +38,17 @@ #include "MEM_guardedalloc.h" #include "DNA_image_types.h" -#include "DNA_mesh_types.h" +#include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" +#include "DNA_mesh_types.h" #include "DNA_object_types.h" -#include "DNA_material_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" -#include "DNA_world_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_world_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -58,10 +59,12 @@ #include "BKE_blender.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_key.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -86,15 +89,13 @@ #include "ED_object.h" #include "ED_view3d.h" +#include "WM_api.h" +#include "WM_types.h" + /* own include */ #include "mesh_intern.h" - -/* from rendercode.c */ -#define VECMUL(dest, f) dest[0]*= f; dest[1]*= f; dest[2]*= f - /* XXX */ -static void BIF_undo_push() {} static void waitcursor() {} static void error() {} static int pupmenu() {return 0;} @@ -103,145 +104,189 @@ static int pupmenu() {return 0;} /* * ********************** no editmode!!! *********** */ +/*********************** JOIN ***************************/ + /* join selected meshes into the active mesh, context sensitive return 0 if no join is made (error) and 1 of the join is done */ -// XXX NOTE to whoever ports this: -// Check the version of this code in the animsys2 branch, which has been nicely commented, -// but more importantly has proper support for handling meshes with shapekeys (instead of lamely bailing out)! -// -- Aligorith, July 2009 -int join_mesh(Scene *scene, View3D *v3d, wmOperator *op) +int join_mesh_exec(bContext *C, wmOperator *op) { - Base *base, *nextb; - Object *ob; + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); Material **matar, *ma; Mesh *me; - MVert *mvert, *mvertmain; + MVert *mvert, *mv, *mvertmain; MEdge *medge = NULL, *medgemain; MFace *mface = NULL, *mfacemain; - float imat[4][4], cmat[4][4]; - int a, b, totcol, totedge=0, totvert=0, totface=0, ok=0, vertofs, map[MAXMAT]; - int i, j, index, haskey=0, hasmulti=0, edgeofs, faceofs; + Key *key, *nkey=NULL; + KeyBlock *kb, *okb, *kbn; + float imat[4][4], cmat[4][4], *fp1, *fp2, curpos; + int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0; + int vertofs, *matmap; + int i, j, index, haskey=0, edgeofs, faceofs; bDeformGroup *dg, *odg; MDeformVert *dvert; CustomData vdata, edata, fdata; - if(scene->obedit) return 0; + if(scene->obedit) + return OPERATOR_CANCELLED; - ob= OBACT; - if(!ob || ob->type!=OB_MESH) return 0; + /* ob is the object we are adding geometry to */ + if(!ob || ob->type!=OB_MESH) + return OPERATOR_CANCELLED; - if (object_data_is_libdata(ob)) { -// XXX error_libdata(); - return 0; - } - /* count & check */ - base= FIRSTBASE; - while(base) { - if(TESTBASELIB_BGMODE(base)) { /* BGMODE since python can access */ - if(base->object->type==OB_MESH) { - me= base->object->data; - totvert+= me->totvert; - totface+= me->totface; - - if(base->object == ob) ok= 1; - - if(me->key) { - haskey= 1; - break; - } - if(me->mr) { - hasmulti= 1; - break; - } - } + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + if(base->object->type==OB_MESH) { + me= base->object->data; + + totvert+= me->totvert; + totedge+= me->totedge; + totface+= me->totface; + totmat+= base->object->totcol; + + if(base->object == ob) + ok= 1; + + /* check for shapekeys */ + if(me->key) + haskey++; } - base= base->next; } + CTX_DATA_END; - if(haskey) { - BKE_report(op->reports, RPT_ERROR, "Can't join meshes with vertex keys"); - return 0; - } - if(hasmulti) { - BKE_report(op->reports, RPT_ERROR, "Can't join meshes with Multires"); - return 0; - } /* that way the active object is always selected */ - if(ok==0) return 0; + if(ok==0) + return OPERATOR_CANCELLED; - if(totvert==0 || totvert>MESH_MAX_VERTS) return 0; - - /* if needed add edges to other meshes */ - for(base= FIRSTBASE; base; base= base->next) { - if(TESTBASELIB_BGMODE(base)) { - if(base->object->type==OB_MESH) { - me= base->object->data; - totedge += me->totedge; - } - } - } + /* only join meshes if there are verts to join, there aren't too many, and we only had one mesh selected */ + me= (Mesh *)ob->data; + key= me->key; + if(totvert==0 || totvert>MESH_MAX_VERTS || totvert==me->totvert) + return OPERATOR_CANCELLED; /* new material indices and material array */ - matar= MEM_callocN(sizeof(void *)*MAXMAT, "join_mesh"); + matar= MEM_callocN(sizeof(void*)*totmat, "join_mesh matar"); + matmap= MEM_callocN(sizeof(int)*totmat, "join_mesh matmap"); totcol= ob->totcol; /* obact materials in new main array, is nicer start! */ - for(a=1; a<=ob->totcol; a++) { - matar[a-1]= give_current_material(ob, a); - id_us_plus((ID *)matar[a-1]); + for(a=0; a<ob->totcol; a++) { + matar[a]= give_current_material(ob, a+1); + id_us_plus((ID *)matar[a]); /* increase id->us : will be lowered later */ } - base= FIRSTBASE; - while(base) { - if(TESTBASELIB_BGMODE(base)) { - if(ob!=base->object && base->object->type==OB_MESH) { - me= base->object->data; - - // Join this object's vertex groups to the base one's - for (dg=base->object->defbase.first; dg; dg=dg->next){ - /* See if this group exists in the object */ - for (odg=ob->defbase.first; odg; odg=odg->next){ - if (!strcmp(odg->name, dg->name)){ - break; - } - } - if (!odg){ - odg = MEM_callocN (sizeof(bDeformGroup), "join deformGroup"); - memcpy (odg, dg, sizeof(bDeformGroup)); - BLI_addtail(&ob->defbase, odg); + /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders + * with arrays that are large enough to hold shapekey data for all meshes + * - if destination mesh didn't have shapekeys, but we encountered some in the meshes we're + * joining, set up a new keyblock and assign to the mesh + */ + if(key) { + /* make a duplicate copy that will only be used here... (must remember to free it!) */ + nkey= copy_key(key); + + /* for all keys in old block, clear data-arrays */ + for(kb= key->block.first; kb; kb= kb->next) { + if(kb->data) MEM_freeN(kb->data); + kb->data= MEM_callocN(sizeof(float)*3*totvert, "join_shapekey"); + kb->totelem= totvert; + kb->weights= NULL; + } + } + else if(haskey) { + /* add a new key-block and add to the mesh */ + key= me->key= add_key((ID *)me); + key->type = KEY_RELATIVE; + } + + /* first pass over objects - copying materials and vertexgroups across */ + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + /* only act if a mesh, and not the one we're joining to */ + if((ob!=base->object) && (base->object->type==OB_MESH)) { + me= base->object->data; + + /* Join this object's vertex groups to the base one's */ + for(dg=base->object->defbase.first; dg; dg=dg->next) { + /* See if this group exists in the object (if it doesn't, add it to the end) */ + for(odg=ob->defbase.first; odg; odg=odg->next) { + if(!strcmp(odg->name, dg->name)) { + break; } - } - if (ob->defbase.first && ob->actdef==0) - ob->actdef=1; - - if(me->totvert) { + if(!odg) { + odg = MEM_callocN(sizeof(bDeformGroup), "join deformGroup"); + memcpy(odg, dg, sizeof(bDeformGroup)); + BLI_addtail(&ob->defbase, odg); + } + } + if(ob->defbase.first && ob->actdef==0) + ob->actdef=1; + + + if(me->totvert) { + /* Add this object's materials to the base one's if they don't exist already (but only if limits not exceeded yet) */ + if(totcol < MAXMAT-1) { for(a=1; a<=base->object->totcol; a++) { ma= give_current_material(base->object, a); - if(ma) { - for(b=0; b<totcol; b++) { - if(ma == matar[b]) break; - } - if(b==totcol) { - matar[b]= ma; + + for(b=0; b<totcol; b++) { + if(ma == matar[b]) break; + } + if(b==totcol) { + matar[b]= ma; + if(ma) ma->id.us++; - totcol++; + totcol++; + } + if(totcol>=MAXMAT-1) + break; + } + } + + /* if this mesh has shapekeys, check if destination mesh already has matching entries too */ + if(me->key && key) { + for(kb= me->key->block.first; kb; kb= kb->next) { + /* if key doesn't exist in destination mesh, add it */ + if(key_get_named_keyblock(key, kb->name) == NULL) { + /* copy this existing one over to the new shapekey block */ + kbn= MEM_dupallocN(kb); + kbn->prev= kbn->next= NULL; + + /* adjust adrcode and other settings to fit (allocate a new data-array) */ + kbn->data= MEM_callocN(sizeof(float)*3*totvert, "joined_shapekey"); + kbn->totelem= totvert; + kbn->weights= NULL; + + okb= key->block.last; + curpos= (okb) ? okb->pos : -0.1f; + if(key->type == KEY_RELATIVE) + kbn->pos= curpos + 0.1f; + else + kbn->pos= curpos; + + BLI_addtail(&key->block, kbn); + kbn->adrcode= key->totkey; + key->totkey++; + if(key->totkey==1) key->refkey= kbn; + + // XXX 2.5 Animato +#if 0 + /* also, copy corresponding ipo-curve to ipo-block if applicable */ + if(me->key->ipo && key->ipo) { + // FIXME... this is a luxury item! + puts("FIXME: ignoring IPO's when joining shapekeys on Meshes for now..."); } - if(totcol>=MAXMAT-1) break; +#endif } } } } - if(totcol>=MAXMAT-1) break; } - base= base->next; } - - me= ob->data; - + CTX_DATA_END; + + /* setup new data for destination mesh */ memset(&vdata, 0, sizeof(vdata)); memset(&edata, 0, sizeof(edata)); memset(&fdata, 0, sizeof(fdata)); @@ -249,114 +294,177 @@ int join_mesh(Scene *scene, View3D *v3d, wmOperator *op) mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface); - + mvertmain= mvert; medgemain= medge; mfacemain= mface; - - /* inverse transorm all selected meshes in this object */ - Mat4Invert(imat, ob->obmat); - + vertofs= 0; edgeofs= 0; faceofs= 0; - base= FIRSTBASE; - while(base) { - nextb= base->next; - if (TESTBASELIB_BGMODE(base)) { - if(base->object->type==OB_MESH) { + + /* inverse transform for all selected meshes in this object */ + Mat4Invert(imat, ob->obmat); + + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + /* only join if this is a mesh */ + if(base->object->type==OB_MESH) { + me= base->object->data; + + if(me->totvert) { + /* standard data */ + CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); + CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert); - me= base->object->data; + /* vertex groups */ + dvert= CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); - if(me->totvert) { - CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); - CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert); - - dvert= CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); - - /* NEW VERSION */ - if (dvert){ - for (i=0; i<me->totvert; i++){ - for (j=0; j<dvert[i].totweight; j++){ - // Find the old vertex group - odg = BLI_findlink (&base->object->defbase, dvert[i].dw[j].def_nr); - if(odg) { - // Search for a match in the new object - for (dg=ob->defbase.first, index=0; dg; dg=dg->next, index++){ - if (!strcmp(dg->name, odg->name)){ - dvert[i].dw[j].def_nr = index; - break; - } + /* NB: vertex groups here are new version */ + if(dvert) { + for(i=0; i<me->totvert; i++) { + for(j=0; j<dvert[i].totweight; j++) { + /* Find the old vertex group */ + odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr); + if(odg) { + /* Search for a match in the new object, and set new index */ + for(dg=ob->defbase.first, index=0; dg; dg=dg->next, index++) { + if(!strcmp(dg->name, odg->name)) { + dvert[i].dw[j].def_nr = index; + break; } } } } } - - if(base->object != ob) { - /* watch this: switch matmul order really goes wrong */ - Mat4MulMat4(cmat, base->object->obmat, imat); - - a= me->totvert; - while(a--) { - Mat4MulVecfl(cmat, mvert->co); - mvert++; - } - } - else mvert+= me->totvert; } - if(me->totface) { - /* make mapping for materials */ - memset(map, 0, 4*MAXMAT); - for(a=1; a<=base->object->totcol; a++) { - ma= give_current_material(base->object, a); - if(ma) { - for(b=0; b<totcol; b++) { - if(ma == matar[b]) { - map[a-1]= b; - break; + /* if this is the object we're merging into, no need to do anything */ + if(base->object != ob) { + /* watch this: switch matmul order really goes wrong */ + Mat4MulMat4(cmat, base->object->obmat, imat); + + /* transform vertex coordinates into new space */ + for(a=0, mv=mvert; a < me->totvert; a++, mv++) { + Mat4MulVecfl(cmat, mv->co); + } + + /* for each shapekey in destination mesh: + * - if there's a matching one, copy it across (will need to transform vertices into new space...) + * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) + */ + if(key) { + /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ + for(kb= key->block.first; kb; kb= kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + fp1= ((float *)kb->data) + (vertofs*3); + + /* check if this mesh has such a shapekey */ + okb= key_get_named_keyblock(me->key, kb->name); + if(okb) { + /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ + fp2= ((float *)(okb->data)); + for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) { + VECCOPY(fp1, fp2); + Mat4MulVecfl(cmat, fp1); + } + } + else { + /* copy this mesh's vertex coordinates to the destination shapekey */ + mv= mvert; + for(a=0; a < me->totvert; a++, fp1+=3, mv++) { + VECCOPY(fp1, mv->co); } } } } - - CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface); - CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface); - - for(a=0; a<me->totface; a++, mface++) { - mface->v1+= vertofs; - mface->v2+= vertofs; - mface->v3+= vertofs; - if(mface->v4) mface->v4+= vertofs; - - mface->mat_nr= map[(int)mface->mat_nr]; + } + else { + /* for each shapekey in destination mesh: + * - if it was an 'original', copy the appropriate data from nkey + * - otherwise, copy across plain coordinates (no need to transform coordinates) + */ + if(key) { + for(kb= key->block.first; kb; kb= kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + fp1= ((float *)kb->data) + (vertofs*3); + + /* check if this was one of the original shapekeys */ + okb= key_get_named_keyblock(nkey, kb->name); + if(okb) { + /* copy this mesh's shapekey to the destination shapekey */ + fp2= ((float *)(okb->data)); + for(a=0; a < me->totvert; a++, fp1+=3, fp2+=3) { + VECCOPY(fp1, fp2); + } + } + else { + /* copy base-coordinates to the destination shapekey */ + mv= mvert; + for(a=0; a < me->totvert; a++, fp1+=3, mv++) { + VECCOPY(fp1, mv->co); + } + } + } } - - faceofs += me->totface; } - if(me->totedge) { - CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); - CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge); - - for(a=0; a<me->totedge; a++, medge++) { - medge->v1+= vertofs; - medge->v2+= vertofs; + /* advance mvert pointer to end of base mesh's data */ + mvert+= me->totvert; + } + + if(me->totface) { + /* make mapping for materials */ + for(a=1; a<=base->object->totcol; a++) { + ma= give_current_material(base->object, a); + + for(b=0; b<totcol; b++) { + if(ma == matar[b]) { + matmap[a-1]= b; + break; + } } - - edgeofs += me->totedge; } - vertofs += me->totvert; + CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface); + CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface); + + for(a=0; a<me->totface; a++, mface++) { + mface->v1+= vertofs; + mface->v2+= vertofs; + mface->v3+= vertofs; + if(mface->v4) mface->v4+= vertofs; + + mface->mat_nr= matmap[(int)mface->mat_nr]; + } + + faceofs += me->totface; + } + + if(me->totedge) { + CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); + CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge); + + for(a=0; a<me->totedge; a++, medge++) { + medge->v1+= vertofs; + medge->v2+= vertofs; + } - if(base->object!=ob) - ED_base_object_free_and_unlink(scene, base); + edgeofs += me->totedge; } + + /* vertofs is used to help newly added verts be reattached to their edge/face + * (cannot be set earlier, or else reattaching goes wrong) + */ + vertofs += me->totvert; + + /* free base, now that data is merged */ + if(base->object != ob) + ED_base_object_free_and_unlink(scene, base); } - base= nextb; } + CTX_DATA_END; + /* return to mesh we're merging to */ me= ob->data; CustomData_free(&me->vdata, me->totvert); @@ -383,30 +491,53 @@ int join_mesh(Scene *scene, View3D *v3d, wmOperator *op) if(ma) ma->id.us--; } if(ob->mat) MEM_freeN(ob->mat); + if(ob->matbits) MEM_freeN(ob->matbits); if(me->mat) MEM_freeN(me->mat); - ob->mat= me->mat= 0; + ob->mat= me->mat= NULL; + ob->matbits= NULL; if(totcol) { me->mat= matar; ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar"); + ob->matbits= MEM_callocN(sizeof(char)*totcol, "join obmatbits"); } - else MEM_freeN(matar); + else + MEM_freeN(matar); ob->totcol= me->totcol= totcol; ob->colbits= 0; + + MEM_freeN(matmap); /* other mesh users */ test_object_materials((ID *)me); - DAG_scene_sort(scene); // removed objects, need to rebuild dag before editmode call + /* free temp copy of destination shapekeys (if applicable) */ + if(nkey) { + // XXX 2.5 Animato +#if 0 + /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */ + if(nkey->ipo) { + free_ipo(nkey->ipo); + BLI_remlink(&G.main->ipo, nkey->ipo); + MEM_freeN(nkey->ipo); + } +#endif + + free_key(nkey); + BLI_remlink(&G.main->key, nkey); + MEM_freeN(nkey); + } -// XXX enter_editmode(EM_WAITCURSOR); -// exit_editmode(EM_FREEDATA|EM_WAITCURSOR); // freedata, but no undo + DAG_scene_sort(scene); // removed objects, need to rebuild dag before editmode call - BIF_undo_push("Join Mesh"); - return 1; -} + ED_object_enter_editmode(C, EM_WAITCURSOR); + ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); + + WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); + return OPERATOR_FINISHED; +} /* ********************** SORT FACES ******************* */ @@ -520,14 +651,14 @@ void sort_faces(Scene *scene, View3D *v3d) else face_sort_floats[i] = reverse; } else { /* find the faces center */ - VECADD(vec, (me->mvert+mf->v1)->co, (me->mvert+mf->v2)->co); + VecAddf(vec, (me->mvert+mf->v1)->co, (me->mvert+mf->v2)->co); if (mf->v4) { - VECADD(vec, vec, (me->mvert+mf->v3)->co); - VECADD(vec, vec, (me->mvert+mf->v4)->co); - VECMUL(vec, 0.25f); + VecAddf(vec, vec, (me->mvert+mf->v3)->co); + VecAddf(vec, vec, (me->mvert+mf->v4)->co); + VecMulf(vec, 0.25f); } else { - VECADD(vec, vec, (me->mvert+mf->v3)->co); - VECMUL(vec, 1.0f/3.0f); + VecAddf(vec, vec, (me->mvert+mf->v3)->co); + VecMulf(vec, 1.0f/3.0f); } /* done */ if (event == 1) { /* sort on view axis */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 35b6e23eaa5..0746fbaefb6 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1755,7 +1755,6 @@ static short select_grouped_parent(bContext *C) /* Makes parent active and de-se static short select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */ { short changed = 0; - Base *base; Group *group, *ob_groups[GROUP_MENU_MAX]; //char str[10 + (24*GROUP_MENU_MAX)]; //char *p = str; @@ -6326,6 +6325,53 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX); } +/* ************************** JOIN *********************** */ + +static int join_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); + + if(scene->obedit) { + BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode."); + return OPERATOR_CANCELLED; + } + else if(!ob) { + BKE_report(op->reports, RPT_ERROR, "Can't join unless there is an active object."); + return OPERATOR_CANCELLED; + } + else if(object_data_is_libdata(ob)) { + BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata."); + return OPERATOR_CANCELLED; + } + + if(ob->type == OB_MESH) + return join_mesh_exec(C, op); + else if(ELEM(ob->type, OB_CURVE, OB_SURF)) + return join_curve_exec(C, op); + else if(ob->type == OB_ARMATURE) + return join_armature_exec(C, op); + + BKE_report(op->reports, RPT_ERROR, "This object type doesn't support joining."); + + return OPERATOR_CANCELLED; +} + +void OBJECT_OT_join(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Join"; + ot->description = "Join selected objects into active object."; + ot->idname= "OBJECT_OT_join"; + + /* api callbacks */ + ot->exec= join_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ********************** */ void image_aspect(Scene *scene, View3D *v3d) diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 76ce8857c2c..23a4b5773ff 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -64,6 +64,7 @@ void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot); void OBJECT_OT_object_add(struct wmOperatorType *ot); void OBJECT_OT_duplicate(struct wmOperatorType *ot); void OBJECT_OT_delete(struct wmOperatorType *ot); +void OBJECT_OT_join(struct wmOperatorType *ot); void OBJECT_OT_mesh_add(struct wmOperatorType *ot); void OBJECT_OT_curve_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 9a0ce23a970..acfe2416d77 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -86,6 +86,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_center_set); WM_operatortype_append(OBJECT_OT_duplicates_make_real); WM_operatortype_append(OBJECT_OT_duplicate); + WM_operatortype_append(OBJECT_OT_join); WM_operatortype_append(GROUP_OT_group_create); WM_operatortype_append(GROUP_OT_objects_remove); WM_operatortype_append(GROUP_OT_objects_add_active); @@ -170,6 +171,7 @@ void ED_keymap_object(wmWindowManager *wm) WM_keymap_verify_item(keymap, "OBJECT_OT_primitive_add", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "OBJECT_OT_duplicate", DKEY, KM_PRESS, KM_ALT, 0)->ptr, "linked", 1); + WM_keymap_add_item(keymap, "OBJECT_OT_join", JKEY, KM_PRESS, KM_CTRL, 0); // XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith WM_keymap_verify_item(keymap, "ANIM_OT_insert_keyframe_menu", IKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 578da29f102..fd37020c3b4 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -387,7 +387,6 @@ static int view_all_exec(bContext *C, wmOperator *op) ARegion *ar; Scene *scene; Object *obedit; - Image *ima; ImBuf *ibuf; float aspx, aspy, zoomx, zoomy, w, h; int width, height; @@ -398,7 +397,6 @@ static int view_all_exec(bContext *C, wmOperator *op) scene= (Scene*)CTX_data_scene(C); obedit= CTX_data_edit_object(C); - ima= ED_space_image(sima); ibuf= ED_space_image_buffer(sima); ED_space_image_size(sima, &width, &height); ED_space_image_aspect(sima, &aspx, &aspy); diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index e8c32d2a2c7..4776b42b631 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -1700,22 +1700,24 @@ static int tree_element_active_material(Scene *scene, SpaceOops *soops, TreeElem if(tes->idcode==ID_OB) { if(set) { ob->actcol= te->index+1; - ob->colbits |= (1<<te->index); // make ob material active too + ob->matbits[te->index]= 1; // make ob material active too + ob->colbits |= (1<<te->index); } else { if(ob->actcol == te->index+1) - if(ob->colbits & (1<<te->index)) return 1; + if(ob->matbits[te->index]) return 1; } } /* or we search for obdata material */ else { if(set) { ob->actcol= te->index+1; - ob->colbits &= ~(1<<te->index); // make obdata material active too + ob->matbits[te->index]= 0; // make obdata material active too + ob->colbits &= ~(1<<te->index); } else { if(ob->actcol == te->index+1) - if( (ob->colbits & (1<<te->index))==0 ) return 1; + if(ob->matbits[te->index]==0) return 1; } } if(set) { diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f83a0b9686e..93c6c535a31 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -2463,11 +2463,13 @@ static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base if(dt>OB_WIRE) { // no transp in editmode, the fancy draw over goes bad then glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_set_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); } draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt); + GPU_end_object_materials(); + if (obedit!=ob && finalDM) finalDM->release(finalDM); } @@ -2482,17 +2484,19 @@ static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base check_alpha = check_material_alpha(base, me, glsl); if(dt==OB_SOLID || glsl) { - GPU_set_object_materials(v3d, rv3d, scene, ob, glsl, + GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, (check_alpha)? &do_alpha_pass: NULL); } draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag); + + GPU_end_object_materials(); if(me->totvert==0) retval= 1; } } - /* GPU_set_object_materials checked if this is needed */ + /* GPU_begin_object_materials checked if this is needed */ if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag); return retval; @@ -2670,7 +2674,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) glVertexPointer(3, GL_FLOAT, 0, dl->verts); glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index); - GPU_disable_material(); } break; @@ -2688,7 +2691,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index); - GPU_disable_material(); if(index3_nors_incr==0) glEnableClientState(GL_NORMAL_ARRAY); @@ -2702,8 +2704,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index); - GPU_disable_material(); - break; } dl= dl->next; @@ -2797,17 +2797,19 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } else { if(draw_glsl_material(scene, ob, v3d, dt)) { - GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); drawDispListsolid(lb, ob, 1); + GPU_end_object_materials(); } else if(dt == OB_SHADED) { if(ob->disp.first==0) shadeDispList(scene, base); drawDispListshaded(lb, ob); } else { - GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); drawDispListsolid(lb, ob, 0); + GPU_end_object_materials(); } if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) { cpack(0); @@ -2835,18 +2837,19 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if(dl->nors==NULL) addnormalsDispList(ob, lb); if(draw_glsl_material(scene, ob, v3d, dt)) { - GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); drawDispListsolid(lb, ob, 1); + GPU_end_object_materials(); } else if(dt==OB_SHADED) { if(ob->disp.first==NULL) shadeDispList(scene, base); drawDispListshaded(lb, ob); } else { - GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob, 0); + GPU_end_object_materials(); } } else { @@ -2863,8 +2866,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if(solid) { if(draw_glsl_material(scene, ob, v3d, dt)) { - GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); drawDispListsolid(lb, ob, 1); + GPU_end_object_materials(); } else if(dt == OB_SHADED) { dl= lb->first; @@ -2872,10 +2876,10 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas drawDispListshaded(lb, ob); } else { - GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob, 0); + GPU_end_object_materials(); } } else{ @@ -5615,7 +5619,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r if(dm) { glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_set_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); } else { glEnable(GL_COLOR_MATERIAL); @@ -5629,7 +5633,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r if(dm) { dm->drawFacesSolid(dm, GPU_enable_material); - GPU_disable_material(); + GPU_end_object_materials(); } else if(edm) edm->drawMappedFaces(edm, NULL, NULL, 0); diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index ce130951840..802f30506f8 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -63,8 +63,10 @@ void GPU_state_init(void); * GPU_enable_material returns 0 if drawing should be skipped * - after drawing, the material must be disabled again */ -void GPU_set_object_materials(struct View3D *v3d, struct RegionView3D *rv3d, +void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d, struct Scene *scene, struct Object *ob, int glsl, int *do_alpha_pass); +void GPU_end_object_materials(void); + int GPU_enable_material(int nr, void *attribs); void GPU_disable_material(void); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 5edb619f7e5..efb7d688a49 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -776,16 +776,17 @@ void GPU_free_images(void) /* OpenGL Materials */ -/* materials start counting at # one.... */ -#define MAXMATBUF (MAXMAT+1) +#define FIXEDMAT 8 /* OpenGL state caching for materials */ static struct GPUMaterialState { - float matbuf[MAXMATBUF][2][4]; + float (*matbuf)[2][4]; + float matbuf_fixed[FIXEDMAT][2][4]; int totmat; - Material *gmatbuf[MAXMATBUF]; + Material **gmatbuf; + Material *gmatbuf_fixed[FIXEDMAT]; Material *gboundmat; Object *gob; Scene *gscene; @@ -793,7 +794,8 @@ static struct GPUMaterialState { float (*gviewmat)[4]; float (*gviewinv)[4]; - GPUBlendMode blendmode[MAXMATBUF]; + GPUBlendMode *blendmode; + GPUBlendMode blendmode_fixed[FIXEDMAT]; int alphapass; int lastmatnr, lastretval; @@ -814,7 +816,7 @@ Material *gpu_active_node_material(Material *ma) return ma; } -void GPU_set_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, int glsl, int *do_alpha_pass) +void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, int glsl, int *do_alpha_pass) { extern Material defmaterial; /* from material.c */ Material *ma; @@ -830,7 +832,7 @@ void GPU_set_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Obj GMS.gob = ob; GMS.gscene = scene; - GMS.totmat= ob->totcol; + GMS.totmat= ob->totcol+1; /* materials start from 1, default material is 0 */ GMS.glay= v3d->lay; GMS.gviewmat= rv3d->viewmat; GMS.gviewinv= rv3d->viewinv; @@ -838,6 +840,17 @@ void GPU_set_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Obj GMS.alphapass = (v3d && v3d->transp); if(do_alpha_pass) *do_alpha_pass = 0; + + if(GMS.totmat > FIXEDMAT) { + GMS.matbuf= MEM_callocN(sizeof(*GMS.matbuf)*GMS.totmat, "GMS.matbuf"); + GMS.gmatbuf= MEM_callocN(sizeof(*GMS.gmatbuf)*GMS.totmat, "GMS.matbuf"); + GMS.blendmode= MEM_callocN(sizeof(*GMS.blendmode)*GMS.totmat, "GMS.matbuf"); + } + else { + GMS.matbuf= GMS.matbuf_fixed; + GMS.gmatbuf= GMS.gmatbuf_fixed; + GMS.blendmode= GMS.blendmode_fixed; + } /* no materials assigned? */ if(ob->totcol==0) { @@ -870,10 +883,6 @@ void GPU_set_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Obj if(!glsl) ma= gpu_active_node_material(ma); if(ma==NULL) ma= &defmaterial; - /* this shouldn't happen .. */ - if(a>=MAXMATBUF) - continue; - /* create glsl material if requested */ gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; @@ -926,14 +935,14 @@ int GPU_enable_material(int nr, void *attribs) GPUBlendMode blendmode; /* prevent index to use un-initialized array items */ - if(nr>GMS.totmat) - nr= GMS.totmat; + if(nr>=GMS.totmat) + nr= 0; if(gattribs) memset(gattribs, 0, sizeof(*gattribs)); /* keep current material */ - if(nr>=MAXMATBUF || nr==GMS.lastmatnr) + if(nr==GMS.lastmatnr) return GMS.lastretval; /* unbind glsl material */ @@ -1004,6 +1013,21 @@ void GPU_disable_material(void) GPU_set_material_blend_mode(GPU_BLEND_SOLID); } +void GPU_end_object_materials(void) +{ + GPU_disable_material(); + + if(GMS.matbuf && GMS.matbuf != GMS.matbuf_fixed) { + MEM_freeN(GMS.matbuf); + MEM_freeN(GMS.gmatbuf); + MEM_freeN(GMS.blendmode); + + GMS.matbuf= NULL; + GMS.gmatbuf= NULL; + GMS.blendmode= NULL; + } +} + /* Lights */ int GPU_default_lights(void) diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index cd0b73c8f70..561638bfd20 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -142,10 +142,10 @@ typedef struct Material { /* **************** MATERIAL ********************* */ - /* maximum number of materials per material array - * (on object, mesh, lamp, etc.) - */ -#define MAXMAT 16 +/* maximum number of materials per material array. + * (on object, mesh, lamp, etc.). limited by + * short mat_nr in verts, faces. */ +#define MAXMAT 32767 /* material_type */ #define MA_TYPE_SURFACE 0 diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index cec27b85b23..d53a7833d0e 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -37,7 +37,7 @@ struct Image; typedef struct MFace { unsigned int v1, v2, v3, v4; - char pad, mat_nr; + short mat_nr; char edcode, flag; /* we keep edcode, for conversion to edges draw flags in old files */ } MFace; @@ -61,7 +61,8 @@ typedef struct MDeformVert { typedef struct MVert { float co[3]; short no[3]; - char flag, mat_nr, bweight, pad[3]; + short mat_nr; + char flag, bweight, pad[2]; } MVert; /* at the moment alpha is abused for vertex painting @@ -134,7 +135,7 @@ typedef struct MultiresColFace { } MultiresColFace; typedef struct MultiresFace { unsigned int v[4]; - unsigned int mid; + unsigned int mid; char flag, mat_nr, pad[2]; } MultiresFace; typedef struct MultiresEdge { diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index febf2fe59cd..2b0ede846af 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -113,8 +113,12 @@ typedef struct Object { ListBase disp; ListBase defbase; ListBase modifiers; /* list of ModifierData structures */ - - struct Material **mat; + + /* materials */ + struct Material **mat; /* material slots */ + char *matbits; /* 1 if material linked to object */ + int totcol; /* copy of mesh or curve or meta */ + int actcol; /* currently selected material in the UI */ /* rot en drot have to be together! (transform('r' en 's')) */ float loc[3], dloc[3], orig[3]; @@ -129,7 +133,7 @@ typedef struct Object { unsigned int lay; /* copy of Base */ short flag; /* copy of Base */ - short colbits; /* when zero, from obdata */ + short colbits; /* deprecated */ short transflag, protectflag; /* transformation settings and transform locks */ short trackflag, upflag; @@ -164,9 +168,7 @@ typedef struct Object { float m_contactProcessingThreshold; char dt, dtx; - char totcol; /* copy of mesh or curve or meta */ - char actcol; /* currently selected material in the user interface */ - char empty_drawtype, pad1[3]; + char empty_drawtype, pad1[5]; float empty_drawsize; float dupfacesca; /* dupliface scale */ diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 91488aa2a49..5c9da19f9b2 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -701,7 +701,6 @@ static void rna_def_curve_nurb(BlenderRNA *brna) prop= RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "mat_nr"); RNA_def_property_ui_text(prop, "Material Index", ""); - RNA_def_property_range(prop, 0, MAXMAT-1); RNA_def_property_int_funcs(prop, NULL, NULL, "rna_Curve_material_index_range"); prop= RNA_def_property(srna, "character_index", PROP_INT, PROP_UNSIGNED); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 39fa6f36f23..b69a804cf6a 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -879,7 +879,6 @@ static void rna_def_mface(BlenderRNA *brna) prop= RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "mat_nr"); RNA_def_property_ui_text(prop, "Material Index", ""); - RNA_def_property_range(prop, 0, MAXMAT-1); RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshFace_material_index_range"); prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 092d15de96e..33e8c1fbd26 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -331,7 +331,7 @@ static int rna_MaterialSlot_link_get(PointerRNA *ptr) Object *ob= (Object*)ptr->id.data; int index= (Material**)ptr->data - ob->mat; - return (ob->colbits & (1<<index)) != 0; + return ob->matbits[index] != 0; } static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value) @@ -339,10 +339,14 @@ static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value) Object *ob= (Object*)ptr->id.data; int index= (Material**)ptr->data - ob->mat; - if(value) + if(value) { + ob->matbits[index]= 1; ob->colbits |= (1<<index); - else + } + else { + ob->matbits[index]= 0; ob->colbits &= ~(1<<index); + } } static int rna_MaterialSlot_name_length(PointerRNA *ptr) @@ -523,8 +527,8 @@ static void rna_def_material_slot(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem link_items[] = { - {0, "DATA", 0, "Data", ""}, {1, "OBJECT", 0, "Object", ""}, + {0, "DATA", 0, "Data", ""}, {0, NULL, 0, NULL, NULL}}; /* NOTE: there is no MaterialSlot equivalent in DNA, so the internal diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 1d6d98bebdf..65942a14be9 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2582,9 +2582,9 @@ static void init_render_surf(Render *re, ObjectRen *obr) Curve *cu; ListBase displist; DispList *dl; - Material *matar[32]; + Material **matar; float *orco=NULL, *orcobase=NULL, mat[4][4]; - int a, need_orco=0; + int a, totmat, need_orco=0; cu= ob->data; nu= cu->nurb.first; @@ -2594,13 +2594,14 @@ static void init_render_surf(Render *re, ObjectRen *obr) MTC_Mat4Invert(ob->imat, mat); /* material array */ - memset(matar, 0, 4*32); - matar[0]= give_render_material(re, ob, 0); - for(a=0; a<ob->totcol; a++) { + totmat= ob->totcol+1; + matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar"); + + for(a=0; a<totmat; a++) { matar[a]= give_render_material(re, ob, a+1); - if(matar[a] && matar[a]->texco & TEXCO_ORCO) { + + if(matar[a] && matar[a]->texco & TEXCO_ORCO) need_orco= 1; - } } if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1; @@ -2610,17 +2611,15 @@ static void init_render_surf(Render *re, ObjectRen *obr) displist.first= displist.last= 0; makeDispListSurf(re->scene, ob, &displist, 1, 0); - dl= displist.first; /* walk along displaylist and create rendervertices/-faces */ - while(dl) { - /* watch out: u ^= y, v ^= x !! */ - if(dl->type==DL_SURF) { + for(dl=displist.first; dl; dl=dl->next) { + /* watch out: u ^= y, v ^= x !! */ + if(dl->type==DL_SURF) orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); - } - - dl= dl->next; } + freedisplist(&displist); + MEM_freeN(matar); } static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) @@ -2631,11 +2630,11 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) VlakRen *vlr; DispList *dl; ListBase olddl={NULL, NULL}; - Material *matar[32]; + Material **matar; float len, *data, *fp, *orco=NULL, *orcobase= NULL; float n[3], mat[4][4]; int nr, startvert, startvlak, a, b; - int frontside, need_orco=0; + int frontside, need_orco=0, totmat; cu= ob->data; if(ob->type==OB_FONT && cu->str==NULL) return; @@ -2656,13 +2655,14 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) MTC_Mat4Invert(ob->imat, mat); /* material array */ - memset(matar, 0, 4*32); - matar[0]= give_render_material(re, ob, 0); - for(a=0; a<ob->totcol; a++) { + totmat= ob->totcol+1; + matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar"); + + for(a=0; a<totmat; a++) { matar[a]= give_render_material(re, ob, a+1); - if(matar[a]->texco & TEXCO_ORCO) { + + if(matar[a] && matar[a]->texco & TEXCO_ORCO) need_orco= 1; - } } if(need_orco) orcobase=orco= get_object_orco(re, ob); @@ -2840,6 +2840,8 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) freedisplist(&cu->disp); SWAP(ListBase, olddl, cu->disp); } + + MEM_freeN(matar); } /* ------------------------------------------------------------------------- */ |