Merging r39717 through r39983 from trunk into soc-2011-tomato
[blender.git] / source / blender / editors / mesh / editmesh.c
index a63f4995acc8c28848aee4f3bc263aa142986d79..e371c346f362c7ddddb8efb9f193d667e736d502 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/mesh/editmesh.c
+ *  \ingroup edmesh
+ */
+
+
 
 #include <stdlib.h>
 #include <string.h>
 
 #include "MEM_guardedalloc.h"
 
-
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
 #include "DNA_key_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
 #include "BLI_editVert.h"
 #include "BLI_dynstr.h"
 #include "BLI_rand.h"
+#include "BLI_utildefines.h"
 
-#include "BKE_cloth.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_context.h"
-#include "BKE_customdata.h"
 #include "BKE_depsgraph.h"
-#include "BKE_DerivedMesh.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
-#include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
 #include "BKE_mesh.h"
-#include "BKE_modifier.h"
-#include "BKE_object.h"
 #include "BKE_paint.h"
-#include "BKE_pointcache.h"
-#include "BKE_softbody.h"
-#include "BKE_texture.h"
-#include "BKE_utildefines.h"
+#include "BKE_report.h"
+#include "BKE_multires.h"
 
 #include "ED_mesh.h"
 #include "ED_object.h"
-#include "ED_retopo.h"
 #include "ED_screen.h"
 #include "ED_util.h"
 #include "ED_view3d.h"
@@ -84,8 +85,8 @@ editmesh.c:
 */
 
 /* XXX */
-static void BIF_undo_push(const char *dummy) {}
-static void error(const char *dummy) {}
+static void BIF_undo_push(const char *UNUSED(arg)) {}
+static void error(const char *UNUSED(arg)) {}
 
 
 /* ***************** HASH ********************* */
@@ -97,7 +98,7 @@ static void error(const char *dummy) {}
 
 /* ************ ADD / REMOVE / FIND ****************** */
 
-static void *calloc_em(EditMesh *em, size_t size, size_t nr)
+static void *calloc_em(EditMesh *UNUSED(em), size_t size, size_t nr)
 {
        return calloc(size, nr);
 }
@@ -263,7 +264,7 @@ EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *exampl
                        eed->h |= (example->h & EM_FGON);
                }
        }
-
+       
        return eed;
 }
 
@@ -384,6 +385,7 @@ EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, Ed
                efa->mat_nr= example->mat_nr;
                efa->flag= example->flag;
                CustomData_em_copy_data(&em->fdata, &em->fdata, example->data, &efa->data);
+               CustomData_em_validate_data(&em->fdata, efa->data, efa->v4 ? 4 : 3);
        }
        else {
                efa->mat_nr= em->mat_nr;
@@ -453,19 +455,19 @@ int editface_containsEdge(EditFace *efa, EditEdge *eed)
 /* ************************ stuct EditMesh manipulation ***************************** */
 
 /* fake callocs for fastmalloc below */
-static void *calloc_fastvert(EditMesh *em, size_t size, size_t nr)
+static void *calloc_fastvert(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
 {
        EditVert *eve= em->curvert++;
        eve->fast= 1;
        return eve;
 }
-static void *calloc_fastedge(EditMesh *em, size_t size, size_t nr)
+static void *calloc_fastedge(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
 {
        EditEdge *eed= em->curedge++;
        eed->fast= 1;
        return eed;
 }
-static void *calloc_fastface(EditMesh *em, size_t size, size_t nr)
+static void *calloc_fastface(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
 {
        EditFace *efa= em->curface++;
        efa->fast= 1;
@@ -597,7 +599,7 @@ static void edge_normal_compare(EditEdge *eed, EditFace *efa1)
        if(efa1==efa2) return;
        
        inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2];
-       if(inp<0.999 && inp >-0.999) eed->f2= 1;
+       if(inp<0.999f && inp >-0.999f) eed->f2= 1;
                
        if(efa1->v4) cent_quad_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co);
        else cent_tri_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co);
@@ -608,7 +610,7 @@ static void edge_normal_compare(EditEdge *eed, EditFace *efa1)
        normalize_v3(cent1);
        inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2]; 
 
-       if(inp < -0.001 ) eed->f1= 1;
+       if(inp < -0.001f) eed->f1= 1;
 }
 
 #if 0
