skip assigning vars for inline bmesh flag funcs, just cast.
[blender.git] / source / blender / bmesh / operators / extrudeops.c
1 #include "MEM_guardedalloc.h"
2
3 #include "BLI_utildefines.h"
4
5 #include "BLI_ghash.h"
6 #include "BLI_memarena.h"
7 #include "BLI_blenlib.h"
8 #include "BLI_math.h"
9 #include "BLI_array.h"
10
11 #include "bmesh.h"
12 #include "bmesh_private.h"
13 #include "bmesh_operators_private.h"
14
15 #include <math.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #define EXT_INPUT       1
21 #define EXT_KEEP        2
22 #define EXT_DEL         4
23
24 void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op)
25 {
26         BMOIter siter;
27         BMIter liter, liter2;
28         BMFace *f, *f2, *f3;
29         BMLoop *l, *l2, *l3, *l4;
30         BMEdge **edges = NULL, *e, *laste;
31         BMVert *v, *lastv, *firstv;
32         BLI_array_declare(edges);
33         int i;
34
35         BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
36                 BLI_array_empty(edges);
37                 i = 0;
38                 firstv = lastv = NULL;
39                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
40                         BLI_array_growone(edges);
41
42                         v = BM_Make_Vert(bm, l->v->co, NULL);
43                         BM_Copy_Attributes(bm, bm, l->v, v);
44
45                         if (lastv) {
46                                 e = BM_Make_Edge(bm, lastv, v, l->e, 0);
47                                 edges[i++] = e;
48                         }
49
50                         lastv = v;
51                         laste = l->e;
52                         if (!firstv) firstv = v;
53                 }
54
55                 BLI_array_growone(edges);
56                 e = BM_Make_Edge(bm, v, firstv, laste, 0);
57                 edges[i++] = e;
58
59                 BMO_SetFlag(bm, f, EXT_DEL);
60
61                 f2 = BM_Make_Ngon(bm, edges[0]->v1, edges[0]->v2, edges, f->len, 0);
62                 BMO_SetFlag(bm, f2, EXT_KEEP);
63                 BM_Copy_Attributes(bm, bm, f, f2);
64
65                 l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
66                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
67                         BM_Copy_Attributes(bm, bm, l, l2);
68                         l3 = l->next;
69                         l4 = l2->next;
70
71                         f3 = BM_Make_QuadTri(bm, l3->v, l4->v, l2->v, l->v, f, 0);
72                         
73                         BM_Copy_Attributes(bm, bm, l->next, bm_firstfaceloop(f3));
74                         BM_Copy_Attributes(bm, bm, l->next, bm_firstfaceloop(f3)->next);
75                         BM_Copy_Attributes(bm, bm, l, bm_firstfaceloop(f3)->next->next);
76                         BM_Copy_Attributes(bm, bm, l, bm_firstfaceloop(f3)->next->next->next);
77
78                         l2 = BMIter_Step(&liter2);
79                 }
80         }
81
82         BMO_CallOpf(bm, "del geom=%ff context=%d", EXT_DEL, DEL_ONLYFACES);
83
84         BMO_Flag_To_Slot(bm, op, "faceout", EXT_KEEP, BM_FACE);
85 }
86
87 void bmesh_extrude_onlyedge_exec(BMesh *bm, BMOperator *op)
88 {
89         BMOIter siter;
90         BMOperator dupeop;
91         BMVert *v1, *v2, *v3, *v4;
92         BMEdge *e, *e2;
93         BMFace *f;
94         
95         BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
96                 BMO_SetFlag(bm, e, EXT_INPUT);
97                 BMO_SetFlag(bm, e->v1, EXT_INPUT);
98                 BMO_SetFlag(bm, e->v2, EXT_INPUT);
99         }
100
101         BMO_InitOpf(bm, &dupeop, "dupe geom=%fve", EXT_INPUT);
102         BMO_Exec_Op(bm, &dupeop);
103
104         e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
105         for (; e; e=BMO_IterStep(&siter)) {
106                 e2 = BMO_IterMapVal(&siter);
107                 e2 = *(BMEdge**)e2;
108
109                 if (e->l && e->v1 != e->l->v) {
110                         v1 = e->v1;
111                         v2 = e->v2;
112                         v3 = e2->v2;
113                         v4 = e2->v1;
114                 } else {
115                         v1 = e2->v1;
116                         v2 = e2->v2;
117                         v3 = e->v2;
118                         v4 = e->v1;
119                 }
120                         /*not sure what to do about example face, pass   NULL for now.*/
121                 f = BM_Make_QuadTri(bm, v1, v2, v3, v4, NULL, 0);               
122                 
123                 if (BMO_TestFlag(bm, e, EXT_INPUT))
124                         e = e2;
125                 
126                 BMO_SetFlag(bm, f, EXT_KEEP);
127                 BMO_SetFlag(bm, e, EXT_KEEP);
128                 BMO_SetFlag(bm, e->v1, EXT_KEEP);
129                 BMO_SetFlag(bm, e->v2, EXT_KEEP);
130                 
131         }
132
133         BMO_Finish_Op(bm, &dupeop);
134
135         BMO_Flag_To_Slot(bm, op, "geomout", EXT_KEEP, BM_ALL);
136 }
137
138 void extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
139 {
140         BMOIter siter;
141         BMVert *v, *dupev;
142         BMEdge *e;
143
144         v = BMO_IterNew(&siter, bm, op, "verts", BM_VERT);
145         for (; v; v=BMO_IterStep(&siter)) {
146                 dupev = BM_Make_Vert(bm, v->co, NULL);
147                 copy_v3_v3(dupev->no, v->no);
148                 BM_Copy_Attributes(bm, bm, v, dupev);
149
150                 e = BM_Make_Edge(bm, v, dupev, NULL, 0);
151
152                 BMO_SetFlag(bm, e, EXT_KEEP);
153                 BMO_SetFlag(bm, dupev, EXT_KEEP);
154         }
155
156         BMO_Flag_To_Slot(bm, op, "vertout", EXT_KEEP, BM_VERT);
157         BMO_Flag_To_Slot(bm, op, "edgeout", EXT_KEEP, BM_EDGE);
158 }
159
160 void extrude_edge_context_exec(BMesh *bm, BMOperator *op)
161 {
162         BMOperator dupeop, delop;
163         BMOIter siter;
164         BMIter iter, fiter, viter;
165         BMEdge *e, *newedge /* , *e2 */, *ce;
166         BMLoop *l, *l2;
167         BMVert *verts[4], *v, *v2;
168         BMFace *f;
169         int rlen, found, delorig=0 /*, i */;
170
171         /*initialize our sub-operators*/
172         BMO_Init_Op(&dupeop, "dupe");
173         
174         BMO_Flag_Buffer(bm, op, "edgefacein", EXT_INPUT, BM_EDGE|BM_FACE);
175         
176         /*if one flagged face is bordered by an unflagged face, then we delete
177           original geometry.*/
178         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
179                 if (!BMO_TestFlag(bm, e, EXT_INPUT)) continue;
180
181                 found = 0;
182                 f = BMIter_New(&fiter, bm, BM_FACES_OF_EDGE, e);
183                 for (rlen=0; f; f=BMIter_Step(&fiter), rlen++) {
184                         if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
185                                 found = 1;
186                                 delorig = 1;
187                                 break;
188                         }
189                 }
190                 
191                 if (!found && (rlen > 1)) BMO_SetFlag(bm, e, EXT_DEL);
192         }
193
194         /*calculate verts to delete*/
195         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
196                 found = 0;
197
198                 BM_ITER(e, &viter, bm, BM_EDGES_OF_VERT, v) {
199                         if (!BMO_TestFlag(bm, e, EXT_INPUT)) {
200                                 found = 1;
201                                 break;
202                         }
203                 }
204                 
205                 BM_ITER(f, &viter, bm, BM_FACES_OF_VERT, v) {
206                         if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
207                                 found = 1;
208                                 break;
209                         }
210                 }
211
212                 if (!found) {
213                         BMO_SetFlag(bm, v, EXT_DEL);
214                 }
215         }
216         
217         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
218                 if (BMO_TestFlag(bm, f, EXT_INPUT))
219                         BMO_SetFlag(bm, f, EXT_DEL);
220         }
221         if (delorig) BMO_InitOpf(bm, &delop, "del geom=%fvef context=%d", 
222                                  EXT_DEL, DEL_ONLYTAGGED);
223
224         BMO_CopySlot(op, &dupeop, "edgefacein", "geom");
225         BMO_Exec_Op(bm, &dupeop);
226
227         if (bm->act_face && BMO_TestFlag(bm, bm->act_face, EXT_INPUT))
228                 bm->act_face = BMO_Get_MapPointer(bm, &dupeop, "facemap", bm->act_face);
229
230         if (delorig) BMO_Exec_Op(bm, &delop);
231         
232         /*if not delorig, reverse loops of original faces*/
233         if (!delorig) {
234                 for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)) {
235                         if (BMO_TestFlag(bm, f, EXT_INPUT)) {
236                                 BM_flip_normal(bm, f);
237                         }
238                 }
239         }
240         
241         BMO_CopySlot(&dupeop, op, "newout", "geomout");
242         e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
243         for (; e; e=BMO_IterStep(&siter)) {
244                 if (BMO_InMap(bm, op, "exclude", e)) continue;
245
246                 newedge = BMO_IterMapVal(&siter);
247                 newedge = *(BMEdge**)newedge;
248                 if (!newedge) continue;
249                 if (!newedge->l) ce = e;
250                 else ce = newedge;
251                 
252                 if (ce->l && (ce->l->v == ce->v1)) {
253                         verts[0] = e->v1;
254                         verts[1] = e->v2;
255                         verts[2] = newedge->v2;
256                         verts[3] = newedge->v1;
257                 } else {
258                         verts[3] = e->v1;
259                         verts[2] = e->v2;
260                         verts[1] = newedge->v2;
261                         verts[0] = newedge->v1;
262                 }
263
264                 /*not sure what to do about example face, pass NULL for now.*/
265                 f = BM_Make_Quadtriangle(bm, verts, NULL, 4, NULL, 0);          
266
267                 /*copy attributes*/
268                 l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
269                 for (; l; l=BMIter_Step(&iter)) {
270                         if (l->e != e && l->e != newedge) continue;
271                         l2 = l->radial_next;
272                         
273                         if (l2 == l) {
274                                 l2 = newedge->l;
275                                 BM_Copy_Attributes(bm, bm, l2->f, l->f);
276
277                                 BM_Copy_Attributes(bm, bm, l2, l);
278                                 l2 = (BMLoop*) l2->next;
279                                 l = (BMLoop*) l->next;
280                                 BM_Copy_Attributes(bm, bm, l2, l);
281                         } else {
282                                 BM_Copy_Attributes(bm, bm, l2->f, l->f);
283
284                                 /*copy data*/
285                                 if (l2->v == l->v) {
286                                         BM_Copy_Attributes(bm, bm, l2, l);
287                                         l2 = (BMLoop*) l2->next;
288                                         l = (BMLoop*) l->next;
289                                         BM_Copy_Attributes(bm, bm, l2, l);
290                                 } else {
291                                         l2 = (BMLoop*) l2->next;
292                                         BM_Copy_Attributes(bm, bm, l2, l);
293                                         l2 = (BMLoop*) l2->prev;
294                                         l = (BMLoop*) l->next;
295                                         BM_Copy_Attributes(bm, bm, l2, l);
296                                 }
297                         }
298                 }
299         }
300
301         /*link isolated verts*/
302         v = BMO_IterNew(&siter, bm, &dupeop, "isovertmap", 0);
303         for (; v; v=BMO_IterStep(&siter)) {
304                 v2 = *((void**)BMO_IterMapVal(&siter));
305                 BM_Make_Edge(bm, v, v2, v->e, 1);
306         }
307
308         /*cleanup*/
309         if (delorig) BMO_Finish_Op(bm, &delop);
310         BMO_Finish_Op(bm, &dupeop);
311 }