4d6502157ec30d6895fe55c6841b357ddb206e52
[blender.git] / source / blender / src / editmesh.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #ifdef WIN32
43 #include "BLI_winstuff.h"
44 #endif
45 #include "MEM_guardedalloc.h"
46
47 #include "PIL_time.h"
48
49 #include "DNA_mesh_types.h"
50 #include "DNA_meshdata_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_screen_types.h"
53 #include "DNA_key_types.h"
54 #include "DNA_scene_types.h"
55 #include "DNA_view3d_types.h"
56 #include "DNA_material_types.h"
57 #include "DNA_texture_types.h"
58 #include "DNA_userdef_types.h"
59
60 #include "BLI_blenlib.h"
61 #include "BLI_arithb.h"
62 #include "BLI_editVert.h"
63 #include "BLI_dynstr.h"
64
65 #include "BKE_utildefines.h"
66 #include "BKE_key.h"
67 #include "BKE_object.h"
68 #include "BKE_displist.h"
69 #include "BKE_global.h"
70 #include "BKE_library.h"
71 #include "BKE_main.h"
72 #include "BKE_material.h"
73 #include "BKE_mesh.h"
74 #include "BKE_texture.h"
75
76 #include "BIF_editkey.h"
77 #include "BIF_editmesh.h"
78 #include "BIF_editmode_undo.h"
79 #include "BIF_interface.h"
80 #include "BIF_mywindow.h"
81 #include "BIF_space.h"
82 #include "BIF_screen.h"
83 #include "BIF_toolbox.h"
84
85 #include "BSE_view.h"
86 #include "BSE_edit.h"
87 #include "BSE_trans_types.h"
88
89 #include "BDR_drawobject.h"
90 #include "BDR_editobject.h"
91 #include "BDR_editface.h"
92 #include "BDR_vpaint.h"
93
94 #include "mydevice.h"
95 #include "blendef.h"
96 #include "render.h"
97
98 /* own include */
99 #include "editmesh.h"
100
101 /* 
102
103 editmesh.c:
104 - add/alloc/free data
105 - hashtables
106 - enter/exit editmode
107
108 */
109
110
111 /* ***************** HASH ********************* */
112
113
114 #define EDHASHSIZE              (512*512)
115 #define EDHASH(a, b)    (a % EDHASHSIZE)
116
117
118 /* ************ ADD / REMOVE / FIND ****************** */
119
120 /* used to bypass normal calloc with fast one */
121 static void *(*callocvert)(size_t, size_t) = calloc;
122 static void *(*callocedge)(size_t, size_t) = calloc;
123 static void *(*callocface)(size_t, size_t) = calloc;
124
125 EditVert *addvertlist(float *vec)
126 {
127         EditMesh *em = G.editMesh;
128         EditVert *eve;
129         static int hashnr= 0;
130
131         eve= callocvert(sizeof(EditVert), 1);
132         BLI_addtail(&em->verts, eve);
133         
134         if(vec) VECCOPY(eve->co, vec);
135
136         eve->hash= hashnr++;
137         if( hashnr>=EDHASHSIZE) hashnr= 0;
138
139         /* new verts get keyindex of -1 since they did not
140          * have a pre-editmode vertex order
141          */
142         eve->keyindex = -1;
143         return eve;
144 }
145
146 void free_editvert (EditVert *eve)
147 {
148         if(eve->dw) MEM_freeN(eve->dw);
149         if(eve->fast==0) free(eve);
150 }
151
152
153 EditEdge *findedgelist(EditVert *v1, EditVert *v2)
154 {
155         EditVert *v3;
156         struct HashEdge *he;
157
158         /* swap ? */
159         if( (long)v1 > (long)v2) {
160                 v3= v2; 
161                 v2= v1; 
162                 v1= v3;
163         }
164         
165         if(G.editMesh->hashedgetab==NULL)
166                 G.editMesh->hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab");
167
168         he= G.editMesh->hashedgetab + EDHASH(v1->hash, v2->hash);
169         
170         while(he) {
171                 
172                 if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed;
173                 
174                 he= he->next;
175         }
176         return 0;
177 }
178
179 static void insert_hashedge(EditEdge *eed)
180 {
181         /* assuming that eed is not in the list yet, and that a find has been done before */
182         
183         struct HashEdge *first, *he;
184
185         first= G.editMesh->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
186
187         if( first->eed==0 ) {
188                 first->eed= eed;
189         }
190         else {
191                 he= &eed->hash; 
192                 he->eed= eed;
193                 he->next= first->next;
194                 first->next= he;
195         }
196 }
197
198 static void remove_hashedge(EditEdge *eed)
199 {
200         /* assuming eed is in the list */
201         
202         struct HashEdge *first, *he, *prev=NULL;
203
204         he=first= G.editMesh->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
205
206         while(he) {
207                 if(he->eed == eed) {
208                         /* remove from list */
209                         if(he==first) {
210                                 if(first->next) {
211                                         he= first->next;
212                                         first->eed= he->eed;
213                                         first->next= he->next;
214                                 }
215                                 else he->eed= 0;
216                         }
217                         else {
218                                 prev->next= he->next;
219                         }
220                         return;
221                 }
222                 prev= he;
223                 he= he->next;
224         }
225 }
226
227 EditEdge *addedgelist(EditVert *v1, EditVert *v2, EditEdge *example)
228 {
229         EditMesh *em = G.editMesh;
230         EditVert *v3;
231         EditEdge *eed;
232         int swap= 0;
233         
234         if(v1==v2) return NULL;
235         if(v1==NULL || v2==NULL) return NULL;
236
237         /* swap ? */
238         if(v1>v2) {
239                 v3= v2; 
240                 v2= v1; 
241                 v1= v3;
242                 swap= 1;
243         }
244         
245         /* find in hashlist */
246         eed= findedgelist(v1, v2);
247
248         if(eed==NULL) {
249         
250                 eed= (EditEdge *)callocedge(sizeof(EditEdge), 1);
251                 eed->v1= v1;
252                 eed->v2= v2;
253                 BLI_addtail(&em->edges, eed);
254                 eed->dir= swap;
255                 insert_hashedge(eed);
256                 
257                 /* copy edge data:
258                    rule is to do this with addedgelist call, before addfacelist */
259                 if(example) {
260                         eed->crease= example->crease;
261                         eed->seam = example->seam;
262                         eed->h |= (example->h & EM_FGON);
263                 }
264         }
265
266         return eed;
267 }
268
269 void remedge(EditEdge *eed)
270 {
271         EditMesh *em = G.editMesh;
272
273         BLI_remlink(&em->edges, eed);
274         remove_hashedge(eed);
275 }
276
277 void free_editedge(EditEdge *eed)
278 {
279         if(eed->fast==0) free(eed);
280 }
281
282 void free_editface(EditFace *efa)
283 {
284         if(efa->fast==0) free(efa);
285 }
286
287 void free_vertlist(ListBase *edve) 
288 {
289         EditVert *eve, *next;
290
291         if (!edve) return;
292
293         eve= edve->first;
294         while(eve) {
295                 next= eve->next;
296                 free_editvert(eve);
297                 eve= next;
298         }
299         edve->first= edve->last= NULL;
300 }
301
302 void free_edgelist(ListBase *lb)
303 {
304         EditEdge *eed, *next;
305         
306         eed= lb->first;
307         while(eed) {
308                 next= eed->next;
309                 free_editedge(eed);
310                 eed= next;
311         }
312         lb->first= lb->last= NULL;
313 }
314
315 void free_facelist(ListBase *lb)
316 {
317         EditFace *efa, *next;
318         
319         efa= lb->first;
320         while(efa) {
321                 next= efa->next;
322                 free_editface(efa);
323                 efa= next;
324         }
325         lb->first= lb->last= NULL;
326 }
327
328 EditFace *addfacelist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditFace *example, EditFace *exampleEdges)
329 {
330         EditMesh *em = G.editMesh;
331         EditFace *efa;
332         EditEdge *e1, *e2=0, *e3=0, *e4=0;
333
334         /* add face to list and do the edges */
335         if(exampleEdges) {
336                 e1= addedgelist(v1, v2, exampleEdges->e1);
337                 e2= addedgelist(v2, v3, exampleEdges->e2);
338                 if(v4) e3= addedgelist(v3, v4, exampleEdges->e3); 
339                 else e3= addedgelist(v3, v1, exampleEdges->e3);
340                 if(v4) e4= addedgelist(v4, v1, exampleEdges->e4);
341         }
342         else {
343                 e1= addedgelist(v1, v2, NULL);
344                 e2= addedgelist(v2, v3, NULL);
345                 if(v4) e3= addedgelist(v3, v4, NULL); 
346                 else e3= addedgelist(v3, v1, NULL);
347                 if(v4) e4= addedgelist(v4, v1, NULL);
348         }
349         
350         if(v1==v2 || v2==v3 || v1==v3) return NULL;
351         if(e2==0) return NULL;
352
353         efa= (EditFace *)callocface(sizeof(EditFace), 1);
354         efa->v1= v1;
355         efa->v2= v2;
356         efa->v3= v3;
357         efa->v4= v4;
358
359         efa->e1= e1;
360         efa->e2= e2;
361         efa->e3= e3;
362         efa->e4= e4;
363
364         if(example) {
365                 efa->mat_nr= example->mat_nr;
366                 efa->tf= example->tf;
367                 efa->flag= example->flag;
368         }
369         else {
370                 if (G.obedit && G.obedit->actcol)
371                         efa->mat_nr= G.obedit->actcol-1;
372                 default_uv(efa->tf.uv, 1.0);
373
374                 /* Initialize colors */
375                 efa->tf.col[0]= efa->tf.col[1]= efa->tf.col[2]= efa->tf.col[3]= vpaint_get_current_col();
376         }
377
378         BLI_addtail(&em->faces, efa);
379
380         if(efa->v4) {
381                 CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
382                 CalcCent4f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
383         }
384         else {
385                 CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
386                 CalcCent3f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
387         }
388
389         return efa;
390 }
391
392 /* ************************ end add/new/find ************  */
393
394 /* ************************ stuct EditMesh manipulation ***************************** */
395
396 /* fake callocs for fastmalloc below */
397 static void *calloc_fastvert(size_t size, size_t nr)
398 {
399         EditVert *eve= G.editMesh->curvert++;
400         eve->fast= 1;
401         return eve;
402 }
403 static void *calloc_fastedge(size_t size, size_t nr)
404 {
405         EditEdge *eed= G.editMesh->curedge++;
406         eed->fast= 1;
407         return eed;
408 }
409 static void *calloc_fastface(size_t size, size_t nr)
410 {
411         EditFace *efa= G.editMesh->curface++;
412         efa->fast= 1;
413         return efa;
414 }
415
416 /* allocate 1 chunk for all vertices, edges, faces. These get tagged to
417    prevent it from being freed
418 */
419 static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface)
420 {
421         
422         if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts");
423         else em->allverts= NULL;
424         em->curvert= em->allverts;
425         
426         if(totedge==0) totedge= 4*totface;      // max possible
427
428         if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges");
429         else em->alledges= NULL;
430         em->curedge= em->alledges;
431         
432         if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces");
433         else em->allfaces= NULL;
434         em->curface= em->allfaces;
435
436         callocvert= calloc_fastvert;
437         callocedge= calloc_fastedge;
438         callocface= calloc_fastface;
439 }
440
441 static void end_editmesh_fastmalloc(void)
442 {
443         callocvert= calloc;
444         callocedge= calloc;
445         callocface= calloc;
446 }
447
448 void free_editMesh(EditMesh *em)
449 {
450         if(em==NULL) return;
451         
452         if(em->verts.first) free_vertlist(&em->verts);
453         if(em->edges.first) free_edgelist(&em->edges);
454         if(em->faces.first) free_facelist(&em->faces);
455
456         /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */
457 #if 0
458         if(em->hashedgetab) {
459                 HashEdge *he, *hen;
460                 int a, used=0, max=0, nr;
461                 he= em->hashedgetab;
462                 for(a=0; a<EDHASHSIZE; a++, he++) {
463                         if(he->eed) used++;
464                         hen= he->next;
465                         nr= 0;
466                         while(hen) {
467                                 nr++;
468                                 hen= hen->next;
469                         }
470                         if(max<nr) max= nr;
471                 }
472                 printf("hastab used %d max %d\n", used, max);
473         }
474 #endif
475         if(em->hashedgetab) MEM_freeN(em->hashedgetab);
476         em->hashedgetab= NULL;
477         
478         if(em->allverts) MEM_freeN(em->allverts);
479         if(em->alledges) MEM_freeN(em->alledges);
480         if(em->allfaces) MEM_freeN(em->allfaces);
481         
482         em->allverts= em->curvert= NULL;
483         em->alledges= em->curedge= NULL;
484         em->allfaces= em->curface= NULL;
485         
486         G.totvert= G.totface= 0;
487 }
488
489 /* on G.editMesh */
490 static void editMesh_set_hash(void)
491 {
492         EditEdge *eed;
493
494         G.editMesh->hashedgetab= NULL;
495         
496         for(eed=G.editMesh->edges.first; eed; eed= eed->next)  {
497                 if( findedgelist(eed->v1, eed->v2)==NULL )
498                         insert_hashedge(eed);
499         }
500
501 }
502
503
504 /* ************************ IN & OUT EDITMODE ***************************** */
505
506
507 static void edge_normal_compare(EditEdge *eed, EditFace *efa1)
508 {
509         EditFace *efa2;
510         float cent1[3], cent2[3];
511         float inp;
512         
513         efa2= (EditFace *)eed->vn;
514         if(efa1==efa2) return;
515         
516         inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2];
517         if(inp<0.999 && inp >-0.999) eed->f2= 1;
518                 
519         if(efa1->v4) CalcCent4f(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co);
520         else CalcCent3f(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co);
521         if(efa2->v4) CalcCent4f(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co, efa2->v4->co);
522         else CalcCent3f(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co);
523         
524         VecSubf(cent1, cent2, cent1);
525         Normalise(cent1);
526         inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2]; 
527
528         if(inp < -0.001 ) eed->f1= 1;
529 }
530
531 static void edge_drawflags(void)
532 {
533         EditMesh *em = G.editMesh;
534         EditVert *eve;
535         EditEdge *eed, *e1, *e2, *e3, *e4;
536         EditFace *efa;
537         
538         /* - count number of times edges are used in faces: 0 en 1 time means draw edge
539          * - edges more than 1 time used: in *vn is pointer to first face
540          * - check all faces, when normal differs to much: draw (flag becomes 1)
541          */
542
543         /* later on: added flags for 'cylinder' and 'sphere' intersection tests in old
544            game engine (2.04)
545          */
546         
547         recalc_editnormals();
548         
549         /* init */
550         eve= em->verts.first;
551         while(eve) {
552                 eve->f1= 1;             /* during test it's set at zero */
553                 eve= eve->next;
554         }
555         eed= em->edges.first;
556         while(eed) {
557                 eed->f2= eed->f1= 0;
558                 eed->vn= 0;
559                 eed= eed->next;
560         }
561
562         efa= em->faces.first;
563         while(efa) {
564                 e1= efa->e1;
565                 e2= efa->e2;
566                 e3= efa->e3;
567                 e4= efa->e4;
568                 if(e1->f2<3) e1->f2+= 1;
569                 if(e2->f2<3) e2->f2+= 1;
570                 if(e3->f2<3) e3->f2+= 1;
571                 if(e4 && e4->f<3) e4->f2+= 1;
572                 
573                 if(e1->vn==0) e1->vn= (EditVert *)efa;
574                 if(e2->vn==0) e2->vn= (EditVert *)efa;
575                 if(e3->vn==0) e3->vn= (EditVert *)efa;
576                 if(e4 && e4->vn==0) e4->vn= (EditVert *)efa;
577                 
578                 efa= efa->next;
579         }
580
581         if(G.f & G_ALLEDGES) {
582                 efa= em->faces.first;
583                 while(efa) {
584                         if(efa->e1->f2>=2) efa->e1->f2= 1;
585                         if(efa->e2->f2>=2) efa->e2->f2= 1;
586                         if(efa->e3->f2>=2) efa->e3->f2= 1;
587                         if(efa->e4 && efa->e4->f>=2) efa->e4->f2= 1;
588                         
589                         efa= efa->next;
590                 }               
591         }       
592         else {
593                 
594                 /* handle single-edges for 'test cylinder flag' (old engine) */
595                 
596                 eed= em->edges.first;
597                 while(eed) {
598                         if(eed->f2==1) eed->f1= 1;
599                         eed= eed->next;
600                 }
601
602                 /* all faces, all edges with flag==2: compare normal */
603                 efa= em->faces.first;
604                 while(efa) {
605                         if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa);
606                         if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa);
607                         if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa);
608                         if(efa->e4 && efa->e4->f2==2) edge_normal_compare(efa->e4, efa);
609                         
610                         efa= efa->next;
611                 }
612                 
613                 /* sphere collision flag */
614                 
615                 eed= em->edges.first;
616                 while(eed) {
617                         if(eed->f1!=1) {
618                                 eed->v1->f1= eed->v2->f1= 0;
619                         }
620                         eed= eed->next;
621                 }
622                 
623         }
624 }
625
626 /* turns Mesh into editmesh */
627 void make_editMesh()
628 {
629         EditMesh *em = G.editMesh;
630         Mesh *me= G.obedit->data;
631         MFace *mface;
632         TFace *tface;
633         MVert *mvert;
634         KeyBlock *actkey=0;
635         EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
636         EditFace *efa;
637         EditEdge *eed;
638         int tot, a;
639
640         if(G.obedit==NULL) return;
641
642         /* because of reload */
643         free_editMesh(G.editMesh);
644         
645         G.totvert= tot= me->totvert;
646
647         if(tot==0) {
648                 countall();
649                 return;
650         }
651         
652         waitcursor(1);
653
654         /* initialize fastmalloc for editmesh */
655         init_editmesh_fastmalloc(G.editMesh, me->totvert, me->totedge, me->totface);
656
657         /* keys? */
658         if(me->key) {
659                 actkey= me->key->block.first;
660                 while(actkey) {
661                         if(actkey->flag & SELECT) break;
662                         actkey= actkey->next;
663                 }
664         }
665
666         if(actkey) {
667                 key_to_mesh(actkey, me);
668                 tot= actkey->totelem;
669         }
670
671         /* make editverts */
672         mvert= me->mvert;
673
674         evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
675         for(a=0; a<tot; a++, mvert++) {
676                 eve= addvertlist(mvert->co);
677                 evlist[a]= eve;
678                 
679                 // face select sets selection in next loop
680                 if( (G.f & G_FACESELECT)==0 )
681                         eve->f |= (mvert->flag & 1);
682                 
683                 if (mvert->flag & ME_HIDE) eve->h= 1;           
684                 eve->no[0]= mvert->no[0]/32767.0;
685                 eve->no[1]= mvert->no[1]/32767.0;
686                 eve->no[2]= mvert->no[2]/32767.0;
687
688                 /* lets overwrite the keyindex of the editvert
689                  * with the order it used to be in before
690                  * editmode
691                  */
692                 eve->keyindex = a;
693
694                 if (me->dvert){
695                         eve->totweight = me->dvert[a].totweight;
696                         if (me->dvert[a].dw){
697                                 eve->dw = MEM_callocN (sizeof(MDeformWeight) * me->dvert[a].totweight, "deformWeight");
698                                 memcpy (eve->dw, me->dvert[a].dw, sizeof(MDeformWeight) * me->dvert[a].totweight);
699                         }
700                 }
701
702         }
703
704         if(actkey && actkey->totelem!=me->totvert);
705         else {
706                 unsigned int *mcol;
707                 
708                 /* make edges */
709                 if(me->medge) {
710                         MEdge *medge= me->medge;
711                         
712                         for(a=0; a<me->totedge; a++, medge++) {
713                                 eed= addedgelist(evlist[medge->v1], evlist[medge->v2], NULL);
714                                 eed->crease= ((float)medge->crease)/255.0;
715                                 
716                                 if(medge->flag & ME_SEAM) eed->seam= 1;
717                                 if(medge->flag & SELECT) eed->f |= SELECT;
718                                 if(medge->flag & ME_FGON) eed->h= EM_FGON;      // 2 different defines!
719                                 if(medge->flag & ME_HIDE) eed->h |= 1;
720                         }
721
722                 }
723                 
724                 /* make faces */
725                 mface= me->mface;
726                 tface= me->tface;
727                 mcol= (unsigned int *)me->mcol;
728                 
729                 for(a=0; a<me->totface; a++, mface++) {
730                         eve1= evlist[mface->v1];
731                         eve2= evlist[mface->v2];
732                         if(mface->v3) eve3= evlist[mface->v3]; else eve3= NULL;
733                         if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL;
734                         
735                         efa= addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
736
737                         if(efa) {
738                         
739                                 if(mcol) memcpy(efa->tf.col, mcol, 4*sizeof(int));
740
741                                 if(me->tface) {
742                                         efa->tf= *tface;
743
744                                         if( tface->flag & TF_SELECT) {
745                                                 if(G.f & G_FACESELECT) {
746                                                         EM_select_face(efa, 1);
747                                                 }
748                                         }
749                                 }
750                         
751                                 efa->mat_nr= mface->mat_nr;
752                                 efa->flag= mface->flag & ~ME_HIDE;
753                                 
754                                 if((G.f & G_FACESELECT)==0) {
755                                         /* select face flag, if no edges we flush down */
756                                         if(mface->flag & ME_FACE_SEL) {
757                                                 efa->f |= SELECT;
758                                                 if(me->medge==NULL) EM_select_face(efa, 1);
759                                         }
760                                 }
761                                 if(mface->flag & ME_HIDE) efa->h= 1;
762                                 
763                         }
764
765                         if(me->tface) tface++;
766                         if(mcol) mcol+=4;
767                 }
768         }
769         
770         /* flush hide flags when no medge */
771         if(me->medge==NULL) {
772                 for(eed= em->edges.first; eed; eed= eed->next) {
773                         if(eed->v1->h || eed->v2->h) eed->h |= 1;
774                         else eed->h &= ~1;
775                 }       
776         }
777         
778         MEM_freeN(evlist);
779
780         end_editmesh_fastmalloc();      // resets global function pointers
781
782         /* this creates coherent selections. also needed for older files */
783         EM_selectmode_set();
784         /* paranoia check to enforce hide rules */
785         EM_hide_reset();
786         /* sets helper flags which arent saved */
787         EM_fgon_flags();
788         
789         countall();
790         
791         if (mesh_uses_displist(me)) makeDispList(G.obedit);
792         
793         waitcursor(0);
794 }
795
796 /** Rotates MFace and UVFace vertices in case the last
797   * vertex index is = 0. 
798   * This function is a hack and may only be called in the
799   * conversion from EditMesh to Mesh data.
800   * This function is similar to test_index_mface in
801   * blenkernel/intern/mesh.c. 
802   * To not clutter the blenkernel code with more bad level
803   * calls/structures, this function resides here.
804   */
805
806 static void fix_faceindices(MFace *mface, EditFace *efa, int nr)
807 {
808         int a;
809         float tmpuv[2];
810         unsigned int tmpcol;
811
812         /* first test if the face is legal */
813
814         if(mface->v3 && mface->v3==mface->v4) {
815                 mface->v4= 0;
816                 nr--;
817         }
818         if(mface->v2 && mface->v2==mface->v3) {
819                 mface->v3= mface->v4;
820                 mface->v4= 0;
821                 nr--;
822         }
823         if(mface->v1==mface->v2) {
824                 mface->v2= mface->v3;
825                 mface->v3= mface->v4;
826                 mface->v4= 0;
827                 nr--;
828         }
829
830         /* prevent a zero index value at the wrong location */
831         if(nr==2) {
832                 if(mface->v2==0) SWAP(int, mface->v1, mface->v2);
833         }
834         else if(nr==3) {
835                 if(mface->v3==0) {
836                         SWAP(int, mface->v1, mface->v2);
837                         SWAP(int, mface->v2, mface->v3);
838                         /* rotate face UV coordinates, too */
839                         UVCOPY(tmpuv, efa->tf.uv[0]);
840                         UVCOPY(efa->tf.uv[0], efa->tf.uv[1]);
841                         UVCOPY(efa->tf.uv[1], efa->tf.uv[2]);
842                         UVCOPY(efa->tf.uv[2], tmpuv);
843                         /* same with vertex colours */
844                         tmpcol = efa->tf.col[0];
845                         efa->tf.col[0] = efa->tf.col[1];
846                         efa->tf.col[1] = efa->tf.col[2];
847                         efa->tf.col[2] = tmpcol;
848
849                         
850                         a= mface->edcode;
851                         mface->edcode= 0;
852                         if(a & ME_V1V2) mface->edcode |= ME_V3V1;
853                         if(a & ME_V2V3) mface->edcode |= ME_V1V2;
854                         if(a & ME_V3V1) mface->edcode |= ME_V2V3;
855                         
856                         a= mface->puno;
857                         mface->puno &= ~15;
858                         if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2;
859                         if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3;
860                         if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
861
862                 }
863         }
864         else if(nr==4) {
865                 if(mface->v3==0 || mface->v4==0) {
866                         SWAP(int, mface->v1, mface->v3);
867                         SWAP(int, mface->v2, mface->v4);
868                         /* swap UV coordinates */
869                         UVCOPY(tmpuv, efa->tf.uv[0]);
870                         UVCOPY(efa->tf.uv[0], efa->tf.uv[2]);
871                         UVCOPY(efa->tf.uv[2], tmpuv);
872                         UVCOPY(tmpuv, efa->tf.uv[1]);
873                         UVCOPY(efa->tf.uv[1], efa->tf.uv[3]);
874                         UVCOPY(efa->tf.uv[3], tmpuv);
875                         /* swap vertex colours */
876                         tmpcol = efa->tf.col[0];
877                         efa->tf.col[0] = efa->tf.col[2];
878                         efa->tf.col[2] = tmpcol;
879                         tmpcol = efa->tf.col[1];
880                         efa->tf.col[1] = efa->tf.col[3];
881                         efa->tf.col[3] = tmpcol;
882
883                         a= mface->edcode;
884                         mface->edcode= 0;
885                         if(a & ME_V1V2) mface->edcode |= ME_V3V4;
886                         if(a & ME_V2V3) mface->edcode |= ME_V2V3;
887                         if(a & ME_V3V4) mface->edcode |= ME_V1V2;
888                         if(a & ME_V4V1) mface->edcode |= ME_V4V1;
889
890                         a= mface->puno;
891                         mface->puno &= ~15;
892                         if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3;
893                         if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4;
894                         if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
895                         if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2;
896
897                 }
898         }
899 }
900
901 /* makes Mesh out of editmesh */
902 void load_editMesh(void)
903 {
904         EditMesh *em = G.editMesh;
905         Mesh *me= G.obedit->data;
906         MVert *mvert, *oldverts;
907         MEdge *medge=NULL;
908         MFace *mface;
909         MSticky *ms;
910         KeyBlock *actkey=NULL, *currkey;
911         EditVert *eve;
912         EditFace *efa;
913         EditEdge *eed;
914         float *fp, *newkey, *oldkey, nor[3];
915         int i, a, ototvert, totedge=0;
916         MDeformVert *dvert;
917         int     usedDvert = 0;
918
919         waitcursor(1);
920         countall();
921
922         /* this one also tests of edges are not in faces: */
923         /* eed->f2==0: not in face, f2==1: draw it */
924         /* eed->f1 : flag for dynaface (cylindertest, old engine) */
925         /* eve->f1 : flag for dynaface (sphere test, old engine) */
926         edge_drawflags();
927         
928         /* this sets efa->puno, punoflag (for vertex normal & projection) */
929         vertexnormals( (me->flag & ME_NOPUNOFLIP)==0 );
930                 
931         eed= em->edges.first;
932         while(eed) {
933                 totedge++;
934                 if(me->medge==NULL && (eed->f2==0)) G.totface++;
935                 eed= eed->next;
936         }
937         
938         /* new Vertex block */
939         if(G.totvert==0) mvert= NULL;
940         else mvert= MEM_callocN(G.totvert*sizeof(MVert), "loadeditMesh vert");
941
942         /* new Edge block */
943         if(totedge) {
944                 if(me->medge==NULL) totedge= 0; // if edges get added is defined by orig mesh
945                 else medge= MEM_callocN(totedge*sizeof(MEdge), "loadeditMesh edge");
946         }
947         
948         /* new Face block */
949         if(G.totface==0) mface= NULL;
950         else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh face");
951         
952
953         if (G.totvert==0) dvert= NULL;
954         else dvert = MEM_callocN(G.totvert*sizeof(MDeformVert), "loadeditMesh3");
955
956         if (me->dvert) free_dverts(me->dvert, me->totvert);
957         me->dvert=dvert;
958
959         /* lets save the old verts just in case we are actually working on
960          * a key ... we now do processing of the keys at the end */
961         oldverts = me->mvert;
962         ototvert= me->totvert;
963
964         /* put new data in Mesh */
965         me->mvert= mvert;
966         me->totvert= G.totvert;
967
968         if(me->medge) MEM_freeN(me->medge);
969         me->medge= medge;
970         if(medge) me->totedge= totedge; else me->totedge= 0;
971         
972         if(me->mface) MEM_freeN(me->mface);
973         me->mface= mface;
974         me->totface= G.totface;
975                 
976         /* the vertices, abuse ->vn as counter */
977         eve= em->verts.first;
978         a= 0;
979
980         while(eve) {
981                 VECCOPY(mvert->co, eve->co);
982                 mvert->mat_nr= 255;  /* what was this for, halos? */
983                 
984                 /* vertex normal */
985                 VECCOPY(nor, eve->no);
986                 VecMulf(nor, 32767.0);
987                 VECCOPY(mvert->no, nor);
988
989                 /* NEW VERSION */
990                 if (dvert){
991                         dvert->totweight=eve->totweight;
992                         if (eve->dw){
993                                 dvert->dw = MEM_callocN (sizeof(MDeformWeight)*eve->totweight,
994                                                                                  "deformWeight");
995                                 memcpy (dvert->dw, eve->dw, 
996                                                 sizeof(MDeformWeight)*eve->totweight);
997                                 usedDvert++;
998                         }
999                 }
1000
1001                 eve->vn= (EditVert *)(long)(a++);  /* counter */
1002                         
1003                 mvert->flag= 0;
1004                 if(eve->f1==1) mvert->flag |= ME_SPHERETEST;
1005                 mvert->flag |= (eve->f & SELECT);
1006                 if (eve->h) mvert->flag |= ME_HIDE;                     
1007                         
1008                 eve= eve->next;
1009                 mvert++;
1010                 dvert++;
1011         }
1012         
1013         /* If we didn't actually need the dverts, get rid of them */
1014         if (!usedDvert){
1015                 free_dverts(me->dvert, G.totvert);
1016                 me->dvert=NULL;
1017         }
1018
1019         /* the edges */
1020         if(medge) {
1021                 eed= em->edges.first;
1022                 while(eed) {
1023                         medge->v1= (unsigned int) eed->v1->vn;
1024                         medge->v2= (unsigned int) eed->v2->vn;
1025                         
1026                         medge->flag= eed->f & SELECT;
1027                         if(eed->f2<2) medge->flag |= ME_EDGEDRAW;
1028                         if(eed->seam) medge->flag |= ME_SEAM;
1029                         if(eed->h & EM_FGON) medge->flag |= ME_FGON;    // different defines yes
1030                         if(eed->h & 1) medge->flag |= ME_HIDE;
1031                         
1032                         medge->crease= (char)(255.0*eed->crease);
1033
1034                         medge++;
1035                         eed= eed->next;
1036                 }
1037         }
1038
1039         /* the faces */
1040         efa= em->faces.first;
1041         i = 0;
1042         while(efa) {
1043                 mface= &((MFace *) me->mface)[i];
1044                 
1045                 mface->v1= (unsigned int) efa->v1->vn;
1046                 mface->v2= (unsigned int) efa->v2->vn;
1047                 mface->v3= (unsigned int) efa->v3->vn;
1048                 if(efa->v4) mface->v4= (unsigned int) efa->v4->vn;
1049                         
1050                 mface->mat_nr= efa->mat_nr;
1051                 mface->puno= efa->puno;
1052                 
1053                 mface->flag= efa->flag;
1054                 /* bit 0 of flag is already taken for smooth... */
1055                 if(efa->f & 1) mface->flag |= ME_FACE_SEL;
1056                 else mface->flag &= ~ME_FACE_SEL;
1057                 if(efa->h) mface->flag |= ME_HIDE;
1058                 
1059                 /* mat_nr in vertex */
1060                 if(me->totcol>1) {
1061                         mvert= me->mvert+mface->v1;
1062                         if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
1063                         mvert= me->mvert+mface->v2;
1064                         if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
1065                         mvert= me->mvert+mface->v3;
1066                         if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
1067                         if(mface->v4) {
1068                                 mvert= me->mvert+mface->v4;
1069                                 if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
1070                         }
1071                 }
1072                         
1073                 /* watch: efa->e1->f2==0 means loose edge */ 
1074                         
1075                 if(efa->e1->f2==1) {
1076                         mface->edcode |= ME_V1V2; 
1077                         efa->e1->f2= 2;
1078                 }                       
1079                 if(efa->e2->f2==1) {
1080                         mface->edcode |= ME_V2V3; 
1081                         efa->e2->f2= 2;
1082                 }
1083                 if(efa->e3->f2==1) {
1084                         if(efa->v4) {
1085                                 mface->edcode |= ME_V3V4;
1086                         }
1087                         else {
1088                                 mface->edcode |= ME_V3V1;
1089                         }
1090                         efa->e3->f2= 2;
1091                 }
1092                 if(efa->e4 && efa->e4->f2==1) {
1093                         mface->edcode |= ME_V4V1; 
1094                         efa->e4->f2= 2;
1095                 }
1096
1097
1098                 /* no index '0' at location 3 or 4 */
1099                 if(efa->v4) fix_faceindices(mface, efa, 4);
1100                 else fix_faceindices(mface, efa, 3);
1101                         
1102                 i++;
1103                 efa= efa->next;
1104         }
1105                 
1106         /* add loose edges as a face */
1107         if(medge==NULL) {
1108                 eed= em->edges.first;
1109                 while(eed) {
1110                         if( eed->f2==0 ) {
1111                                 mface= &((MFace *) me->mface)[i];
1112                                 mface->v1= (unsigned int) eed->v1->vn;
1113                                 mface->v2= (unsigned int) eed->v2->vn;
1114                                 test_index_mface(mface, 2);
1115                                 mface->edcode= ME_V1V2;
1116                                 i++;
1117                         }
1118                         eed= eed->next;
1119                 }
1120         }
1121         
1122         tex_space_mesh(me);
1123
1124         /* tface block */
1125         if( me->tface && me->totface ) {
1126                 TFace *tfn, *tf;
1127                         
1128                 tf=tfn= MEM_callocN(sizeof(TFace)*me->totface, "tface");
1129                 efa= em->faces.first;
1130                 while(efa) {
1131                                 
1132                         *tf= efa->tf;
1133                                 
1134                         if(G.f & G_FACESELECT) {
1135                                 if( efa->f & SELECT)  tf->flag |= TF_SELECT;
1136                                 else tf->flag &= ~TF_SELECT;
1137                         }
1138                                 
1139                         tf++;
1140                         efa= efa->next;
1141                 }
1142
1143                 if(me->tface) MEM_freeN(me->tface);
1144                 me->tface= tfn;
1145         }
1146         else if(me->tface) {
1147                 MEM_freeN(me->tface);
1148                 me->tface= NULL;
1149         }
1150                 
1151         /* mcol: same as tface... */
1152         if(me->mcol && me->totface) {
1153                 unsigned int *mcn, *mc;
1154
1155                 mc=mcn= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
1156                 efa= em->faces.first;
1157                 while(efa) {
1158                         memcpy(mc, efa->tf.col, 4*sizeof(int));
1159                                 
1160                         mc+=4;
1161                         efa= efa->next;
1162                 }
1163                 if(me->mcol) MEM_freeN(me->mcol);
1164                         me->mcol= (MCol *)mcn;
1165         }
1166         else if(me->mcol) {
1167                 MEM_freeN(me->mcol);
1168                 me->mcol= 0;
1169         }
1170
1171
1172         /* are there keys? */
1173         if(me->key) {
1174
1175                 /* find the active key */
1176                 actkey= me->key->block.first;
1177                 while(actkey) {
1178                         if(actkey->flag & SELECT) break;
1179                         actkey= actkey->next;
1180                 }
1181
1182                 /* Lets reorder the key data so that things line up roughly
1183                  * with the way things were before editmode */
1184                 currkey = me->key->block.first;
1185                 while(currkey) {
1186                         
1187                         fp= newkey= MEM_callocN(me->key->elemsize*G.totvert,  "currkey->data");
1188                         oldkey = currkey->data;
1189
1190                         eve= em->verts.first;
1191
1192                         i = 0;
1193                         mvert = me->mvert;
1194                         while(eve) {
1195                                 if (eve->keyindex >= 0) { // old vertex
1196                                         if(currkey == actkey) {
1197                                                 if (actkey == me->key->refkey) {
1198                                                         VECCOPY(fp, mvert->co);
1199                                                 }
1200                                                 else {
1201                                                         VECCOPY(fp, mvert->co);
1202                                                         if(oldverts) {
1203                                                                 VECCOPY(mvert->co, oldverts[eve->keyindex].co);
1204                                                         }
1205                                                 }
1206                                         }
1207                                         else {
1208                                                 if(oldkey) {
1209                                                         VECCOPY(fp, oldkey + 3 * eve->keyindex);
1210                                                 }
1211                                         }
1212                                 }
1213                                 else {
1214                                         VECCOPY(fp, mvert->co);
1215                                 }
1216                                 fp+= 3;
1217                                 ++i;
1218                                 ++mvert;
1219                                 eve= eve->next;
1220                         }
1221                         currkey->totelem= G.totvert;
1222                         if(currkey->data) MEM_freeN(currkey->data);
1223                         currkey->data = newkey;
1224                         
1225                         currkey= currkey->next;
1226                 }
1227
1228         }
1229
1230         if(oldverts) MEM_freeN(oldverts);
1231
1232         if(actkey) do_spec_key(me->key);
1233         
1234         /* te be sure: clear ->vn pointers */
1235         eve= em->verts.first;
1236         while(eve) {
1237                 eve->vn= 0;
1238                 eve= eve->next;
1239         }
1240
1241         /* displists of all users, including this one */
1242         freedisplist(&me->disp);
1243         freedisplist(&G.obedit->disp);
1244         
1245         /* sticky */
1246         if(me->msticky) {
1247                 if (ototvert<me->totvert) {
1248                         ms= MEM_callocN(me->totvert*sizeof(MSticky), "msticky");
1249                         memcpy(ms, me->msticky, ototvert*sizeof(MSticky));
1250                         MEM_freeN(me->msticky);
1251                         me->msticky= ms;
1252                         error("Sticky was too small");
1253                 }
1254         }
1255         waitcursor(0);
1256 }
1257
1258 void remake_editMesh(void)
1259 {
1260         make_editMesh();
1261         allqueue(REDRAWVIEW3D, 0);
1262         makeDispList(G.obedit);
1263         BIF_undo_push("Undo all changes");
1264 }
1265
1266 /* *************** SEPARATE (partial exit editmode) *************/
1267
1268
1269 void separatemenu(void)
1270 {
1271         short event;
1272
1273         if(G.editMesh->verts.first==NULL) return;
1274            
1275         event = pupmenu("Separate (No undo!) %t|Selected%x1|All Loose Parts%x2");
1276         
1277         if (event==0) return;
1278         waitcursor(1);
1279         
1280         switch (event) {
1281         case 1: 
1282                 separate_mesh();                    
1283                 break;
1284         case 2:                     
1285                 separate_mesh_loose();              
1286                 break;
1287         }
1288         waitcursor(0);
1289 }
1290
1291
1292 void separate_mesh(void)
1293 {
1294         EditMesh *em = G.editMesh;
1295         EditMesh emcopy;
1296         EditVert *eve, *v1;
1297         EditEdge *eed, *e1;
1298         EditFace *efa, *vl1;
1299         Object *oldob;
1300         Mesh *me, *men;
1301         Base *base, *oldbase;
1302         ListBase edve, eded, edvl;
1303         float trans[9];
1304         int ok, flag;
1305         
1306         TEST_EDITMESH   
1307
1308         waitcursor(1);
1309         
1310         me= get_mesh(G.obedit);
1311         if(me->key) {
1312                 error("Can't separate with vertex keys");
1313                 return;
1314         }
1315         
1316         EM_selectmode_set();    // enforce full consistant selection flags 
1317         
1318         /* we are going to abuse the system as follows:
1319          * 1. add a duplicate object: this will be the new one, we remember old pointer
1320          * 2: then do a split if needed.
1321          * 3. put apart: all NOT selected verts, edges, faces
1322          * 4. call load_editMesh(): this will be the new object
1323          * 5. freelist and get back old verts, edges, facs
1324          */
1325         
1326         /* make only obedit selected */
1327         base= FIRSTBASE;
1328         while(base) {
1329                 if(base->lay & G.vd->lay) {
1330                         if(base->object==G.obedit) base->flag |= SELECT;
1331                         else base->flag &= ~SELECT;
1332                 }
1333                 base= base->next;
1334         }
1335         
1336         /* test for split */
1337         ok= 0;
1338         eed= em->edges.first;
1339         while(eed) {
1340                 flag= (eed->v1->f & SELECT)+(eed->v2->f & SELECT);
1341                 if(flag==SELECT) {
1342                         ok= 1;
1343                         break;
1344                 }
1345                 eed= eed->next;
1346         }
1347         if(ok) {
1348                 /* SPLIT: first make duplicate */
1349                 adduplicateflag(SELECT);
1350                 /* SPLIT: old faces have 3x flag 128 set, delete these ones */
1351                 delfaceflag(128);
1352         }
1353         
1354         /* set apart: everything that is not selected */
1355         edve.first= edve.last= eded.first= eded.last= edvl.first= edvl.last= 0;
1356         eve= em->verts.first;
1357         while(eve) {
1358                 v1= eve->next;
1359                 if((eve->f & SELECT)==0) {
1360                         BLI_remlink(&em->verts, eve);
1361                         BLI_addtail(&edve, eve);
1362                 }
1363                 eve= v1;
1364         }
1365         eed= em->edges.first;
1366         while(eed) {
1367                 e1= eed->next;
1368                 if((eed->f & SELECT)==0) {
1369                         BLI_remlink(&em->edges, eed);
1370                         BLI_addtail(&eded, eed);
1371                 }
1372                 eed= e1;
1373         }
1374         efa= em->faces.first;
1375         while(efa) {
1376                 vl1= efa->next;
1377                 if((efa->f & SELECT)==0) {
1378                         BLI_remlink(&em->faces, efa);
1379                         BLI_addtail(&edvl, efa);
1380                 }
1381                 efa= vl1;
1382         }
1383         
1384         oldob= G.obedit;
1385         oldbase= BASACT;
1386         
1387         trans[0]=trans[1]=trans[2]=trans[3]=trans[4]=trans[5]= 0.0;
1388         trans[6]=trans[7]=trans[8]= 1.0;
1389         G.qual |= LR_ALTKEY;    /* patch to make sure we get a linked duplicate */
1390         adduplicate(trans);
1391         G.qual &= ~LR_ALTKEY;
1392         
1393         G.obedit= BASACT->object;       /* basact was set in adduplicate()  */
1394
1395         men= copy_mesh(me);
1396         set_mesh(G.obedit, men);
1397         /* because new mesh is a copy: reduce user count */
1398         men->id.us--;
1399         
1400         load_editMesh();
1401         
1402         BASACT->flag &= ~SELECT;
1403         
1404         /* we cannot free the original buffer... */
1405         emcopy= *G.editMesh;
1406         emcopy.allverts= NULL;
1407         emcopy.alledges= NULL;
1408         emcopy.allfaces= NULL;
1409         free_editMesh(&emcopy);
1410         
1411         em->verts= edve;
1412         em->edges= eded;
1413         em->faces= edvl;
1414         
1415         /* hashedges are freed now, make new! */
1416         editMesh_set_hash();
1417         
1418         G.obedit= oldob;
1419         BASACT= oldbase;
1420         BASACT->flag |= SELECT;
1421         
1422         waitcursor(0);
1423
1424         countall();
1425         allqueue(REDRAWVIEW3D, 0);
1426         makeDispList(G.obedit);
1427
1428 }
1429
1430 void separate_mesh_loose(void)
1431 {
1432         EditMesh *em = G.editMesh;
1433         EditMesh emcopy;
1434         EditVert *eve, *v1;
1435         EditEdge *eed, *e1;
1436         EditFace *efa, *vl1;
1437         Object *oldob;
1438         Mesh *me, *men;
1439         Base *base, *oldbase;
1440         ListBase edve, eded, edvl;
1441         float trans[9];
1442         int ok, vertsep=0, flag;        
1443         short done=0, check=1;
1444                 
1445         TEST_EDITMESH
1446         waitcursor(1);  
1447         
1448         /* we are going to abuse the system as follows:
1449          * 1. add a duplicate object: this will be the new one, we remember old pointer
1450          * 2: then do a split if needed.
1451          * 3. put apart: all NOT selected verts, edges, faces
1452          * 4. call load_editMesh(): this will be the new object
1453          * 5. freelist and get back old verts, edges, facs
1454          */
1455                         
1456         
1457                         
1458         while(!done){           
1459                 vertsep=check=1;
1460                 
1461                 countall();
1462                 
1463                 me= get_mesh(G.obedit);
1464                 if(me->key) {
1465                         error("Can't separate a mesh with vertex keys");
1466                         return;
1467                 }               
1468                 
1469                 /* make only obedit selected */
1470                 base= FIRSTBASE;
1471                 while(base) {
1472                         if(base->lay & G.vd->lay) {
1473                                 if(base->object==G.obedit) base->flag |= SELECT;
1474                                 else base->flag &= ~SELECT;
1475                         }
1476                         base= base->next;
1477                 }               
1478                 
1479                 /*--------- Select connected-----------*/               
1480                 
1481                 EM_clear_flag_all(SELECT);
1482
1483                 /* Select a random vert to start with */
1484                 eve= em->verts.first;
1485                 eve->f |= SELECT;
1486                 
1487                 while(check==1) {
1488                         check= 0;                       
1489                         eed= em->edges.first;                   
1490                         while(eed) {                            
1491                                 if(eed->h==0) {
1492                                         if(eed->v1->f & SELECT) {
1493                                                 if( (eed->v2->f & SELECT)==0 ) {
1494                                                         eed->v2->f |= SELECT;
1495                                                         vertsep++;
1496                                                         check= 1;
1497                                                 }
1498                                         }
1499                                         else if(eed->v2->f & SELECT) {
1500                                                 if( (eed->v1->f & SELECT)==0 ) {
1501                                                         eed->v1->f |= SELECT;
1502                                                         vertsep++;
1503                                                         check= SELECT;
1504                                                 }
1505                                         }
1506                                 }
1507                                 eed= eed->next;                         
1508                         }
1509                 }               
1510                 /*----------End of select connected--------*/
1511                 
1512                 
1513                 /* If the amount of vertices that is about to be split == the total amount 
1514                    of verts in the mesh, it means that there is only 1 unconnected object, so we don't have to separate
1515                 */
1516                 if(G.totvert==vertsep) done=1;                          
1517                 else{                   
1518                         /* Test for splitting: Separate selected */
1519                         ok= 0;
1520                         eed= em->edges.first;
1521                         while(eed) {
1522                                 flag= (eed->v1->f & SELECT)+(eed->v2->f & SELECT);
1523                                 if(flag==SELECT) {
1524                                         ok= 1;
1525                                         break;
1526                                 }
1527                                 eed= eed->next;
1528                         }
1529                         if(ok) {
1530                                 /* SPLIT: first make duplicate */
1531                                 adduplicateflag(SELECT);
1532                                 /* SPLIT: old faces have 3x flag 128 set, delete these ones */
1533                                 delfaceflag(128);
1534                         }       
1535                         
1536                         EM_select_flush();      // from verts->edges->faces
1537
1538                         /* set apart: everything that is not selected */
1539                         edve.first= edve.last= eded.first= eded.last= edvl.first= edvl.last= 0;
1540                         eve= em->verts.first;
1541                         while(eve) {
1542                                 v1= eve->next;
1543                                 if((eve->f & SELECT)==0) {
1544                                         BLI_remlink(&em->verts, eve);
1545                                         BLI_addtail(&edve, eve);
1546                                 }
1547                                 eve= v1;
1548                         }
1549                         eed= em->edges.first;
1550                         while(eed) {
1551                                 e1= eed->next;
1552                                 if( (eed->f & SELECT)==0 ) {
1553                                         BLI_remlink(&em->edges, eed);
1554                                         BLI_addtail(&eded, eed);
1555                                 }
1556                                 eed= e1;
1557                         }
1558                         efa= em->faces.first;
1559                         while(efa) {
1560                                 vl1= efa->next;
1561                                 if( (efa->f & SELECT)==0 ) {
1562                                         BLI_remlink(&em->faces, efa);
1563                                         BLI_addtail(&edvl, efa);
1564                                 }
1565                                 efa= vl1;
1566                         }
1567                         
1568                         oldob= G.obedit;
1569                         oldbase= BASACT;
1570                         
1571                         trans[0]=trans[1]=trans[2]=trans[3]=trans[4]=trans[5]= 0.0;
1572                         trans[6]=trans[7]=trans[8]= 1.0;
1573                         G.qual |= LR_ALTKEY;    /* patch to make sure we get a linked duplicate */
1574                         adduplicate(trans);
1575                         G.qual &= ~LR_ALTKEY;
1576                         
1577                         G.obedit= BASACT->object;       /* basact was set in adduplicate()  */
1578                 
1579                         men= copy_mesh(me);
1580                         set_mesh(G.obedit, men);
1581                         /* because new mesh is a copy: reduce user count */
1582                         men->id.us--;
1583                         
1584                         load_editMesh();
1585                         
1586                         BASACT->flag &= ~SELECT;
1587                         
1588                         /* we cannot free the original buffer... */
1589                         emcopy= *G.editMesh;
1590                         emcopy.allverts= NULL;
1591                         emcopy.alledges= NULL;
1592                         emcopy.allfaces= NULL;
1593                         free_editMesh(&emcopy);
1594                         
1595                         em->verts= edve;
1596                         em->edges= eded;
1597                         em->faces= edvl;
1598                         
1599                         /* hashedges are freed now, make new! */
1600                         editMesh_set_hash();
1601                         
1602                         G.obedit= oldob;
1603                         BASACT= oldbase;
1604                         BASACT->flag |= SELECT; 
1605                                         
1606                 }               
1607         }
1608         
1609         /* unselect the vertices that we (ab)used for the separation*/
1610         EM_clear_flag_all(SELECT);
1611                 
1612         waitcursor(0);
1613         countall();
1614         allqueue(REDRAWVIEW3D, 0);
1615         makeDispList(G.obedit); 
1616 }
1617
1618 /* ******************************************** */
1619
1620 /* *************** UNDO ***************************** */
1621 /* new mesh undo, based on pushing editmesh data itself */
1622 /* reuses same code as for global and curve undo... unify that (ton) */
1623
1624 /* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */
1625
1626 /* a compressed version of editmesh data */
1627 typedef struct EditVertC
1628 {
1629         float no[3];
1630         float co[3];
1631         unsigned char f, h;
1632         short totweight;
1633         struct MDeformWeight *dw;
1634         int keyindex; 
1635 } EditVertC;
1636
1637 typedef struct EditEdgeC
1638 {
1639         int v1, v2;
1640         unsigned char f, h, seam, pad;
1641         short crease, fgoni;
1642 } EditEdgeC;
1643
1644 typedef struct EditFaceC
1645 {
1646         int v1, v2, v3, v4;
1647         unsigned char mat_nr, flag, f, h, puno, fgonf;
1648         short pad1;
1649 } EditFaceC;
1650
1651 typedef struct UndoMesh {
1652         EditVertC *verts;
1653         EditEdgeC *edges;
1654         EditFaceC *faces;
1655         TFace *tfaces;
1656         int totvert, totedge, totface;
1657 } UndoMesh;
1658
1659
1660 /* for callbacks */
1661
1662 static void free_undoMesh(void *umv)
1663 {
1664         UndoMesh *um= umv;
1665         EditVertC *evec;
1666         int a;
1667         
1668         for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
1669                 if(evec->dw) MEM_freeN(evec->dw);
1670         }
1671         
1672         if(um->verts) MEM_freeN(um->verts);
1673         if(um->edges) MEM_freeN(um->edges);
1674         if(um->faces) MEM_freeN(um->faces);
1675         if(um->tfaces) MEM_freeN(um->tfaces);
1676         MEM_freeN(um);
1677 }
1678
1679 static void *editMesh_to_undoMesh(void)
1680 {
1681         EditMesh *em= G.editMesh;
1682         UndoMesh *um;
1683         Mesh *me= G.obedit->data;
1684         EditVert *eve;
1685         EditEdge *eed;
1686         EditFace *efa;
1687         EditVertC *evec=NULL;
1688         EditEdgeC *eedc=NULL;
1689         EditFaceC *efac=NULL;
1690         TFace *tface= NULL;
1691         int a=0;
1692         
1693         um= MEM_callocN(sizeof(UndoMesh), "undomesh");
1694
1695         for(eve=em->verts.first; eve; eve= eve->next) um->totvert++;
1696         for(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
1697         for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
1698
1699         /* malloc blocks */
1700         
1701         if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC");
1702         if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
1703         if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
1704
1705         if(me->tface) tface= um->tfaces= MEM_mallocN(um->totface*sizeof(TFace), "all tfacesC");
1706
1707                 //printf("copy editmesh %d\n", um->totvert*sizeof(EditVert) + um->totedge*sizeof(EditEdge) + um->totface*sizeof(EditFace));
1708                 //printf("copy undomesh %d\n", um->totvert*sizeof(EditVertC) + um->totedge*sizeof(EditEdgeC) + um->totface*sizeof(EditFaceC));
1709         
1710         /* now copy vertices */
1711         for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
1712                 VECCOPY(evec->co, eve->co);
1713                 VECCOPY(evec->no, eve->no);
1714
1715                 evec->f= eve->f;
1716                 evec->h= eve->h;
1717                 evec->keyindex= eve->keyindex;
1718                 evec->totweight= eve->totweight;
1719                 evec->dw= MEM_dupallocN(eve->dw);
1720                 
1721                 eve->vn= (EditVert *)a;
1722         }
1723         
1724         /* copy edges */
1725         for(eed=em->edges.first; eed; eed= eed->next, eedc++)  {
1726                 eedc->v1= (int)eed->v1->vn;
1727                 eedc->v2= (int)eed->v2->vn;
1728                 eedc->f= eed->f;
1729                 eedc->h= eed->h;
1730                 eedc->seam= eed->seam;
1731                 eedc->crease= (short)(eed->crease*255.0);
1732                 eedc->fgoni= eed->fgoni;
1733         }
1734         
1735         /* copy faces */
1736         for(efa=em->faces.first; efa; efa= efa->next, efac++) {
1737                 efac->v1= (int)efa->v1->vn;
1738                 efac->v2= (int)efa->v2->vn;
1739                 efac->v3= (int)efa->v3->vn;
1740                 if(efa->v4) efac->v4= (int)efa->v4->vn;
1741                 else efac->v4= -1;
1742                 
1743                 efac->mat_nr= efa->mat_nr;
1744                 efac->flag= efa->flag;
1745                 efac->f= efa->f;
1746                 efac->h= efa->h;
1747                 efac->puno= efa->puno;
1748                 efac->fgonf= efa->fgonf;
1749                 
1750                 if(tface) {
1751                         *tface= efa->tf;
1752                         tface++;
1753                 }
1754         }
1755         
1756         return um;
1757 }
1758
1759 static void undoMesh_to_editMesh(void *umv)
1760 {
1761         UndoMesh *um= umv;
1762         EditMesh *em= G.editMesh;
1763         EditVert *eve, **evar=NULL;
1764         EditEdge *eed;
1765         EditFace *efa;
1766         EditVertC *evec;
1767         EditEdgeC *eedc;
1768         EditFaceC *efac;
1769         TFace *tface;
1770         int a=0;
1771         
1772         free_editMesh(G.editMesh);
1773         
1774         /* malloc blocks */
1775         memset(em, 0, sizeof(EditMesh));
1776
1777         init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);
1778
1779         /* now copy vertices */
1780         if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar");
1781         for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
1782                 eve= addvertlist(evec->co);
1783                 evar[a]= eve;
1784
1785                 VECCOPY(eve->no, evec->no);
1786                 eve->f= evec->f;
1787                 eve->h= evec->h;
1788                 eve->totweight= evec->totweight;
1789                 eve->keyindex= evec->keyindex;
1790                 eve->dw= MEM_dupallocN(evec->dw);
1791         }
1792
1793         /* copy edges */
1794         for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) {
1795                 eed= addedgelist(evar[eedc->v1], evar[eedc->v2], NULL);
1796
1797                 eed->f= eedc->f;
1798                 eed->h= eedc->h;
1799                 eed->seam= eedc->seam;
1800                 eed->fgoni= eedc->fgoni;
1801                 eed->crease= ((float)eedc->crease)/255.0;
1802         }
1803         
1804         /* copy faces */
1805         tface= um->tfaces;
1806         for(a=0, efac= um->faces; a<um->totface; a++, efac++) {
1807                 if(efac->v4 != -1)
1808                         efa= addfacelist(evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL);
1809                 else 
1810                         efa= addfacelist(evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL);
1811
1812                 efa->mat_nr= efac->mat_nr;
1813                 efa->flag= efac->flag;
1814                 efa->f= efac->f;
1815                 efa->h= efac->h;
1816                 efa->puno= efac->puno;
1817                 efa->fgonf= efac->fgonf;
1818                 
1819                 if(tface) {
1820                         efa->tf= *tface;
1821                         tface++;
1822                 }
1823         }
1824         
1825         end_editmesh_fastmalloc();
1826         if(evar) MEM_freeN(evar);
1827 }
1828
1829
1830 /* and this is all the undo system needs to know */
1831 void undo_push_mesh(char *name)
1832 {
1833         undo_editmode_push(name, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh);
1834 }
1835
1836
1837
1838 /* *************** END UNDO *************/
1839
1840