@@ -743,6 +745,7 @@ void make_editMesh(Scene *scene, Object *ob)
        EditSelection *ese;
        float *co, (*keyco)[3]= NULL;
        int tot, a, eekadoodle= 0;
+       const short is_paint_sel= paint_facesel_test(ob);
 
        if(me->edit_mesh==NULL)
                me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
@@ -793,13 +796,11 @@ void make_editMesh(Scene *scene, Object *ob)
                evlist[a]= eve;
                
                /* face select sets selection in next loop */
-               if(!paint_facesel_test(ob))
+               if(!is_paint_sel)
                        eve->f |= (mvert->flag & 1);
                
-               if (mvert->flag & ME_HIDE) eve->h= 1;           
-               eve->no[0]= mvert->no[0]/32767.0;
-               eve->no[1]= mvert->no[1]/32767.0;
-               eve->no[2]= mvert->no[2]/32767.0;
+               if (mvert->flag & ME_HIDE) eve->h= 1;
+               normal_short_to_float_v3(eve->no, mvert->no);
 
                eve->bweight= ((float)mvert->bweight)/255.0f;
 
@@ -868,7 +869,7 @@ void make_editMesh(Scene *scene, Object *ob)
                                        if(mface->flag & ME_FACE_SEL) {
                                                efa->f |= SELECT;
                                                
-                                               if(paint_facesel_test(ob)) {
+                                               if(is_paint_sel) {
                                                        EM_select_face(efa, 1); /* flush down */
                                                }
 
@@ -921,9 +922,9 @@ void make_editMesh(Scene *scene, Object *ob)
 }
 
 /* makes Mesh out of editmesh */
-void load_editMesh(Scene *scene, Object *ob)
+void load_editMesh(Scene *scene, Object *obedit)
 {
-       Mesh *me= ob->data;
+       Mesh *me= obedit->data;
        MVert *mvert, *oldverts;
        MEdge *medge;
        MFace *mface;
@@ -933,7 +934,7 @@ void load_editMesh(Scene *scene, Object *ob)
        EditFace *efa, *efa_act;
        EditEdge *eed;
        EditSelection *ese;
-       float *fp, *newkey, *oldkey, nor[3];
+       float *fp, *newkey, *oldkey;
        int i, a, ototvert;
        
        /* this one also tests of edges are not in faces: */
@@ -991,12 +992,8 @@ void load_editMesh(Scene *scene, Object *ob)
        while(eve) {
                VECCOPY(mvert->co, eve->co);
 
-               mvert->mat_nr= 32767;  /* what was this for, halos? */
-               
                /* vertex normal */
-               VECCOPY(nor, eve->no);
-               mul_v3_fl(nor, 32767.0);
-               VECCOPY(mvert->no, nor);
+               normal_float_to_short_v3(mvert->no, eve->no);
 
                /* note: it used to remove me->dvert when it was not in use, cancelled
                   that... annoying when you have a fresh vgroup */
@@ -1008,7 +1005,7 @@ void load_editMesh(Scene *scene, Object *ob)
                mvert->flag |= (eve->f & SELECT);
                if (eve->h) mvert->flag |= ME_HIDE;
                
-               mvert->bweight= (char)(255.0*eve->bweight);
+               mvert->bweight= (char)(255.0f*eve->bweight);
 
                eve= eve->next;
                mvert++;
@@ -1029,8 +1026,8 @@ void load_editMesh(Scene *scene, Object *ob)
                if(eed->h & EM_FGON) medge->flag |= ME_FGON;    // different defines yes
                if(eed->h & 1) medge->flag |= ME_HIDE;
                
-               medge->crease= (char)(255.0*eed->crease);
-               medge->bweight= (char)(255.0*eed->bweight);
+               medge->crease= (char)(255.0f*eed->crease);
+               medge->bweight= (char)(255.0f*eed->bweight);
                CustomData_from_em_block(&em->edata, &me->edata, eed->data, a);         
 
                eed->tmp.l = a++;
@@ -1065,20 +1062,6 @@ void load_editMesh(Scene *scene, Object *ob)
                        if(efa->f & 1) mface->flag |= ME_FACE_SEL;
                        else mface->flag &= ~ME_FACE_SEL;
                }
-               
-               /* mat_nr in vertex */
-               if(me->totcol>1) {
-                       mvert= me->mvert+mface->v1;
-                       if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr;
-                       mvert= me->mvert+mface->v2;
-                       if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr;
-                       mvert= me->mvert+mface->v3;
-                       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)32767) mvert->mat_nr= mface->mat_nr;
-                       }
-               }
                        
                /* watch: efa->e1->f2==0 means loose edge */ 
                        
