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