Renaming: sl > scene_layer
[blender.git] / source / blender / editors / curve / editcurve_add.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/curve/editcurve_add.c
29  *  \ingroup edcurve
30  */
31
32 #include "DNA_object_types.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_anim_types.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_math.h"
40
41 #include "BLT_translation.h"
42
43 #include "BKE_context.h"
44 #include "BKE_curve.h"
45 #include "BKE_depsgraph.h"
46 #include "BKE_library.h"
47
48 #include "RNA_access.h"
49
50 #include "WM_api.h"
51 #include "WM_types.h"
52
53 #include "ED_object.h"
54 #include "ED_screen.h"
55 #include "ED_util.h"
56 #include "ED_view3d.h"
57 #include "ED_curve.h"
58
59 #include "curve_intern.h"
60
61 static const float nurbcircle[8][2] = {
62         {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0,  1.0},
63         {0.0,  1.0}, { 1.0,  1.0}, { 1.0, 0.0}, { 1.0, -1.0}
64 };
65
66 /************ add primitive, used by object/ module ****************/
67
68 static const char *get_curve_defname(int type)
69 {
70         int stype = type & CU_PRIMITIVE;
71
72         if ((type & CU_TYPE) == CU_BEZIER) {
73                 switch (stype) {
74                         case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCurve");
75                         case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCircle");
76                         case CU_PRIM_PATH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "CurvePath");
77                         default:
78                                 return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve");
79                 }
80         }
81         else {
82                 switch (stype) {
83                         case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCurve");
84                         case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCircle");
85                         case CU_PRIM_PATH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsPath");
86                         default:
87                                 return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve");
88                 }
89         }
90 }
91
92 static const char *get_surf_defname(int type)
93 {
94         int stype = type & CU_PRIMITIVE;
95
96         switch (stype) {
97                 case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCurve");
98                 case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCircle");
99                 case CU_PRIM_PATCH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfPatch");
100                 case CU_PRIM_SPHERE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfSphere");
101                 case CU_PRIM_DONUT: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfTorus");
102                 default:
103                         return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Surface");
104         }
105 }
106
107
108 Nurb *ED_curve_add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob)
109 {
110         static int xzproj = 0;   /* this function calls itself... */
111         ListBase *editnurb = object_editcurve_get(obedit);
112         RegionView3D *rv3d = ED_view3d_context_rv3d(C);
113         Nurb *nu = NULL;
114         BezTriple *bezt;
115         BPoint *bp;
116         Curve *cu = (Curve *)obedit->data;
117         float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f};
118         float umat[4][4], viewmat[4][4];
119         float fac;
120         int a, b;
121         const float grid = 1.0f;
122         const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
123         const int stype = (type & CU_PRIMITIVE);
124
125         unit_m4(umat);
126         unit_m4(viewmat);
127
128         if (rv3d) {
129                 copy_m4_m4(viewmat, rv3d->viewmat);
130                 copy_v3_v3(zvec, rv3d->viewinv[2]);
131         }
132
133         BKE_nurbList_flag_set(editnurb, 0);
134
135         /* these types call this function to return a Nurb */
136         if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) {
137                 nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim");
138                 nu->type = cutype;
139                 nu->resolu = cu->resolu;
140                 nu->resolv = cu->resolv;
141         }
142
143         switch (stype) {
144                 case CU_PRIM_CURVE: /* curve */
145                         nu->resolu = cu->resolu;
146                         if (cutype == CU_BEZIER) {
147                                 nu->pntsu = 2;
148                                 nu->bezt = (BezTriple *)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1");
149                                 bezt = nu->bezt;
150                                 bezt->h1 = bezt->h2 = HD_ALIGN;
151                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
152                                 bezt->radius = 1.0;
153
154                                 bezt->vec[1][0] += -grid;
155                                 bezt->vec[0][0] += -1.5f * grid;
156                                 bezt->vec[0][1] += -0.5f * grid;
157                                 bezt->vec[2][0] += -0.5f * grid;
158                                 bezt->vec[2][1] +=  0.5f * grid;
159                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
160
161                                 bezt++;
162                                 bezt->h1 = bezt->h2 = HD_ALIGN;
163                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
164                                 bezt->radius = bezt->weight = 1.0;
165
166                                 bezt->vec[0][0] = 0;
167                                 bezt->vec[0][1] = 0;
168                                 bezt->vec[1][0] = grid;
169                                 bezt->vec[1][1] = 0;
170                                 bezt->vec[2][0] = grid * 2;
171                                 bezt->vec[2][1] = 0;
172                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
173
174                                 BKE_nurb_handles_calc(nu);
175                         }
176                         else {
177
178                                 nu->pntsu = 4;
179                                 nu->pntsv = 1;
180                                 nu->orderu = 4;
181                                 nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3");
182
183                                 bp = nu->bp;
184                                 for (a = 0; a < 4; a++, bp++) {
185                                         bp->vec[3] = 1.0;
186                                         bp->f1 = SELECT;
187                                         bp->radius = bp->weight = 1.0;
188                                 }
189
190                                 bp = nu->bp;
191                                 bp->vec[0] += -1.5f * grid;
192                                 bp++;
193                                 bp->vec[0] += -grid;
194                                 bp->vec[1] +=  grid;
195                                 bp++;
196                                 bp->vec[0] += grid;
197                                 bp->vec[1] += grid;
198                                 bp++;
199                                 bp->vec[0] += 1.5f * grid;
200
201                                 bp = nu->bp;
202                                 for (a = 0; a < 4; a++, bp++) mul_m4_v3(mat, bp->vec);
203
204                                 if (cutype == CU_NURBS) {
205                                         nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
206                                         BKE_nurb_knot_calc_u(nu);
207                                 }
208
209                         }
210                         break;
211                 case CU_PRIM_PATH: /* 5 point path */
212                         nu->pntsu = 5;
213                         nu->pntsv = 1;
214                         nu->orderu = 5;
215                         nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
216                         nu->resolu = cu->resolu;
217                         nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3");
218
219                         bp = nu->bp;
220                         for (a = 0; a < 5; a++, bp++) {
221                                 bp->vec[3] = 1.0;
222                                 bp->f1 = SELECT;
223                                 bp->radius = bp->weight = 1.0;
224                         }
225
226                         bp = nu->bp;
227                         bp->vec[0] += -2.0f * grid;
228                         bp++;
229                         bp->vec[0] += -grid;
230                         bp++; bp++;
231                         bp->vec[0] += grid;
232                         bp++;
233                         bp->vec[0] += 2.0f * grid;
234
235                         bp = nu->bp;
236                         for (a = 0; a < 5; a++, bp++) mul_m4_v3(mat, bp->vec);
237
238                         if (cutype == CU_NURBS) {
239                                 nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
240                                 BKE_nurb_knot_calc_u(nu);
241                         }
242
243                         break;
244                 case CU_PRIM_CIRCLE: /* circle */
245                         nu->resolu = cu->resolu;
246
247                         if (cutype == CU_BEZIER) {
248                                 nu->pntsu = 4;
249                                 nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1");
250                                 nu->flagu = CU_NURB_CYCLIC;
251                                 bezt = nu->bezt;
252
253                                 bezt->h1 = bezt->h2 = HD_AUTO;
254                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
255                                 bezt->vec[1][0] += -grid;
256                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
257                                 bezt->radius = bezt->weight = 1.0;
258
259                                 bezt++;
260                                 bezt->h1 = bezt->h2 = HD_AUTO;
261                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
262                                 bezt->vec[1][1] += grid;
263                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
264                                 bezt->radius = bezt->weight = 1.0;
265
266                                 bezt++;
267                                 bezt->h1 = bezt->h2 = HD_AUTO;
268                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
269                                 bezt->vec[1][0] += grid;
270                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
271                                 bezt->radius = bezt->weight = 1.0;
272
273                                 bezt++;
274                                 bezt->h1 = bezt->h2 = HD_AUTO;
275                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
276                                 bezt->vec[1][1] += -grid;
277                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
278                                 bezt->radius = bezt->weight = 1.0;
279
280                                 BKE_nurb_handles_calc(nu);
281                         }
282                         else if (cutype == CU_NURBS) { /* nurb */
283                                 nu->pntsu = 8;
284                                 nu->pntsv = 1;
285                                 nu->orderu = 4;
286                                 nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6");
287                                 nu->flagu = CU_NURB_CYCLIC;
288                                 bp = nu->bp;
289
290                                 for (a = 0; a < 8; a++) {
291                                         bp->f1 = SELECT;
292                                         if (xzproj == 0) {
293                                                 bp->vec[0] += nurbcircle[a][0] * grid;
294                                                 bp->vec[1] += nurbcircle[a][1] * grid;
295                                         }
296                                         else {
297                                                 bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid;
298                                                 bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
299                                         }
300                                         if (a & 1) bp->vec[3] = 0.25 * M_SQRT2;
301                                         else bp->vec[3] = 1.0;
302                                         mul_m4_v3(mat, bp->vec);
303                                         bp->radius = bp->weight = 1.0;
304
305                                         bp++;
306                                 }
307
308                                 BKE_nurb_knot_calc_u(nu);
309                         }
310                         break;
311                 case CU_PRIM_PATCH: /* 4x4 patch */
312                         if (cutype == CU_NURBS) { /* nurb */
313
314                                 nu->pntsu = 4;
315                                 nu->pntsv = 4;
316                                 nu->orderu = 4;
317                                 nu->orderv = 4;
318                                 nu->flag = CU_SMOOTH;
319                                 nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6");
320                                 nu->flagu = 0;
321                                 nu->flagv = 0;
322                                 bp = nu->bp;
323
324                                 for (a = 0; a < 4; a++) {
325                                         for (b = 0; b < 4; b++) {
326                                                 bp->f1 = SELECT;
327                                                 fac = (float)a - 1.5f;
328                                                 bp->vec[0] += fac * grid;
329                                                 fac = (float)b - 1.5f;
330                                                 bp->vec[1] += fac * grid;
331                                                 if ((a == 1 || a == 2) && (b == 1 || b == 2)) {
332                                                         bp->vec[2] += grid;
333                                                 }
334                                                 mul_m4_v3(mat, bp->vec);
335                                                 bp->vec[3] = 1.0;
336                                                 bp++;
337                                         }
338                                 }
339
340                                 BKE_nurb_knot_calc_u(nu);
341                                 BKE_nurb_knot_calc_v(nu);
342                         }
343                         break;
344                 case CU_PRIM_TUBE: /* Cylinder */
345                         if (cutype == CU_NURBS) {
346                                 nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
347                                 nu->resolu = cu->resolu;
348                                 nu->flag = CU_SMOOTH;
349                                 BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
350                                 vec[0] = vec[1] = 0.0;
351                                 vec[2] = -grid;
352
353                                 mul_mat3_m4_v3(mat, vec);
354
355                                 ed_editnurb_translate_flag(editnurb, SELECT, vec);
356                                 ed_editnurb_extrude_flag(cu->editnurb, SELECT);
357                                 mul_v3_fl(vec, -2.0f);
358                                 ed_editnurb_translate_flag(editnurb, SELECT, vec);
359
360                                 BLI_remlink(editnurb, nu);
361
362                                 a = nu->pntsu * nu->pntsv;
363                                 bp = nu->bp;
364                                 while (a-- > 0) {
365                                         bp->f1 |= SELECT;
366                                         bp++;
367                                 }
368                         }
369                         break;
370                 case CU_PRIM_SPHERE: /* sphere */
371                         if (cutype == CU_NURBS) {
372                                 float tmp_cent[3] = {0.f, 0.f, 0.f};
373                                 float tmp_vec[3] = {0.f, 0.f, 1.f};
374
375                                 nu->pntsu = 5;
376                                 nu->pntsv = 1;
377                                 nu->orderu = 3;
378                                 nu->resolu = cu->resolu;
379                                 nu->resolv = cu->resolv;
380                                 nu->flag = CU_SMOOTH;
381                                 nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6");
382                                 nu->flagu = 0;
383                                 bp = nu->bp;
384
385                                 for (a = 0; a < 5; a++) {
386                                         bp->f1 = SELECT;
387                                         bp->vec[0] += nurbcircle[a][0] * grid;
388                                         bp->vec[2] += nurbcircle[a][1] * grid;
389                                         if (a & 1) bp->vec[3] = 0.5 * M_SQRT2;
390                                         else bp->vec[3] = 1.0;
391                                         mul_m4_v3(mat, bp->vec);
392                                         bp++;
393                                 }
394                                 nu->flagu = CU_NURB_BEZIER;
395                                 BKE_nurb_knot_calc_u(nu);
396
397                                 BLI_addtail(editnurb, nu); /* temporal for spin */
398
399                                 if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0)
400                                         ed_editnurb_spin(umat, obedit, tmp_vec, tmp_cent);
401                                 else if ((U.flag & USER_ADD_VIEWALIGNED))
402                                         ed_editnurb_spin(viewmat, obedit, zvec, mat[3]);
403                                 else
404                                         ed_editnurb_spin(umat, obedit, tmp_vec, mat[3]);
405
406                                 BKE_nurb_knot_calc_v(nu);
407
408                                 a = nu->pntsu * nu->pntsv;
409                                 bp = nu->bp;
410                                 while (a-- > 0) {
411                                         bp->f1 |= SELECT;
412                                         bp++;
413                                 }
414                                 BLI_remlink(editnurb, nu);
415                         }
416                         break;
417                 case CU_PRIM_DONUT: /* torus */
418                         if (cutype == CU_NURBS) {
419                                 float tmp_cent[3] = {0.f, 0.f, 0.f};
420                                 float tmp_vec[3] = {0.f, 0.f, 1.f};
421
422                                 xzproj = 1;
423                                 nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
424                                 xzproj = 0;
425                                 nu->resolu = cu->resolu;
426                                 nu->resolv = cu->resolv;
427                                 nu->flag = CU_SMOOTH;
428                                 BLI_addtail(editnurb, nu); /* temporal for spin */
429
430                                 /* same as above */
431                                 if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0)
432                                         ed_editnurb_spin(umat, obedit, tmp_vec, tmp_cent);
433                                 else if ((U.flag & USER_ADD_VIEWALIGNED))
434                                         ed_editnurb_spin(viewmat, obedit, zvec, mat[3]);
435                                 else
436                                         ed_editnurb_spin(umat, obedit, tmp_vec, mat[3]);
437
438
439                                 BLI_remlink(editnurb, nu);
440
441                                 a = nu->pntsu * nu->pntsv;
442                                 bp = nu->bp;
443                                 while (a-- > 0) {
444                                         bp->f1 |= SELECT;
445                                         bp++;
446                                 }
447
448                         }
449                         break;
450
451                 default: /* should never happen */
452                         BLI_assert(!"invalid nurbs type");
453                         return NULL;
454         }
455
456         BLI_assert(nu != NULL);
457
458         if (nu) { /* should always be set */
459                 if ((obedit->type != OB_SURF) && ((cu->flag & CU_3D) == 0)) {
460                         nu->flag |= CU_2D;
461                 }
462
463                 nu->flag |= CU_SMOOTH;
464                 cu->actnu = BLI_listbase_count(editnurb);
465                 cu->actvert = CU_ACT_NONE;
466
467                 BKE_nurb_test2D(nu);
468         }
469
470         return nu;
471 }
472
473 static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
474 {
475         Object *obedit = CTX_data_edit_object(C);
476         ListBase *editnurb;
477         Nurb *nu;
478         bool newob = false;
479         bool enter_editmode;
480         unsigned int layer;
481         float dia;
482         float loc[3], rot[3];
483         float mat[4][4];
484
485         WM_operator_view3d_unit_defaults(C, op);
486
487         if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
488                 return OPERATOR_CANCELLED;
489
490         if (!isSurf) { /* adding curve */
491                 if (obedit == NULL || obedit->type != OB_CURVE) {
492                         const char *name = get_curve_defname(type);
493                         Curve *cu;
494
495                         obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, layer);
496                         newob = true;
497
498                         cu = (Curve *)obedit->data;
499                         cu->flag |= CU_DEFORM_FILL;
500
501                         if (type & CU_PRIM_PATH)
502                                 cu->flag |= CU_PATH | CU_3D;
503                 }
504                 else {
505                         DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
506                 }
507         }
508         else { /* adding surface */
509                 if (obedit == NULL || obedit->type != OB_SURF) {
510                         const char *name = get_surf_defname(type);
511                         obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, layer);
512                         newob = true;
513                 }
514                 else {
515                         DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
516                 }
517         }
518
519         /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */
520         if (newob && enter_editmode)
521                 ED_undo_push(C, "Enter Editmode");
522
523         ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
524         dia = RNA_float_get(op->ptr, "radius");
525         mul_mat3_m4_fl(mat, dia);
526
527         nu = ED_curve_add_nurbs_primitive(C, obedit, mat, type, newob);
528         editnurb = object_editcurve_get(obedit);
529         BLI_addtail(editnurb, nu);
530
531         /* userdef */
532         if (newob && !enter_editmode) {
533                 ED_object_editmode_exit(C, EM_FREEDATA);
534         }
535
536         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
537
538         return OPERATOR_FINISHED;
539 }
540
541 static int curve_prim_add(bContext *C, wmOperator *op, int type)
542 {
543         return curvesurf_prim_add(C, op, type, 0);
544 }
545
546 static int surf_prim_add(bContext *C, wmOperator *op, int type)
547 {
548         return curvesurf_prim_add(C, op, type, 1);
549 }
550
551 /* ******************** Curves ******************* */
552
553 static int add_primitive_bezier_exec(bContext *C, wmOperator *op)
554 {
555         return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE);
556 }
557
558 void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot)
559 {
560         /* identifiers */
561         ot->name = "Add Bezier";
562         ot->description = "Construct a Bezier Curve";
563         ot->idname = "CURVE_OT_primitive_bezier_curve_add";
564
565         /* api callbacks */
566         ot->exec = add_primitive_bezier_exec;
567         ot->poll = ED_operator_scene_editable;
568
569         /* flags */
570         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
571
572         ED_object_add_unit_props(ot);
573         ED_object_add_generic_props(ot, true);
574 }
575
576 static int add_primitive_bezier_circle_exec(bContext *C, wmOperator *op)
577 {
578         return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE);
579 }
580
581 void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot)
582 {
583         /* identifiers */
584         ot->name = "Add Bezier Circle";
585         ot->description = "Construct a Bezier Circle";
586         ot->idname = "CURVE_OT_primitive_bezier_circle_add";
587
588         /* api callbacks */
589         ot->exec = add_primitive_bezier_circle_exec;
590         ot->poll = ED_operator_scene_editable;
591
592         /* flags */
593         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
594
595         ED_object_add_unit_props(ot);
596         ED_object_add_generic_props(ot, true);
597 }
598
599 static int add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op)
600 {
601         return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE);
602 }
603
604 void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot)
605 {
606         /* identifiers */
607         ot->name = "Add Nurbs Curve";
608         ot->description = "Construct a Nurbs Curve";
609         ot->idname = "CURVE_OT_primitive_nurbs_curve_add";
610
611         /* api callbacks */
612         ot->exec = add_primitive_nurbs_curve_exec;
613         ot->poll = ED_operator_scene_editable;
614
615         /* flags */
616         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
617
618         ED_object_add_unit_props(ot);
619         ED_object_add_generic_props(ot, true);
620 }
621
622 static int add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op)
623 {
624         return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE);
625 }
626
627 void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot)
628 {
629         /* identifiers */
630         ot->name = "Add Nurbs Circle";
631         ot->description = "Construct a Nurbs Circle";
632         ot->idname = "CURVE_OT_primitive_nurbs_circle_add";
633
634         /* api callbacks */
635         ot->exec = add_primitive_nurbs_circle_exec;
636         ot->poll = ED_operator_scene_editable;
637
638         /* flags */
639         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
640
641         ED_object_add_unit_props(ot);
642         ED_object_add_generic_props(ot, true);
643 }
644
645 static int add_primitive_curve_path_exec(bContext *C, wmOperator *op)
646 {
647         return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH);
648 }
649
650 void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot)
651 {
652         /* identifiers */
653         ot->name = "Add Path";
654         ot->description = "Construct a Path";
655         ot->idname = "CURVE_OT_primitive_nurbs_path_add";
656
657         /* api callbacks */
658         ot->exec = add_primitive_curve_path_exec;
659         ot->poll = ED_operator_scene_editable;
660
661         /* flags */
662         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
663
664         ED_object_add_unit_props(ot);
665         ED_object_add_generic_props(ot, true);
666 }
667
668 /* **************** NURBS surfaces ********************** */
669 static int add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op)
670 {
671         return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS);
672 }
673
674 void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot)
675 {
676         /* identifiers */
677         ot->name = "Add Surface Curve";
678         ot->description = "Construct a Nurbs surface Curve";
679         ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add";
680
681         /* api callbacks */
682         ot->exec = add_primitive_nurbs_surface_curve_exec;
683         ot->poll = ED_operator_scene_editable;
684
685         /* flags */
686         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
687
688         ED_object_add_unit_props(ot);
689         ED_object_add_generic_props(ot, true);
690 }
691
692 static int add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op)
693 {
694         return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS);
695 }
696
697 void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot)
698 {
699         /* identifiers */
700         ot->name = "Add Surface Circle";
701         ot->description = "Construct a Nurbs surface Circle";
702         ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add";
703
704         /* api callbacks */
705         ot->exec = add_primitive_nurbs_surface_circle_exec;
706         ot->poll = ED_operator_scene_editable;
707
708         /* flags */
709         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
710
711         ED_object_add_unit_props(ot);
712         ED_object_add_generic_props(ot, true);
713 }
714
715 static int add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op)
716 {
717         return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS);
718 }
719
720 void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot)
721 {
722         /* identifiers */
723         ot->name = "Add Surface Patch";
724         ot->description = "Construct a Nurbs surface Patch";
725         ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add";
726
727         /* api callbacks */
728         ot->exec = add_primitive_nurbs_surface_surface_exec;
729         ot->poll = ED_operator_scene_editable;
730
731         /* flags */
732         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
733
734         ED_object_add_unit_props(ot);
735         ED_object_add_generic_props(ot, true);
736 }
737
738 static int add_primitive_nurbs_surface_cylinder_exec(bContext *C, wmOperator *op)
739 {
740         return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS);
741 }
742
743 void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot)
744 {
745         /* identifiers */
746         ot->name = "Add Surface Cylinder";
747         ot->description = "Construct a Nurbs surface Cylinder";
748         ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add";
749
750         /* api callbacks */
751         ot->exec = add_primitive_nurbs_surface_cylinder_exec;
752         ot->poll = ED_operator_scene_editable;
753
754         /* flags */
755         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
756
757         ED_object_add_unit_props(ot);
758         ED_object_add_generic_props(ot, true);
759 }
760
761 static int add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op)
762 {
763         return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS);
764 }
765
766 void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot)
767 {
768         /* identifiers */
769         ot->name = "Add Surface Sphere";
770         ot->description = "Construct a Nurbs surface Sphere";
771         ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add";
772
773         /* api callbacks */
774         ot->exec = add_primitive_nurbs_surface_sphere_exec;
775         ot->poll = ED_operator_scene_editable;
776
777         /* flags */
778         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
779
780         ED_object_add_unit_props(ot);
781         ED_object_add_generic_props(ot, true);
782 }
783
784 static int add_primitive_nurbs_surface_torus_exec(bContext *C, wmOperator *op)
785 {
786         return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS);
787 }
788
789 void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot)
790 {
791         /* identifiers */
792         ot->name = "Add Surface Torus";
793         ot->description = "Construct a Nurbs surface Torus";
794         ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add";
795
796         /* api callbacks */
797         ot->exec = add_primitive_nurbs_surface_torus_exec;
798         ot->poll = ED_operator_scene_editable;
799
800         /* flags */
801         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
802
803         ED_object_add_unit_props(ot);
804         ED_object_add_generic_props(ot, true);
805 }