@@ -1113,10 +1096,10 @@ void load_editMesh(Scene *scene, Object *ob)
                Object *ob;
                ModifierData *md;
                EditVert **vertMap = NULL;
-               int i,j;
+               int j;
 
                for (ob=G.main->object.first; ob; ob=ob->id.next) {
-                       if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) {
+                       if (ob->parent==obedit && ELEM(ob->partype, PARVERT1,PARVERT3)) {
                                
                                /* duplicate code from below, make it function later...? */
                                if (!vertMap) {
@@ -1194,12 +1177,15 @@ void load_editMesh(Scene *scene, Object *ob)
                        }
 
                        if(act_is_basis) { /* active key is a base */
+                               float (*fp)[3]= actkey->data;
                                i=0;
                                ofs= MEM_callocN(sizeof(float) * 3 * em->totvert,  "currkey->data");
                                eve= em->verts.first;
                                mvert = me->mvert;
                                while(eve) {
-                                       VECSUB(ofs[i], mvert->co, oldverts[eve->keyindex].co);
+                                       if(eve->keyindex>=0)
+                                               VECSUB(ofs[i], mvert->co, fp[eve->keyindex]);
+
                                        eve= eve->next;
                                        i++;
                                        mvert++;
@@ -1311,12 +1297,15 @@ void load_editMesh(Scene *scene, Object *ob)
        }
 
        mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+
+       /* topology could be changed, ensure mdisps are ok */
+       multires_topology_changed(scene, obedit);
 }
 
 void remake_editMesh(Scene *scene, Object *ob)
 {
        make_editMesh(scene, ob);
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        BIF_undo_push("Undo all changes");
 }
 
@@ -1330,7 +1319,7 @@ static EnumPropertyItem prop_separate_types[] = {
 };
 
 /* return 1: success */
-static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase)
+static int mesh_separate_selected(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
 {
        EditMesh *em, *emnew;
        EditVert *eve, *v1;
@@ -1346,7 +1335,7 @@ static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase)
        me= obedit->data;
        em= BKE_mesh_get_editmesh(me);
        if(me->key) {
-               error("Can't separate with vertex keys");
+               BKE_report(op->reports, RPT_WARNING, "Can't separate mesh with shape keys.");
                BKE_mesh_end_editmesh(me, em);
                return 0;
        }
@@ -1428,12 +1417,19 @@ static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase)
        free_editMesh(emnew);
        MEM_freeN(menew->edit_mesh);
        menew->edit_mesh= NULL;
-       
+
+       /* copy settings */
+       menew->texflag= me->texflag;
+       menew->drawflag= me->drawflag;
+       menew->flag= me->flag;
+       menew->editflag= me->editflag;
+       menew->smoothresh= me->smoothresh;
+
        /* hashedges are invalid now, make new! */
        editMesh_set_hash(em);
 
-       DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);       
-       DAG_id_flush_update(&basenew->object->id, OB_RECALC_DATA);      
+       DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); 
+       DAG_id_tag_update(&basenew->object->id, OB_RECALC_DATA);        
 
        BKE_mesh_end_editmesh(me, em);
 
