svn merge -r40000:40179 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender-staging.git] / source / blender / editors / mesh / editmesh.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, full recode 2002-2008
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/mesh/editmesh.c
29  *  \ingroup edmesh
30  */
31
32
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_scene_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_key_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_modifier_types.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_math.h"
48 #include "BLI_editVert.h"
49 #include "BLI_dynstr.h"
50 #include "BLI_rand.h"
51 #include "BLI_utildefines.h"
52
53 #include "BKE_DerivedMesh.h"
54 #include "BKE_context.h"
55 #include "BKE_depsgraph.h"
56 #include "BKE_global.h"
57 #include "BKE_key.h"
58 #include "BKE_main.h"
59 #include "BKE_material.h"
60 #include "BKE_mesh.h"
61 #include "BKE_paint.h"
62 #include "BKE_report.h"
63 #include "BKE_multires.h"
64
65 #include "ED_mesh.h"
66 #include "ED_object.h"
67 #include "ED_screen.h"
68 #include "ED_util.h"
69 #include "ED_view3d.h"
70
71 #include "RNA_access.h"
72 #include "RNA_define.h"
73
74 #include "WM_api.h"
75 #include "WM_types.h"
76
77 /* own include */
78 #include "mesh_intern.h"
79
80 /* 
81 editmesh.c:
82         - add/alloc/free data
83         - hashtables
84         - enter/exit editmode
85 */
86
87 /* XXX */
88 static void BIF_undo_push(const char *UNUSED(arg)) {}
89 static void error(const char *UNUSED(arg)) {}
90
91
92 /* ***************** HASH ********************* */
93
94
95 #define EDHASHSIZE              (512*512)
96 #define EDHASH(a, b)    (a % EDHASHSIZE)
97
98
99 /* ************ ADD / REMOVE / FIND ****************** */
100
101 static void *calloc_em(EditMesh *UNUSED(em), size_t size, size_t nr)
102 {
103         return calloc(size, nr);
104 }
105
106 /* used to bypass normal calloc with fast one */
107 static void *(*callocvert)(EditMesh *, size_t, size_t) = calloc_em;
108 static void *(*callocedge)(EditMesh *, size_t, size_t) = calloc_em;
109 static void *(*callocface)(EditMesh *, size_t, size_t) = calloc_em;
110
111 EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example)
112 {
113         EditVert *eve;
114         static int hashnr= 0;
115
116         eve= callocvert(em, sizeof(EditVert), 1);
117         BLI_addtail(&em->verts, eve);
118         em->totvert++;
119         
120         if(vec) VECCOPY(eve->co, vec);
121
122         eve->hash= hashnr++;
123         if( hashnr>=EDHASHSIZE) hashnr= 0;
124
125         /* new verts get keyindex of -1 since they did not
126          * have a pre-editmode vertex order
127          */
128         eve->keyindex = -1;
129
130         if(example) {
131                 CustomData_em_copy_data(&em->vdata, &em->vdata, example->data, &eve->data);
132                 eve->bweight = example->bweight;
133         }
134         else {
135                 CustomData_em_set_default(&em->vdata, &eve->data);
136         }
137
138         return eve;
139 }
140
141 void free_editvert (EditMesh *em, EditVert *eve)
142 {
143
144         EM_remove_selection(em, eve, EDITVERT);
145         CustomData_em_free_block(&em->vdata, &eve->data);
146         if(eve->fast==0)
147                 free(eve);
148         
149         em->totvert--;
150 }
151
152
153 EditEdge *findedgelist(EditMesh *em, EditVert *v1, EditVert *v2)
154 {
155         EditVert *v3;
156         struct HashEdge *he;
157
158         /* swap ? */
159         if( v1 > v2) {
160                 v3= v2; 
161                 v2= v1; 
162                 v1= v3;
163         }
164         
165         if(em->hashedgetab==NULL)
166                 em->hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab");
167
168         he= em->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(EditMesh *em, 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= em->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(EditMesh *em, EditEdge *eed)
199 {
200         /* assuming eed is in the list */
201         
202         struct HashEdge *first, *he, *prev=NULL;
203
204         he=first= em->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(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *example)
228 {
229         EditVert *v3;
230         EditEdge *eed;
231         int swap= 0;
232         
233         if(v1==v2) return NULL;
234         if(v1==NULL || v2==NULL) return NULL;
235
236         /* swap ? */
237         if(v1>v2) {
238                 v3= v2; 
239                 v2= v1; 
240                 v1= v3;
241                 swap= 1;
242         }
243         
244         /* find in hashlist */
245         eed= findedgelist(em, v1, v2);
246
247         if(eed==NULL) {
248         
249                 eed= (EditEdge *)callocedge(em, sizeof(EditEdge), 1);
250                 eed->v1= v1;
251                 eed->v2= v2;
252                 BLI_addtail(&em->edges, eed);
253                 eed->dir= swap;
254                 insert_hashedge(em, eed);
255                 em->totedge++;
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->bweight= example->bweight;
262                         eed->sharp = example->sharp;
263                         eed->seam = example->seam;
264                         eed->h |= (example->h & EM_FGON);
265                 }
266         }
267         
268         return eed;
269 }
270
271 void remedge(EditMesh *em, EditEdge *eed)
272 {
273         BLI_remlink(&em->edges, eed);
274         remove_hashedge(em, eed);
275         
276         em->totedge--;
277 }
278
279 void free_editedge(EditMesh *em, EditEdge *eed)
280 {
281         EM_remove_selection(em, eed, EDITEDGE);
282         if(eed->fast==0){ 
283                 free(eed);
284         }
285 }
286
287 void free_editface(EditMesh *em, EditFace *efa)
288 {
289         EM_remove_selection(em, efa, EDITFACE);
290         
291         if (em->act_face==efa) {
292                 EM_set_actFace(em, em->faces.first == efa ? NULL : em->faces.first);
293         }
294                 
295         CustomData_em_free_block(&em->fdata, &efa->data);
296         if(efa->fast==0)
297                 free(efa);
298         
299         em->totface--;
300 }
301
302 void free_vertlist(EditMesh *em, ListBase *edve) 
303 {
304         EditVert *eve, *next;
305
306         if (!edve) return;
307
308         eve= edve->first;
309         while(eve) {
310                 next= eve->next;
311                 free_editvert(em, eve);
312                 eve= next;
313         }
314         edve->first= edve->last= NULL;
315         em->totvert= em->totvertsel= 0;
316 }
317
318 void free_edgelist(EditMesh *em, ListBase *lb)
319 {
320         EditEdge *eed, *next;
321         
322         eed= lb->first;
323         while(eed) {
324                 next= eed->next;
325                 free_editedge(em, eed);
326                 eed= next;
327         }
328         lb->first= lb->last= NULL;
329         em->totedge= em->totedgesel= 0;
330 }
331
332 void free_facelist(EditMesh *em, ListBase *lb)
333 {
334         EditFace *efa, *next;
335         
336         efa= lb->first;
337         while(efa) {
338                 next= efa->next;
339                 free_editface(em, efa);
340                 efa= next;
341         }
342         lb->first= lb->last= NULL;
343         em->totface= em->totfacesel= 0;
344 }
345
346 EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditFace *example, EditFace *exampleEdges)
347 {
348         EditFace *efa;
349         EditEdge *e1, *e2=0, *e3=0, *e4=0;
350
351         /* added sanity check... seems to happen for some tools, or for enter editmode for corrupted meshes */
352         if(v1==v4 || v2==v4 || v3==v4) v4= NULL;
353         
354         /* add face to list and do the edges */
355         if(exampleEdges) {
356                 e1= addedgelist(em, v1, v2, exampleEdges->e1);
357                 e2= addedgelist(em, v2, v3, exampleEdges->e2);
358                 if(v4) e3= addedgelist(em, v3, v4, exampleEdges->e3); 
359                 else e3= addedgelist(em, v3, v1, exampleEdges->e3);
360                 if(v4) e4= addedgelist(em, v4, v1, exampleEdges->e4);
361         }
362         else {
363                 e1= addedgelist(em, v1, v2, NULL);
364                 e2= addedgelist(em, v2, v3, NULL);
365                 if(v4) e3= addedgelist(em, v3, v4, NULL); 
366                 else e3= addedgelist(em, v3, v1, NULL);
367                 if(v4) e4= addedgelist(em, v4, v1, NULL);
368         }
369         
370         if(v1==v2 || v2==v3 || v1==v3) return NULL;
371         if(e2==0) return NULL;
372
373         efa= (EditFace *)callocface(em, sizeof(EditFace), 1);
374         efa->v1= v1;
375         efa->v2= v2;
376         efa->v3= v3;
377         efa->v4= v4;
378
379         efa->e1= e1;
380         efa->e2= e2;
381         efa->e3= e3;
382         efa->e4= e4;
383
384         if(example) {
385                 efa->mat_nr= example->mat_nr;
386                 efa->flag= example->flag;
387                 CustomData_em_copy_data(&em->fdata, &em->fdata, example->data, &efa->data);
388                 CustomData_em_validate_data(&em->fdata, efa->data, efa->v4 ? 4 : 3);
389         }
390         else {
391                 efa->mat_nr= em->mat_nr;
392
393                 CustomData_em_set_default(&em->fdata, &efa->data);
394         }
395
396         BLI_addtail(&em->faces, efa);
397         em->totface++;
398         
399         if(efa->v4) {
400                 normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
401                 cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
402         }
403         else {
404                 normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co);
405                 cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
406         }
407
408         return efa;
409 }
410
411 /* ************************ end add/new/find ************  */
412
413 /* ************************ Edit{Vert,Edge,Face} utilss ***************************** */
414
415 /* some nice utility functions */
416
417 EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve)
418 {
419         if (eve==eed->v1) {
420                 return eed->v2;
421         } else if (eve==eed->v2) {
422                 return eed->v1;
423         } else {
424                 return NULL;
425         }
426 }
427
428 EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2) 
429 {
430         if (eed->v1==eed2->v1 || eed->v1==eed2->v2) {
431                 return eed->v1;
432         } else if (eed->v2==eed2->v1 || eed->v2==eed2->v2) {
433                 return eed->v2;
434         } else {
435                 return NULL;
436         }
437 }
438
439 int editedge_containsVert(EditEdge *eed, EditVert *eve) 
440 {
441         return (eed->v1==eve || eed->v2==eve);
442 }
443
444 int editface_containsVert(EditFace *efa, EditVert *eve) 
445 {
446         return (efa->v1==eve || efa->v2==eve || efa->v3==eve || (efa->v4 && efa->v4==eve));
447 }
448
449 int editface_containsEdge(EditFace *efa, EditEdge *eed) 
450 {
451         return (efa->e1==eed || efa->e2==eed || efa->e3==eed || (efa->e4 && efa->e4==eed));
452 }
453
454
455 /* ************************ stuct EditMesh manipulation ***************************** */
456
457 /* fake callocs for fastmalloc below */
458 static void *calloc_fastvert(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
459 {
460         EditVert *eve= em->curvert++;
461         eve->fast= 1;
462         return eve;
463 }
464 static void *calloc_fastedge(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
465 {
466         EditEdge *eed= em->curedge++;
467         eed->fast= 1;
468         return eed;
469 }
470 static void *calloc_fastface(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
471 {
472         EditFace *efa= em->curface++;
473         efa->fast= 1;
474         return efa;
475 }
476
477 /* allocate 1 chunk for all vertices, edges, faces. These get tagged to
478    prevent it from being freed
479 */
480 static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface)
481 {
482         if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts");
483         else em->allverts= NULL;
484         em->curvert= em->allverts;
485         
486         if(totedge==0) totedge= 4*totface;      // max possible
487
488         if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges");
489         else em->alledges= NULL;
490         em->curedge= em->alledges;
491         
492         if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces");
493         else em->allfaces= NULL;
494         em->curface= em->allfaces;
495
496         callocvert= calloc_fastvert;
497         callocedge= calloc_fastedge;
498         callocface= calloc_fastface;
499 }
500
501 static void end_editmesh_fastmalloc(void)
502 {
503         callocvert= calloc_em;
504         callocedge= calloc_em;
505         callocface= calloc_em;
506 }
507
508 /* do not free editmesh itself here */
509 void free_editMesh(EditMesh *em)
510 {
511         if(em==NULL) return;
512
513         if(em->verts.first) free_vertlist(em, &em->verts);
514         if(em->edges.first) free_edgelist(em, &em->edges);
515         if(em->faces.first) free_facelist(em, &em->faces);
516         if(em->selected.first) BLI_freelistN(&(em->selected));
517
518         CustomData_free(&em->vdata, 0);
519         CustomData_free(&em->fdata, 0);
520
521         if(em->derivedFinal) {
522                 if (em->derivedFinal!=em->derivedCage) {
523                         em->derivedFinal->needsFree= 1;
524                         em->derivedFinal->release(em->derivedFinal);
525                 }
526                 em->derivedFinal= NULL;
527         }
528         if(em->derivedCage) {
529                 em->derivedCage->needsFree= 1;
530                 em->derivedCage->release(em->derivedCage);
531                 em->derivedCage= NULL;
532         }
533
534         /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */
535 #if 0
536         if(em->hashedgetab) {
537                 HashEdge *he, *hen;
538                 int a, used=0, max=0, nr;
539                 he= em->hashedgetab;
540                 for(a=0; a<EDHASHSIZE; a++, he++) {
541                         if(he->eed) used++;
542                         hen= he->next;
543                         nr= 0;
544                         while(hen) {
545                                 nr++;
546                                 hen= hen->next;
547                         }
548                         if(max<nr) max= nr;
549                 }
550                 printf("hastab used %d max %d\n", used, max);
551         }
552 #endif
553         if(em->hashedgetab) MEM_freeN(em->hashedgetab);
554         em->hashedgetab= NULL;
555         
556         if(em->allverts) MEM_freeN(em->allverts);
557         if(em->alledges) MEM_freeN(em->alledges);
558         if(em->allfaces) MEM_freeN(em->allfaces);
559         
560         em->allverts= em->curvert= NULL;
561         em->alledges= em->curedge= NULL;
562         em->allfaces= em->curface= NULL;
563         
564         mesh_octree_table(NULL, NULL, NULL, 'e');
565         mesh_mirrtopo_table(NULL, 'e');
566
567         em->totvert= em->totedge= em->totface= 0;
568
569 // XXX  if(em->retopo_paint_data) retopo_free_paint_data(em->retopo_paint_data);
570         em->retopo_paint_data= NULL;
571         em->act_face = NULL;
572 }
573
574 static void editMesh_set_hash(EditMesh *em)
575 {
576         EditEdge *eed;
577
578         if(em->hashedgetab) MEM_freeN(em->hashedgetab);
579         em->hashedgetab= NULL;
580         
581         for(eed=em->edges.first; eed; eed= eed->next)  {
582                 if( findedgelist(em, eed->v1, eed->v2)==NULL )
583                         insert_hashedge(em, eed);
584         }
585
586 }
587
588
589 /* ************************ IN & OUT EDITMODE ***************************** */
590
591
592 static void edge_normal_compare(EditEdge *eed, EditFace *efa1)
593 {
594         EditFace *efa2;
595         float cent1[3], cent2[3];
596         float inp;
597         
598         efa2 = eed->tmp.f;
599         if(efa1==efa2) return;
600         
601         inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2];
602         if(inp<0.999f && inp >-0.999f) eed->f2= 1;
603                 
604         if(efa1->v4) cent_quad_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co);
605         else cent_tri_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co);
606         if(efa2->v4) cent_quad_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co, efa2->v4->co);
607         else cent_tri_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co);
608         
609         sub_v3_v3v3(cent1, cent2, cent1);
610         normalize_v3(cent1);
611         inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2]; 
612
613         if(inp < -0.001f) eed->f1= 1;
614 }
615
616 #if 0
617 typedef struct {
618         EditEdge *eed;
619         float noLen,no[3];
620         int adjCount;
621 } EdgeDrawFlagInfo;
622
623 static int edgeDrawFlagInfo_cmp(const void *av, const void *bv)
624 {
625         const EdgeDrawFlagInfo *a = av;
626         const EdgeDrawFlagInfo *b = bv;
627
628         if (a->noLen<b->noLen) return -1;
629         else if (a->noLen>b->noLen) return 1;
630         else return 0;
631 }
632 #endif
633
634 static void edge_drawflags(Mesh *me, EditMesh *em)
635 {
636         EditVert *eve;
637         EditEdge *eed, *e1, *e2, *e3, *e4;
638         EditFace *efa;
639         
640         /* - count number of times edges are used in faces: 0 en 1 time means draw edge
641          * - edges more than 1 time used: in *tmp.f is pointer to first face
642          * - check all faces, when normal differs to much: draw (flag becomes 1)
643          */
644
645         /* later on: added flags for 'cylinder' and 'sphere' intersection tests in old
646            game engine (2.04)
647          */
648         
649         recalc_editnormals(em);
650         
651         /* init */
652         eve= em->verts.first;
653         while(eve) {
654                 eve->f1= 1;             /* during test it's set at zero */
655                 eve= eve->next;
656         }
657         eed= em->edges.first;
658         while(eed) {
659                 eed->f2= eed->f1= 0;
660                 eed->tmp.f = 0;
661                 eed= eed->next;
662         }
663
664         efa= em->faces.first;
665         while(efa) {
666                 e1= efa->e1;
667                 e2= efa->e2;
668                 e3= efa->e3;
669                 e4= efa->e4;
670                 if(e1->f2<4) e1->f2+= 1;
671                 if(e2->f2<4) e2->f2+= 1;
672                 if(e3->f2<4) e3->f2+= 1;
673                 if(e4 && e4->f2<4) e4->f2+= 1;
674                 
675                 if(e1->tmp.f == 0) e1->tmp.f = (void *) efa;
676                 if(e2->tmp.f == 0) e2->tmp.f = (void *) efa;
677                 if(e3->tmp.f ==0) e3->tmp.f = (void *) efa;
678                 if(e4 && (e4->tmp.f == 0)) e4->tmp.f = (void *) efa;
679                 
680                 efa= efa->next;
681         }
682
683         if(me->drawflag & ME_ALLEDGES) {
684                 efa= em->faces.first;
685                 while(efa) {
686                         if(efa->e1->f2>=2) efa->e1->f2= 1;
687                         if(efa->e2->f2>=2) efa->e2->f2= 1;
688                         if(efa->e3->f2>=2) efa->e3->f2= 1;
689                         if(efa->e4 && efa->e4->f2>=2) efa->e4->f2= 1;
690                         
691                         efa= efa->next;
692                 }               
693         }       
694         else {
695                 
696                 /* handle single-edges for 'test cylinder flag' (old engine) */
697                 
698                 eed= em->edges.first;
699                 while(eed) {
700                         if(eed->f2==1) eed->f1= 1;
701                         eed= eed->next;
702                 }
703
704                 /* all faces, all edges with flag==2: compare normal */
705                 efa= em->faces.first;
706                 while(efa) {
707                         if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa);
708                         else efa->e1->f2= 1;
709                         if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa);
710                         else efa->e2->f2= 1;
711                         if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa);
712                         else efa->e3->f2= 1;
713                         if(efa->e4) {
714                                 if(efa->e4->f2==2) edge_normal_compare(efa->e4, efa);
715                                 else efa->e4->f2= 1;
716                         }
717                         efa= efa->next;
718                 }
719                 
720                 /* sphere collision flag */
721                 
722                 eed= em->edges.first;
723                 while(eed) {
724                         if(eed->f1!=1) {
725                                 eed->v1->f1= eed->v2->f1= 0;
726                         }
727                         eed= eed->next;
728                 }
729                 
730         }
731 }
732
733 /* turns Mesh into editmesh */
734 void make_editMesh(Scene *scene, Object *ob)
735 {
736         Mesh *me= ob->data;
737         MFace *mface;
738         MVert *mvert;
739         MSelect *mselect;
740         KeyBlock *actkey;
741         EditMesh *em;
742         EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
743         EditFace *efa, *efa_last_sel= NULL;
744         EditEdge *eed;
745         EditSelection *ese;
746         float *co, (*keyco)[3]= NULL;
747         int tot, a, eekadoodle= 0;
748         const short is_paint_sel= paint_facesel_test(ob);
749
750         if(me->edit_mesh==NULL)
751                 me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
752         else 
753                 /* because of reload */
754                 free_editMesh(me->edit_mesh);
755         
756         em= me->edit_mesh;
757         
758         em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
759         em->act_face = NULL;
760         em->totvert= tot= me->totvert;
761         em->totedge= me->totedge;
762         em->totface= me->totface;
763         
764         if(tot==0) {
765                 return;
766         }
767         
768         if(ob->actcol > 0)
769                 em->mat_nr= ob->actcol-1;
770
771         /* initialize fastmalloc for editmesh */
772         init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface);
773
774         actkey = ob_get_keyblock(ob);
775         if(actkey) {
776                 /* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */
777                 undo_editmode_clear();
778                 keyco= actkey->data;
779                 em->shapenr= ob->shapenr;
780         }
781
782         /* make editverts */
783         CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
784         mvert= me->mvert;
785
786         evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
787         for(a=0; a<tot; a++, mvert++) {
788                 
789                 co= mvert->co;
790
791                 /* edit the shape key coordinate if available */
792                 if(keyco && a < actkey->totelem)
793                         co= keyco[a];
794
795                 eve= addvertlist(em, co, NULL);
796                 evlist[a]= eve;
797                 
798                 /* face select sets selection in next loop */
799                 if(!is_paint_sel)
800                         eve->f |= (mvert->flag & 1);
801                 
802                 if (mvert->flag & ME_HIDE) eve->h= 1;
803                 normal_short_to_float_v3(eve->no, mvert->no);
804
805                 eve->bweight= ((float)mvert->bweight)/255.0f;
806
807                 /* lets overwrite the keyindex of the editvert
808                  * with the order it used to be in before
809                  * editmode
810                  */
811                 eve->keyindex = a;
812
813                 CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data);
814         }
815
816         if(actkey && actkey->totelem!=me->totvert);
817         else {
818                 MEdge *medge= me->medge;
819                 
820                 CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
821                 /* make edges */
822                 for(a=0; a<me->totedge; a++, medge++) {
823                         eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL);
824                         /* eed can be zero when v1 and v2 are identical, dxf import does this... */
825                         if(eed) {
826                                 eed->crease= ((float)medge->crease)/255.0f;
827                                 eed->bweight= ((float)medge->bweight)/255.0f;
828                                 
829                                 if(medge->flag & ME_SEAM) eed->seam= 1;
830                                 if(medge->flag & ME_SHARP) eed->sharp = 1;
831                                 if(medge->flag & SELECT) eed->f |= SELECT;
832                                 if(medge->flag & ME_FGON) eed->h= EM_FGON;      // 2 different defines!
833                                 if(medge->flag & ME_HIDE) eed->h |= 1;
834                                 if(em->selectmode==SCE_SELECT_EDGE) 
835                                         EM_select_edge(eed, eed->f & SELECT);           // force edge selection to vertices, seems to be needed ...
836                                 CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data);
837                         }
838                 }
839                 
840                 CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
841
842                 /* make faces */
843                 mface= me->mface;
844
845                 for(a=0; a<me->totface; a++, mface++) {
846                         eve1= evlist[mface->v1];
847                         eve2= evlist[mface->v2];
848                         if(!mface->v3) eekadoodle= 1;
849                         eve3= evlist[mface->v3];
850                         if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL;
851                         
852                         efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
853
854                         if(efa) {
855                                 CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data);
856
857                                 efa->mat_nr= mface->mat_nr;
858                                 efa->flag= mface->flag & ~ME_HIDE;
859                                 
860                                 /* select and hide face flag */
861                                 if(mface->flag & ME_HIDE) {
862                                         efa->h= 1;
863                                 } else {
864                                         if (a==me->act_face) {
865                                                 EM_set_actFace(em, efa);
866                                         }
867                                         
868                                         /* dont allow hidden and selected */
869                                         if(mface->flag & ME_FACE_SEL) {
870                                                 efa->f |= SELECT;
871                                                 
872                                                 if(is_paint_sel) {
873                                                         EM_select_face(efa, 1); /* flush down */
874                                                 }
875
876                                                 efa_last_sel= efa;
877                                         }
878                                 }
879                         }
880                 }
881         }
882         
883         if(EM_get_actFace(em, 0)==NULL && efa_last_sel) {
884                 EM_set_actFace(em, efa_last_sel);
885         }
886
887         if(eekadoodle)
888                 error("This Mesh has old style edgecodes, please put it in the bugtracker!");
889         
890         MEM_freeN(evlist);
891
892         end_editmesh_fastmalloc();      // resets global function pointers
893         
894         if(me->mselect){
895                 //restore editselections
896                 EM_init_index_arrays(em, 1,1,1);
897                 mselect = me->mselect;
898                 
899                 for(a=0; a<me->totselect; a++, mselect++){
900                         /*check if recorded selection is still valid, if so copy into editmesh*/
901                         if( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) || (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) || (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) ){
902                                 ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
903                                 ese->type = mselect->type;      
904                                 if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else
905                                 if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else
906                                 if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index);
907                                 BLI_addtail(&(em->selected),ese);
908                         }
909                 }
910                 EM_free_index_arrays();
911         }
912         /* this creates coherent selections. also needed for older files */
913         EM_selectmode_set(em);
914         /* paranoia check to enforce hide rules */
915         EM_hide_reset(em);
916         /* sets helper flags which arent saved */
917         EM_fgon_flags(em);
918         
919         if (EM_get_actFace(em, 0)==NULL) {
920                 EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */
921         }
922 }
923
924 /* makes Mesh out of editmesh */
925 void load_editMesh(Scene *scene, Object *obedit)
926 {
927         Mesh *me= obedit->data;
928         MVert *mvert, *oldverts;
929         MEdge *medge;
930         MFace *mface;
931         MSelect *mselect;
932         EditMesh *em= me->edit_mesh;
933         EditVert *eve;
934         EditFace *efa, *efa_act;
935         EditEdge *eed;
936         EditSelection *ese;
937         float *fp, *newkey, *oldkey;
938         int i, a, ototvert;
939         
940         /* this one also tests of edges are not in faces: */
941         /* eed->f2==0: not in face, f2==1: draw it */
942         /* eed->f1 : flag for dynaface (cylindertest, old engine) */
943         /* eve->f1 : flag for dynaface (sphere test, old engine) */
944         /* eve->f2 : being used in vertexnormals */
945         edge_drawflags(me, em);
946         
947         EM_stats_update(em);
948         
949         /* new Vertex block */
950         if(em->totvert==0) mvert= NULL;
951         else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert");
952
953         /* new Edge block */
954         if(em->totedge==0) medge= NULL;
955         else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge");
956         
957         /* new Face block */
958         if(em->totface==0) mface= NULL;
959         else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face");
960
961         /* lets save the old verts just in case we are actually working on
962          * a key ... we now do processing of the keys at the end */
963         oldverts= me->mvert;
964         ototvert= me->totvert;
965
966         /* don't free this yet */
967         CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
968
969         /* free custom data */
970         CustomData_free(&me->vdata, me->totvert);
971         CustomData_free(&me->edata, me->totedge);
972         CustomData_free(&me->fdata, me->totface);
973
974         /* add new custom data */
975         me->totvert= em->totvert;
976         me->totedge= em->totedge;
977         me->totface= em->totface;
978
979         CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
980         CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
981         CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface);
982
983         CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
984         CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
985         CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
986         mesh_update_customdata_pointers(me);
987
988         /* the vertices, use ->tmp.l as counter */
989         eve= em->verts.first;
990         a= 0;
991
992         while(eve) {
993                 VECCOPY(mvert->co, eve->co);
994
995                 /* vertex normal */
996                 normal_float_to_short_v3(mvert->no, eve->no);
997
998                 /* note: it used to remove me->dvert when it was not in use, cancelled
999                    that... annoying when you have a fresh vgroup */
1000                 CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a);
1001
1002                 eve->tmp.l = a++;  /* counter */
1003                         
1004                 mvert->flag= 0;
1005                 mvert->flag |= (eve->f & SELECT);
1006                 if (eve->h) mvert->flag |= ME_HIDE;
1007                 
1008                 mvert->bweight= (char)(255.0f*eve->bweight);
1009
1010                 eve= eve->next;
1011                 mvert++;
1012         }
1013
1014         /* the edges */
1015         a= 0;
1016         eed= em->edges.first;
1017         while(eed) {
1018                 medge->v1= (unsigned int) eed->v1->tmp.l;
1019                 medge->v2= (unsigned int) eed->v2->tmp.l;
1020                 
1021                 medge->flag= (eed->f & SELECT) | ME_EDGERENDER;
1022                 if(eed->f2<2) medge->flag |= ME_EDGEDRAW;
1023                 if(eed->f2==0) medge->flag |= ME_LOOSEEDGE;
1024                 if(eed->sharp) medge->flag |= ME_SHARP;
1025                 if(eed->seam) medge->flag |= ME_SEAM;
1026                 if(eed->h & EM_FGON) medge->flag |= ME_FGON;    // different defines yes
1027                 if(eed->h & 1) medge->flag |= ME_HIDE;
1028                 
1029                 medge->crease= (char)(255.0f*eed->crease);
1030                 medge->bweight= (char)(255.0f*eed->bweight);
1031                 CustomData_from_em_block(&em->edata, &me->edata, eed->data, a);         
1032
1033                 eed->tmp.l = a++;
1034                 
1035                 medge++;
1036                 eed= eed->next;
1037         }
1038
1039         /* the faces */
1040         a = 0;
1041         efa= em->faces.first;
1042         efa_act= EM_get_actFace(em, 0);
1043         i = 0;
1044         me->act_face = -1;
1045         while(efa) {
1046                 mface= &((MFace *) me->mface)[i];
1047                 
1048                 mface->v1= (unsigned int) efa->v1->tmp.l;
1049                 mface->v2= (unsigned int) efa->v2->tmp.l;
1050                 mface->v3= (unsigned int) efa->v3->tmp.l;
1051                 if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l;
1052
1053                 mface->mat_nr= efa->mat_nr;
1054                 
1055                 mface->flag= efa->flag;
1056                 /* bit 0 of flag is already taken for smooth... */
1057                 
1058                 if(efa->h) {
1059                         mface->flag |= ME_HIDE;
1060                         mface->flag &= ~ME_FACE_SEL;
1061                 } else {
1062                         if(efa->f & 1) mface->flag |= ME_FACE_SEL;
1063                         else mface->flag &= ~ME_FACE_SEL;
1064                 }
1065                         
1066                 /* watch: efa->e1->f2==0 means loose edge */ 
1067                         
1068                 if(efa->e1->f2==1) {
1069                         efa->e1->f2= 2;
1070                 }                       
1071                 if(efa->e2->f2==1) {
1072                         efa->e2->f2= 2;
1073                 }
1074                 if(efa->e3->f2==1) {
1075                         efa->e3->f2= 2;
1076                 }
1077                 if(efa->e4 && efa->e4->f2==1) {
1078                         efa->e4->f2= 2;
1079                 }
1080
1081                 CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i);
1082
1083                 /* no index '0' at location 3 or 4 */
1084                 test_index_face(mface, &me->fdata, i, efa->v4?4:3);
1085                 
1086                 if (efa_act == efa)
1087                         me->act_face = a;
1088
1089                 efa->tmp.l = a++;
1090                 i++;
1091                 efa= efa->next;
1092         }
1093
1094         /* patch hook indices and vertex parents */
1095         {
1096                 Object *ob;
1097                 ModifierData *md;
1098                 EditVert **vertMap = NULL;
1099                 int j;
1100
1101                 for (ob=G.main->object.first; ob; ob=ob->id.next) {
1102                         if (ob->parent==obedit && ELEM(ob->partype, PARVERT1,PARVERT3)) {
1103                                 
1104                                 /* duplicate code from below, make it function later...? */
1105                                 if (!vertMap) {
1106                                         vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
1107                                         
1108                                         for (eve=em->verts.first; eve; eve=eve->next) {
1109                                                 if (eve->keyindex!=-1)
1110                                                         vertMap[eve->keyindex] = eve;
1111                                         }
1112                                 }
1113                                 if(ob->par1 < ototvert) {
1114                                         eve = vertMap[ob->par1];
1115                                         if(eve) ob->par1= eve->tmp.l;
1116                                 }
1117                                 if(ob->par2 < ototvert) {
1118                                         eve = vertMap[ob->par2];
1119                                         if(eve) ob->par2= eve->tmp.l;
1120                                 }
1121                                 if(ob->par3 < ototvert) {
1122                                         eve = vertMap[ob->par3];
1123                                         if(eve) ob->par3= eve->tmp.l;
1124                                 }
1125                                 
1126                         }
1127                         if (ob->data==me) {
1128                                 for (md=ob->modifiers.first; md; md=md->next) {
1129                                         if (md->type==eModifierType_Hook) {
1130                                                 HookModifierData *hmd = (HookModifierData*) md;
1131
1132                                                 if (!vertMap) {
1133                                                         vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
1134
1135                                                         for (eve=em->verts.first; eve; eve=eve->next) {
1136                                                                 if (eve->keyindex!=-1)
1137                                                                         vertMap[eve->keyindex] = eve;
1138                                                         }
1139                                                 }
1140                                                 
1141                                                 for (i=j=0; i<hmd->totindex; i++) {
1142                                                         if(hmd->indexar[i] < ototvert) {
1143                                                                 eve = vertMap[hmd->indexar[i]];
1144                                                                 
1145                                                                 if (eve) {
1146                                                                         hmd->indexar[j++] = eve->tmp.l;
1147                                                                 }
1148                                                         }
1149                                                         else j++;
1150                                                 }
1151
1152                                                 hmd->totindex = j;
1153                                         }
1154                                 }
1155                         }
1156                 }
1157
1158                 if (vertMap) MEM_freeN(vertMap);
1159         }
1160
1161         /* are there keys? */
1162         if(me->key) {
1163                 KeyBlock *currkey;
1164                 KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1);
1165
1166                 float (*ofs)[3] = NULL;
1167
1168                 /* editing the base key should update others */
1169                 if(me->key->type==KEY_RELATIVE && oldverts) {
1170                         int act_is_basis = 0;
1171                         /* find if this key is a basis for any others */
1172                         for(currkey = me->key->block.first; currkey; currkey= currkey->next) {
1173                                 if(em->shapenr-1 == currkey->relative) {
1174                                         act_is_basis = 1;
1175                                         break;
1176                                 }
1177                         }
1178
1179                         if(act_is_basis) { /* active key is a base */
1180                                 float (*fp)[3]= actkey->data;
1181                                 i=0;
1182                                 ofs= MEM_callocN(sizeof(float) * 3 * em->totvert,  "currkey->data");
1183                                 eve= em->verts.first;
1184                                 mvert = me->mvert;
1185                                 while(eve) {
1186                                         if(eve->keyindex>=0)
1187                                                 VECSUB(ofs[i], mvert->co, fp[eve->keyindex]);
1188
1189                                         eve= eve->next;
1190                                         i++;
1191                                         mvert++;
1192                                 }
1193                         }
1194                 }
1195
1196
1197                 /* Lets reorder the key data so that things line up roughly
1198                  * with the way things were before editmode */
1199                 currkey = me->key->block.first;
1200                 while(currkey) {
1201                         int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative));
1202
1203                         fp= newkey= MEM_callocN(me->key->elemsize*em->totvert,  "currkey->data");
1204                         oldkey = currkey->data;
1205
1206                         eve= em->verts.first;
1207
1208                         i = 0;
1209                         mvert = me->mvert;
1210                         while(eve) {
1211                                 if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex
1212                                         if(currkey == actkey) {
1213                                                 if(actkey == me->key->refkey) {
1214                                                         VECCOPY(fp, mvert->co);
1215                                                 }
1216                                                 else {
1217                                                         VECCOPY(fp, mvert->co);
1218                                                         if(oldverts) {
1219                                                                 VECCOPY(mvert->co, oldverts[eve->keyindex].co);
1220                                                         }
1221                                                 }
1222                                         }
1223                                         else {
1224                                                 if(oldkey) {
1225                                                         VECCOPY(fp, oldkey + 3 * eve->keyindex);
1226                                                 }
1227                                         }
1228                                 }
1229                                 else {
1230                                         VECCOPY(fp, mvert->co);
1231                                 }
1232
1233                                 /* propagate edited basis offsets to other shapes */
1234                                 if(apply_offset) {
1235                                         VECADD(fp, fp, ofs[i]);
1236                                 }
1237
1238                                 fp+= 3;
1239                                 ++i;
1240                                 ++mvert;
1241                                 eve= eve->next;
1242                         }
1243                         currkey->totelem= em->totvert;
1244                         if(currkey->data) MEM_freeN(currkey->data);
1245                         currkey->data = newkey;
1246                         
1247                         currkey= currkey->next;
1248                 }
1249
1250                 if(ofs) MEM_freeN(ofs);
1251         }
1252
1253         if(oldverts) MEM_freeN(oldverts);
1254         
1255         i = 0;
1256         for(ese=em->selected.first; ese; ese=ese->next) i++;
1257         me->totselect = i;
1258         if(i==0) mselect= NULL;
1259         else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections");
1260         
1261         if(me->mselect) MEM_freeN(me->mselect);
1262         me->mselect= mselect;
1263         
1264         for(ese=em->selected.first; ese; ese=ese->next){
1265                 mselect->type = ese->type;
1266                 if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l;
1267                 else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l;
1268                 else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l;
1269                 mselect++;
1270         }
1271         
1272         /* to be sure: clear ->tmp.l pointers */
1273         eve= em->verts.first;
1274         while(eve) {
1275                 eve->tmp.l = 0;
1276                 eve= eve->next;
1277         }
1278         
1279         eed= em->edges.first;
1280         while(eed) { 
1281                 eed->tmp.l = 0;
1282                 eed= eed->next;
1283         }
1284         
1285         efa= em->faces.first;
1286         while(efa) {
1287                 efa->tmp.l = 0;
1288                 efa= efa->next;
1289         }
1290         
1291         /* remake softbody of all users */
1292         if(me->id.us>1) {
1293                 Base *base;
1294                 for(base= scene->base.first; base; base= base->next)
1295                         if(base->object->data==me)
1296                                 base->object->recalc |= OB_RECALC_DATA;
1297         }
1298
1299         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
1300
1301         /* topology could be changed, ensure mdisps are ok */
1302         multires_topology_changed(scene, obedit);
1303 }
1304
1305 void remake_editMesh(Scene *scene, Object *ob)
1306 {
1307         make_editMesh(scene, ob);
1308         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1309         BIF_undo_push("Undo all changes");
1310 }
1311
1312 /* *************** Operator: separate parts *************/
1313
1314 static EnumPropertyItem prop_separate_types[] = {
1315         {0, "SELECTED", 0, "Selection", ""},
1316         {1, "MATERIAL", 0, "By Material", ""},
1317         {2, "LOOSE", 0, "By loose parts", ""},
1318         {0, NULL, 0, NULL, NULL}
1319 };
1320
1321 /* return 1: success */
1322 static int mesh_separate_selected(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
1323 {
1324         EditMesh *em, *emnew;
1325         EditVert *eve, *v1;
1326         EditEdge *eed, *e1;
1327         EditFace *efa, *f1;
1328         Object *obedit;
1329         Mesh *me, *menew;
1330         Base *basenew;
1331         
1332         if(editbase==NULL) return 0;
1333         
1334         obedit= editbase->object;
1335         me= obedit->data;
1336         em= BKE_mesh_get_editmesh(me);
1337         if(me->key) {
1338                 BKE_report(op->reports, RPT_WARNING, "Can't separate mesh with shape keys.");
1339                 BKE_mesh_end_editmesh(me, em);
1340                 return 0;
1341         }
1342         
1343         if(em->selected.first) 
1344                 BLI_freelistN(&(em->selected)); /* clear the selection order */
1345                 
1346         EM_selectmode_set(em);  // enforce full consistent selection flags 
1347         
1348         EM_stats_update(em);
1349         
1350         if(em->totvertsel==0) {
1351                 BKE_mesh_end_editmesh(me, em);
1352                 return 0;
1353         }
1354         
1355         /* we are going to work as follows:
1356          * 1. add a linked duplicate object: this will be the new one, we remember old pointer
1357          * 2. give new object empty mesh and put in editmode
1358          * 3: do a split if needed on current editmesh.
1359          * 4. copy over: all NOT selected verts, edges, faces
1360          * 5. call load_editMesh() on the new object
1361          */
1362         
1363         /* 1 */
1364         basenew= ED_object_add_duplicate(bmain, scene, editbase, 0);    /* 0 = fully linked */
1365         ED_base_object_select(basenew, BA_DESELECT);
1366         
1367         /* 2 */
1368         basenew->object->data= menew= add_mesh(me->id.name+2);  /* empty */
1369         assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
1370         me->id.us--;
1371         make_editMesh(scene, basenew->object);
1372         emnew= menew->edit_mesh;
1373         CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
1374         CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
1375         CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
1376         
1377         /* 3 */
1378         /* SPLIT: first make duplicate */
1379         adduplicateflag(em, SELECT);
1380         /* SPLIT: old faces have 3x flag 128 set, delete these ones */
1381         delfaceflag(em, 128);
1382         /* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */
1383         EM_selectmode_set(em);
1384         
1385         /* 4 */
1386         /* move over: everything that is selected */
1387         for(eve= em->verts.first; eve; eve= v1) {
1388                 v1= eve->next;
1389                 if(eve->f & SELECT) {
1390                         BLI_remlink(&em->verts, eve);
1391                         BLI_addtail(&emnew->verts, eve);
1392                 }
1393         }
1394         
1395         for(eed= em->edges.first; eed; eed= e1) {
1396                 e1= eed->next;
1397                 if(eed->f & SELECT) {
1398                         BLI_remlink(&em->edges, eed);
1399                         BLI_addtail(&emnew->edges, eed);
1400                 }
1401         }
1402         
1403         for(efa= em->faces.first; efa; efa= f1) {
1404                 f1= efa->next;
1405                 if (efa == em->act_face && (efa->f & SELECT)) {
1406                         EM_set_actFace(em, NULL);
1407                 }
1408
1409                 if(efa->f & SELECT) {
1410                         BLI_remlink(&em->faces, efa);
1411                         BLI_addtail(&emnew->faces, efa);
1412                 }
1413         }
1414
1415         /* 5 */
1416         load_editMesh(scene, basenew->object);
1417         free_editMesh(emnew);
1418         MEM_freeN(menew->edit_mesh);
1419         menew->edit_mesh= NULL;
1420
1421         /* copy settings */
1422         menew->texflag= me->texflag;
1423         menew->drawflag= me->drawflag;
1424         menew->flag= me->flag;
1425         menew->editflag= me->editflag;
1426         menew->smoothresh= me->smoothresh;
1427
1428         /* hashedges are invalid now, make new! */
1429         editMesh_set_hash(em);
1430
1431         DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); 
1432         DAG_id_tag_update(&basenew->object->id, OB_RECALC_DATA);        
1433
1434         BKE_mesh_end_editmesh(me, em);
1435
1436         return 1;
1437 }
1438
1439 /* return 1: success */
1440 static int mesh_separate_material(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
1441 {
1442         Mesh *me= editbase->object->data;
1443         EditMesh *em= BKE_mesh_get_editmesh(me);
1444         unsigned char curr_mat;
1445         
1446         for (curr_mat = 1; curr_mat < editbase->object->totcol; ++curr_mat) {
1447                 /* clear selection, we're going to use that to select material group */
1448                 EM_clear_flag_all(em, SELECT);
1449                 /* select the material */
1450                 EM_select_by_material(em, curr_mat);
1451                 /* and now separate */
1452                 if(em->totfacesel > 0) {
1453                         mesh_separate_selected(op, bmain, scene, editbase);
1454                 }
1455         }
1456
1457         BKE_mesh_end_editmesh(me, em);
1458         return 1;
1459 }
1460
1461 /* return 1: success */
1462 static int mesh_separate_loose(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
1463 {
1464         Mesh *me;
1465         EditMesh *em;
1466         int doit= 1;
1467         
1468         me= editbase->object->data;
1469         em= BKE_mesh_get_editmesh(me);
1470         
1471         if(me->key) {
1472                 error("Can't separate with vertex keys");
1473                 BKE_mesh_end_editmesh(me, em);
1474                 return 0;
1475         }
1476         
1477         EM_clear_flag_all(em, SELECT);
1478
1479         while(doit) {
1480                 /* Select a random vert to start with */
1481                 EditVert *eve;
1482                 int tot;
1483
1484                 /* check if all verts that are visible have been done */
1485                 for(eve=em->verts.first; eve; eve= eve->next)
1486                         if(!eve->h) break;
1487                 if(eve==NULL) break; /* only hidden verts left, quit early */
1488
1489                 /* first non hidden vert */
1490                 eve->f |= SELECT;
1491                 
1492                 selectconnected_mesh_all(em);
1493                 
1494                 /* don't separate the very last part */
1495                 for(eve=em->verts.first; eve; eve= eve->next)
1496                         if((eve->f & SELECT)==0) break;
1497                 if(eve==NULL) break;
1498
1499                 tot= BLI_countlist(&em->verts);
1500
1501                 /* and now separate */
1502                 doit= mesh_separate_selected(op, bmain, scene, editbase);
1503
1504                 /* with hidden verts this can happen */
1505                 if(tot == BLI_countlist(&em->verts))
1506                         break;
1507         }
1508
1509         BKE_mesh_end_editmesh(me, em);
1510         return 1;
1511 }
1512
1513
1514 static int mesh_separate_exec(bContext *C, wmOperator *op)
1515 {
1516         Main *bmain= CTX_data_main(C);
1517         Scene *scene= CTX_data_scene(C);
1518         Base *base= CTX_data_active_base(C);
1519         int retval= 0, type= RNA_enum_get(op->ptr, "type");
1520         
1521         if(type == 0)
1522                 retval= mesh_separate_selected(op, bmain, scene, base);
1523         else if(type == 1)
1524                 retval= mesh_separate_material(op, bmain, scene, base);
1525         else if(type == 2)
1526                 retval= mesh_separate_loose(op, bmain, scene, base);
1527            
1528         if(retval) {
1529                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
1530
1531                 // XXX: new object was created, but selection wasn't actually changed
1532                 //      need this for outliner update without adding new ND. nazgul.
1533                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
1534
1535                 return OPERATOR_FINISHED;
1536         }
1537         return OPERATOR_CANCELLED;
1538 }
1539
1540 void MESH_OT_separate(wmOperatorType *ot)
1541 {
1542         /* identifiers */
1543         ot->name= "Separate";
1544         ot->description= "Separate selected geometry into a new mesh";
1545         ot->idname= "MESH_OT_separate";
1546         
1547         /* api callbacks */
1548         ot->invoke= WM_menu_invoke;
1549         ot->exec= mesh_separate_exec;
1550         ot->poll= ED_operator_editmesh;
1551         
1552         /* flags */
1553         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1554         
1555         ot->prop= RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", "");
1556 }
1557
1558
1559 /* ******************************************** */
1560
1561 /* *************** UNDO ***************************** */
1562 /* new mesh undo, based on pushing editmesh data itself */
1563 /* reuses same code as for global and curve undo... unify that (ton) */
1564
1565 /* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */
1566
1567 /* a compressed version of editmesh data */
1568
1569 typedef struct EditVertC
1570 {
1571         float no[3];
1572         float co[3];
1573         unsigned char f, h;
1574         short bweight;
1575         int keyindex;
1576 } EditVertC;
1577
1578 typedef struct EditEdgeC
1579 {
1580         int v1, v2;
1581         unsigned char f, h, seam, sharp, pad;
1582         short crease, bweight, fgoni;
1583 } EditEdgeC;
1584
1585 typedef struct EditFaceC
1586 {
1587         int v1, v2, v3, v4;
1588         unsigned char flag, f, h, fgonf, pad1;
1589         short mat_nr;
1590 } EditFaceC;
1591
1592 typedef struct EditSelectionC{
1593         short type;
1594         int index;
1595 }EditSelectionC;
1596
1597 typedef struct UndoMesh {
1598         EditVertC *verts;
1599         EditEdgeC *edges;
1600         EditFaceC *faces;
1601         EditSelectionC *selected;
1602         int totvert, totedge, totface, totsel;
1603         int selectmode, shapenr;
1604         char retopo_mode;
1605         CustomData vdata, edata, fdata;
1606 } UndoMesh;
1607
1608 /* for callbacks */
1609
1610 static void free_undoMesh(void *umv)
1611 {
1612         UndoMesh *um= umv;
1613         
1614         if(um->verts) MEM_freeN(um->verts);
1615         if(um->edges) MEM_freeN(um->edges);
1616         if(um->faces) MEM_freeN(um->faces);
1617         if(um->selected) MEM_freeN(um->selected);
1618 // XXX  if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data);
1619         CustomData_free(&um->vdata, um->totvert);
1620         CustomData_free(&um->edata, um->totedge);
1621         CustomData_free(&um->fdata, um->totface);
1622         MEM_freeN(um);
1623 }
1624
1625 static void *editMesh_to_undoMesh(void *emv)
1626 {
1627         EditMesh *em= (EditMesh *)emv;
1628         UndoMesh *um;
1629         EditVert *eve;
1630         EditEdge *eed;
1631         EditFace *efa;
1632         EditSelection *ese;
1633         EditVertC *evec=NULL;
1634         EditEdgeC *eedc=NULL;
1635         EditFaceC *efac=NULL;
1636         EditSelectionC *esec=NULL;
1637         int a;
1638
1639         um= MEM_callocN(sizeof(UndoMesh), "undomesh");
1640         
1641         um->selectmode = em->selectmode;
1642         um->shapenr = em->shapenr;
1643         
1644         for(eve=em->verts.first; eve; eve= eve->next) um->totvert++;
1645         for(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
1646         for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
1647         for(ese=em->selected.first; ese; ese=ese->next) um->totsel++; 
1648         /* malloc blocks */
1649         
1650         if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC");
1651         if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
1652         if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
1653         if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections");
1654
1655         if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert);
1656         if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge);
1657         if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface);
1658         
1659         /* now copy vertices */
1660         a = 0;
1661         for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
1662                 copy_v3_v3(evec->co, eve->co);
1663                 copy_v3_v3(evec->no, eve->no);
1664
1665                 evec->f= eve->f;
1666                 evec->h= eve->h;
1667                 evec->keyindex= eve->keyindex;
1668                 eve->tmp.l = a; /*store index*/
1669                 evec->bweight= (short)(eve->bweight*255.0f);
1670
1671                 CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a);
1672         }
1673         
1674         /* copy edges */
1675         a = 0;
1676         for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++)  {
1677                 eedc->v1= (int)eed->v1->tmp.l;
1678                 eedc->v2= (int)eed->v2->tmp.l;
1679                 eedc->f= eed->f;
1680                 eedc->h= eed->h;
1681                 eedc->seam= eed->seam;
1682                 eedc->sharp= eed->sharp;
1683                 eedc->crease= (short)(eed->crease*255.0f);
1684                 eedc->bweight= (short)(eed->bweight*255.0f);
1685                 eedc->fgoni= eed->fgoni;
1686                 eed->tmp.l = a; /*store index*/
1687                 CustomData_from_em_block(&em->edata, &um->edata, eed->data, a);
1688         
1689         }
1690         
1691         /* copy faces */
1692         a = 0;
1693         for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) {
1694                 efac->v1= (int)efa->v1->tmp.l;
1695                 efac->v2= (int)efa->v2->tmp.l;
1696                 efac->v3= (int)efa->v3->tmp.l;
1697                 if(efa->v4) efac->v4= (int)efa->v4->tmp.l;
1698                 else efac->v4= -1;
1699                 
1700                 efac->mat_nr= efa->mat_nr;
1701                 efac->flag= efa->flag;
1702                 efac->f= efa->f;
1703                 efac->h= efa->h;
1704                 efac->fgonf= efa->fgonf;
1705
1706                 efa->tmp.l = a; /*store index*/
1707
1708                 CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a);
1709         }
1710         
1711         a = 0;
1712         for(ese=em->selected.first; ese; ese=ese->next, esec++){
1713                 esec->type = ese->type;
1714                 if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l; 
1715                 else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l; 
1716                 else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l;
1717         }
1718
1719 // XXX  um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data);
1720 //      um->retopo_mode= scene->toolsettings->retopo_mode;
1721         
1722         return um;
1723 }
1724
1725 static void undoMesh_to_editMesh(void *umv, void *emv)
1726 {
1727         EditMesh *em= (EditMesh *)emv;
1728         UndoMesh *um= (UndoMesh *)umv;
1729         EditVert *eve, **evar=NULL;
1730         EditEdge *eed;
1731         EditFace *efa;
1732         EditSelection *ese;
1733         EditVertC *evec;
1734         EditEdgeC *eedc;
1735         EditFaceC *efac;
1736         EditSelectionC *esec;
1737         int a=0;
1738
1739         free_editMesh(em);
1740         
1741         /* malloc blocks */
1742         memset(em, 0, sizeof(EditMesh));
1743                 
1744         em->selectmode = um->selectmode;
1745         em->shapenr = um->shapenr;
1746         
1747         init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);
1748
1749         CustomData_free(&em->vdata, 0);
1750         CustomData_free(&em->edata, 0);
1751         CustomData_free(&em->fdata, 0);
1752
1753         CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
1754         CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
1755         CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
1756
1757         /* now copy vertices */
1758
1759         if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar");
1760         for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
1761                 eve= addvertlist(em, evec->co, NULL);
1762                 evar[a]= eve;
1763
1764                 copy_v3_v3(eve->no, evec->no);
1765                 eve->f= evec->f;
1766                 eve->h= evec->h;
1767                 eve->keyindex= evec->keyindex;
1768                 eve->bweight= ((float)evec->bweight)/255.0f;
1769
1770                 CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data);
1771         }
1772
1773         /* copy edges */
1774         for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) {
1775                 eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL);
1776
1777                 eed->f= eedc->f;
1778                 eed->h= eedc->h;
1779                 eed->seam= eedc->seam;
1780                 eed->sharp= eedc->sharp;
1781                 eed->fgoni= eedc->fgoni;
1782                 eed->crease= ((float)eedc->crease)/255.0f;
1783                 eed->bweight= ((float)eedc->bweight)/255.0f;
1784                 CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data);
1785         }
1786         
1787         /* copy faces */
1788         for(a=0, efac= um->faces; a<um->totface; a++, efac++) {
1789                 if(efac->v4 != -1)
1790                         efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL);
1791                 else 
1792                         efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL);
1793
1794                 efa->mat_nr= efac->mat_nr;
1795                 efa->flag= efac->flag;
1796                 efa->f= efac->f;
1797                 efa->h= efac->h;
1798                 efa->fgonf= efac->fgonf;
1799                 
1800                 CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data);
1801         }
1802         
1803         end_editmesh_fastmalloc();
1804         if(evar) MEM_freeN(evar);
1805         
1806         em->totvert = um->totvert;
1807         em->totedge = um->totedge;
1808         em->totface = um->totface;
1809         /*restore stored editselections*/
1810         if(um->totsel){
1811                 EM_init_index_arrays(em, 1,1,1);
1812                 for(a=0, esec= um->selected; a<um->totsel; a++, esec++){
1813                         ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
1814                         ese->type = esec->type;
1815                         if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else
1816                         if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else
1817                         if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index);
1818                         BLI_addtail(&(em->selected),ese);
1819                 }
1820                 EM_free_index_arrays();
1821         }
1822
1823         /* restore total selections */
1824         EM_nvertices_selected(em);
1825         EM_nedges_selected(em);
1826         EM_nfaces_selected(em);
1827
1828 // XXX  retopo_free_paint();
1829 //      em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data);
1830 //      scene->toolsettings->retopo_mode= um->retopo_mode;
1831 //      if(scene->toolsettings->retopo_mode) {
1832 // XXX          if(G.vd->depths) G.vd->depths->damaged= 1;
1833 //              retopo_queue_updates(G.vd);
1834 //              retopo_paint_view_update(G.vd);
1835 //      }
1836         
1837 }
1838
1839 static void *getEditMesh(bContext *C)
1840 {
1841         Object *obedit= CTX_data_edit_object(C);
1842         if(obedit && obedit->type==OB_MESH) {
1843                 Mesh *me= obedit->data;
1844                 return me->edit_mesh;
1845         }
1846         return NULL;
1847 }
1848
1849 /* and this is all the undo system needs to know */
1850 void undo_push_mesh(bContext *C, const char *name)
1851 {
1852         undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL);
1853 }
1854
1855
1856
1857 /* *************** END UNDO *************/
1858
1859 static EditVert **g_em_vert_array = NULL;
1860 static EditEdge **g_em_edge_array = NULL;
1861 static EditFace **g_em_face_array = NULL;
1862
1863 void EM_init_index_arrays(EditMesh *em, int forVert, int forEdge, int forFace)
1864 {
1865         EditVert *eve;
1866         EditEdge *eed;
1867         EditFace *efa;
1868         int i;
1869
1870         if (forVert) {
1871                 em->totvert= BLI_countlist(&em->verts);
1872
1873                 if(em->totvert) {
1874                         g_em_vert_array = MEM_mallocN(sizeof(*g_em_vert_array)*em->totvert, "em_v_arr");
1875
1876                         for (i=0,eve=em->verts.first; eve; i++,eve=eve->next)
1877                                 g_em_vert_array[i] = eve;
1878                 }
1879         }
1880
1881         if (forEdge) {
1882                 em->totedge= BLI_countlist(&em->edges);
1883
1884                 if(em->totedge) {
1885                         g_em_edge_array = MEM_mallocN(sizeof(*g_em_edge_array)*em->totedge, "em_e_arr");
1886
1887                         for (i=0,eed=em->edges.first; eed; i++,eed=eed->next)
1888                                 g_em_edge_array[i] = eed;
1889                 }
1890         }
1891
1892         if (forFace) {
1893                 em->totface= BLI_countlist(&em->faces);
1894
1895                 if(em->totface) {
1896                         g_em_face_array = MEM_mallocN(sizeof(*g_em_face_array)*em->totface, "em_f_arr");
1897
1898                         for (i=0,efa=em->faces.first; efa; i++,efa=efa->next)
1899                                 g_em_face_array[i] = efa;
1900                 }
1901         }
1902 }
1903
1904 void EM_free_index_arrays(void)
1905 {
1906         if (g_em_vert_array) MEM_freeN(g_em_vert_array);
1907         if (g_em_edge_array) MEM_freeN(g_em_edge_array);
1908         if (g_em_face_array) MEM_freeN(g_em_face_array);
1909         g_em_vert_array = NULL;
1910         g_em_edge_array = NULL;
1911         g_em_face_array = NULL;
1912 }
1913
1914 EditVert *EM_get_vert_for_index(int index)
1915 {
1916         return g_em_vert_array?g_em_vert_array[index]:NULL;
1917 }
1918
1919 EditEdge *EM_get_edge_for_index(int index)
1920 {
1921         return g_em_edge_array?g_em_edge_array[index]:NULL;
1922 }
1923
1924 EditFace *EM_get_face_for_index(int index)
1925 {
1926         return g_em_face_array?g_em_face_array[index]:NULL;
1927 }
1928
1929 /* can we edit UV's for this mesh?*/
1930 int EM_texFaceCheck(EditMesh *em)
1931 {
1932         /* some of these checks could be a touch overkill */
1933         if (    (em) &&
1934                         (em->faces.first) &&
1935                         (CustomData_has_layer(&em->fdata, CD_MTFACE)))
1936                 return 1;
1937         return 0;
1938 }
1939
1940 /* can we edit colors for this mesh?*/
1941 int EM_vertColorCheck(EditMesh *em)
1942 {
1943         /* some of these checks could be a touch overkill */
1944         if (    (em) &&
1945                         (em->faces.first) &&
1946                         (CustomData_has_layer(&em->fdata, CD_MCOL)))
1947                 return 1;
1948         return 0;
1949 }
1950
1951
1952 void em_setup_viewcontext(bContext *C, ViewContext *vc)
1953 {
1954         view3d_set_viewcontext(C, vc);
1955         
1956         if(vc->obedit) {
1957                 Mesh *me= vc->obedit->data;
1958                 vc->em= me->edit_mesh;
1959         }
1960 }
1961
1962
1963 /* Jason (similar to void paintface_flush_flags(Object *ob))
1964  * copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
1965  * use in object mode when selecting vertices (while painting) */
1966 void paintvert_flush_flags(Object *ob)
1967 {
1968         Mesh *me= get_mesh(ob);
1969         DerivedMesh *dm= ob->derivedFinal;
1970         MVert *verts, *mv, *mv_orig;
1971         int *index_array = NULL;
1972         int totvert;
1973         int i;
1974         
1975         if(me==NULL || dm==NULL)
1976                 return;
1977
1978         index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
1979         
1980         verts = dm->getVertArray(dm);
1981         totvert = dm->getNumVerts(dm);
1982         
1983         mv= verts;
1984         
1985         for (i= 0; i<totvert; i++, mv++) { /* loop over derived mesh faces */
1986                 if(index_array) {
1987                         mv_orig= me->mvert + index_array[i];
1988                         mv->flag= mv_orig->flag;
1989                 } else {
1990                         mv_orig= me->mvert + i;
1991                         mv->flag= mv_orig->flag;
1992                 }
1993         }
1994 }
1995 /* Jason note: caller needs to run paintvert_flush_flags(ob) after this */
1996 void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
1997 {
1998         Mesh *me;
1999         MVert *mvert;
2000         int a;
2001
2002         me= get_mesh(ob);
2003         if(me==NULL) return;
2004         
2005         if(action == SEL_INVERT) {
2006                 mvert= me->mvert;
2007                 a= me->totvert;
2008                 while(a--) {
2009                         if((mvert->flag & ME_HIDE) == 0) {
2010                                 mvert->flag ^= SELECT;
2011                         }
2012                         mvert++;
2013                 }
2014         }
2015         else {
2016                 if (action == SEL_TOGGLE) {
2017                         action = SEL_SELECT;
2018
2019                         mvert= me->mvert;
2020                         a= me->totvert;
2021                         while(a--) {
2022                                 if((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
2023                                         action = SEL_DESELECT;
2024                                         break;
2025                                 }
2026                                 mvert++;
2027                         }
2028                 }
2029
2030                 mvert= me->mvert;
2031                 a= me->totvert;
2032                 while(a--) {
2033                         if((mvert->flag & ME_HIDE) == 0) {
2034                                 switch (action) {
2035                                 case SEL_SELECT:
2036                                         mvert->flag |= SELECT;
2037                                         break;
2038                                 case SEL_DESELECT:
2039                                         mvert->flag &= ~SELECT;
2040                                         break;
2041                                 case SEL_INVERT:
2042                                         mvert->flag ^= SELECT;
2043                                         break;
2044                                 }
2045                         }
2046                         mvert++;
2047                 }
2048         }
2049
2050         if(flush_flags) {
2051                 paintvert_flush_flags(ob);
2052         }
2053 }