2.5
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 13 Jul 2009 00:40:20 +0000 (00:40 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 13 Jul 2009 00:40:20 +0000 (00:40 +0000)
* 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.

31 files changed:
release/ui/buttons_material.py
source/blender/blenkernel/intern/exotic.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/BLI_editVert.h
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/armature/editarmature.c
source/blender/editors/curve/editcurve.c
source/blender/editors/include/ED_armature.h
source/blender/editors/include/ED_curve.h
source/blender/editors/include/ED_mesh.h
source/blender/editors/include/ED_transform.h
source/blender/editors/mesh/editmesh.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_ops.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_outliner/outliner.c
source/blender/editors/space_view3d/drawobject.c
source/blender/gpu/GPU_draw.h
source/blender/gpu/intern/gpu_draw.c
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_meshdata_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesrna/intern/rna_curve.c
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_object.c
source/blender/render/intern/source/convertblender.c

index 9298b2d2248fe6173d380fa7cfe3372cc69fe05f..e24049797735dfc16ea7ed1d658078ce48bdfd81 100644 (file)
@@ -47,11 +47,11 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel):
 
                if ob and slot:
                        split.template_ID(slot, "material", new="MATERIAL_OT_new")
-                       #split.itemR(ob, "active_material_index", text="Active")
+                       row = split.row()
+                       row.itemR(slot, "link", expand=True)
                elif mat:
                        split.template_ID(space, "pin_id")
                        split.itemS()
-
        
 class MATERIAL_PT_material(MaterialButtonsPanel):
        __idname__= "MATERIAL_PT_material"
index 4e7e76dfae3226fe15fe0607458c68aedc9fd265..c7a8b150d3a065ca3e69b73edc25a550ff9d28bd 100644 (file)
@@ -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) */
index 57b88bb0b3f66e69548c51b7d3713aa40ef510f1..d1fdac65dbb764372b676189ab92e4a695fed076 100644 (file)
@@ -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;
index 7d6a83d79001614204df859f351eb21d98f3a74f..02c0d46a73f83ff872c513ca491779fd8578b516 100644 (file)
@@ -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]); 
index 66f7fe8a44bab3a475071c46e4d3799037de396c..bcdea06936f0214867019220c57832be5bf754f2 100644 (file)
@@ -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 */
index 758e3d136aa3fdd7d1ced0d15274a6d0d6d6ef48..56a20d8462aa77bd5fe8d4a3e6975d3698b5229c 100644 (file)
@@ -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;
 
index c2b19a804eefd1eef905275547e8327e2462fb52..21e173bd87dcaa13648b448428a2834bb9fccc34 100644 (file)
@@ -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) {
index 65a4a355717424182b373d14adb53b386c4fcbaf..ebec409ddf405da99fe6492f2627b4378fd40beb 100644 (file)
@@ -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);
index 4312838cba5bedc2bcd81ceae6be37c5a3d04ffd..d00f4c770d1dfb4692c96e6f7118e5c244dc2e91 100644 (file)
@@ -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 */
index c437f35c4843c2cd2e6f9fe17576bf0d296a092a..51a9cf5c75adf49d6dabdcdc777cf624980a7e9c 100644 (file)
@@ -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;
 }
index 1df9182fc9bc8fe27c27249fda01a8d66403b6a5..a9823bd9ff16f6e4c2dfe5b09276ec6257567e0b 100644 (file)
@@ -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
index 2cebc6a572a688414e10f9417ff870f37d2e8873..4149c6a9cca0d4bf8e43c2b7402bbe0aefcd9676 100644 (file)
@@ -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);
index c4fde48c631da6e2ca6b78073631216625240511..0face00f82b272e441cdda77e54cffc9aad98054 100644 (file)
@@ -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);
index 768040597a49e760216b760e397f1130acb9a191..5719aa6323461cb7230822ccf4cb9db265f8e54c 100644 (file)
@@ -33,6 +33,7 @@
 /* ******************* Registration Function ********************** */
 
 struct wmWindowManager;
+struct wmOperatorType;
 struct ListBase;
 struct wmEvent;
 struct bContext;
index cdd51a72f4fe099ca26d60a72ede8817656c472a..6c66ae468fa5597d8a9370a4727a100e2f77b067 100644 (file)
@@ -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{
index df3e2a5685cd845c1b1ba443fdc5407d500084f8..c10fdbcfd8fb95a4f00079d3818128a5676f775a 100644 (file)
 #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"
 
 
 #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"
 #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 */
index 35b6e23eaa52efa0e4af4fdef96c75f76bd19d6c..0746fbaefb6cc5b350811bf58dbdf4f63350f29e 100644 (file)
@@ -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)
index 76ce8857c2cf8931034ff8a30c844cef5a446151..23a4b5773ffbce6d0356bd0790f927119a303fe7 100644 (file)
@@ -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);
index 9a0ce23a97094d68b25fdfc494ecd777f8d613d8..acfe2416d7723676aba2f5bcb17982f4a060e56b 100644 (file)
@@ -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);
index 578da29f102db5026af3125b5c295fdc58981400..fd37020c3b4b6c6e7d6e26120f589e3069d1f709 100644 (file)
@@ -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);
index e8c32d2a2c743b8bc2fe1b2aacb45ceac792351b..4776b42b63180778808b8abe32e31ea685545ec1 100644 (file)
@@ -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) {
index f83a0b9686efd67a95d420175a21652b718c2c38..93c6c535a31040e4020f378602e92d16129062b2 100644 (file)
@@ -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);
index ce1309518405d0ef165a637618037288eddb89d6..802f30506f8e1f4f65e275f84257e19e84940d3e 100644 (file)
@@ -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);
 
index 5edb619f7e5e259069481c1abde3c6fe25c4c7ef..efb7d688a490c1c3a06d6b988a3d4829b04086f0 100644 (file)
@@ -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)
index cd0b73c8f70dbe5bd073c07bff4f2f369939ece7..561638bfd209bbab2f100490c85f445e93008903 100644 (file)
@@ -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
index cec27b85b23959d3394010a5e65a965e36c0d786..d53a7833d0ed480960fdd91cd1272f4347d3a102 100644 (file)
@@ -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 {
index febf2fe59cd46f060747802074cd3eff37bee6dd..2b0ede846af77457ff62b2e8289c852a0fededd8 100644 (file)
@@ -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 */
        
index 91488aa2a497213999bc2fc4a5f9d702112d8bd2..5c9da19f9b2e73511a7f13d8348f1bfa2889c813 100644 (file)
@@ -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);
index 39fa6f36f23f87125e942f13c80a2e8897366e79..b69a804cf6ab7feda3cccd372e11aca792fdf241 100644 (file)
@@ -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);
index 092d15de96e6fc310e0c68568c80b14c373f9c84..33e8c1fbd26ee36d27ffade88ca33ba6f3ec23a3 100644 (file)
@@ -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
index 1d6d98bebdfc991632ef4e197b19d5f241a1507a..65942a14be9ca08ee5a1c09c5ef42b86522b4b12 100644 (file)
@@ -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);
 }
 
 /* ------------------------------------------------------------------------- */