@@ -1441,7 +1437,7 @@ static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase)
 }
 
 /* return 1: success */
-static int mesh_separate_material(Main *bmain, Scene *scene, Base *editbase)
+static int mesh_separate_material(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
 {
        Mesh *me= editbase->object->data;
        EditMesh *em= BKE_mesh_get_editmesh(me);
@@ -1453,9 +1449,8 @@ static int mesh_separate_material(Main *bmain, Scene *scene, Base *editbase)
                /* select the material */
                EM_select_by_material(em, curr_mat);
                /* and now separate */
-               if(0==mesh_separate_selected(bmain, scene, editbase)) {
-                       BKE_mesh_end_editmesh(me, em);
-                       return 0;
+               if(em->totfacesel > 0) {
+                       mesh_separate_selected(op, bmain, scene, editbase);
                }
        }
 
@@ -1464,7 +1459,7 @@ static int mesh_separate_material(Main *bmain, Scene *scene, Base *editbase)
 }
 
 /* return 1: success */
-static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase)
+static int mesh_separate_loose(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
 {
        Mesh *me;
        EditMesh *em;
@@ -1504,7 +1499,7 @@ static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase)
                tot= BLI_countlist(&em->verts);
 
                /* and now separate */
-               doit= mesh_separate_selected(bmain, scene, editbase);
+               doit= mesh_separate_selected(op, bmain, scene, editbase);
 
                /* with hidden verts this can happen */
                if(tot == BLI_countlist(&em->verts))
@@ -1524,14 +1519,19 @@ static int mesh_separate_exec(bContext *C, wmOperator *op)
        int retval= 0, type= RNA_enum_get(op->ptr, "type");
        
        if(type == 0)
-               retval= mesh_separate_selected(bmain, scene, base);
+               retval= mesh_separate_selected(op, bmain, scene, base);
        else if(type == 1)
-               retval= mesh_separate_material(bmain, scene, base);
+               retval= mesh_separate_material(op, bmain, scene, base);
        else if(type == 2)
-               retval= mesh_separate_loose(bmain, scene, base);
+               retval= mesh_separate_loose(op, bmain, scene, base);
           
        if(retval) {
                WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
+
+               // XXX: new object was created, but selection wasn't actually changed
+               //      need this for outliner update without adding new ND. nazgul.
+               WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
+
                return OPERATOR_FINISHED;
        }
        return OPERATOR_CANCELLED;
@@ -1601,7 +1601,6 @@ typedef struct UndoMesh {
        EditSelectionC *selected;
        int totvert, totedge, totface, totsel;
        int selectmode, shapenr;
-       RetopoPaintData *retopo_paint_data;
        char retopo_mode;
        CustomData vdata, edata, fdata;
 } UndoMesh;
@@ -1667,7 +1666,7 @@ static void *editMesh_to_undoMesh(void *emv)
                evec->h= eve->h;
                evec->keyindex= eve->keyindex;
                eve->tmp.l = a; /*store index*/
-               evec->bweight= (short)(eve->bweight*255.0);
+               evec->bweight= (short)(eve->bweight*255.0f);
 
                CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a);
        }
@@ -1681,8 +1680,8 @@ static void *editMesh_to_undoMesh(void *emv)
                eedc->h= eed->h;
                eedc->seam= eed->seam;
                eedc->sharp= eed->sharp;
-               eedc->crease= (short)(eed->crease*255.0);
-               eedc->bweight= (short)(eed->bweight*255.0);
+               eedc->crease= (short)(eed->crease*255.0f);
+               eedc->bweight= (short)(eed->bweight*255.0f);
                eedc->fgoni= eed->fgoni;
                eed->tmp.l = a; /*store index*/
                CustomData_from_em_block(&em->edata, &um->edata, eed->data, a);
@@ -1848,7 +1847,7 @@ static void *getEditMesh(bContext *C)
 }
 
 /* and this is all the undo system needs to know */
-void undo_push_mesh(bContext *C, char *name)
+void undo_push_mesh(bContext *C, const char *name)
 {
        undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL);
 }