Curves: save active point to file
[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 "BLF_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_(BLF_I18NCONTEXT_ID_CURVE, "BezierCurve");
75                         case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "BezierCircle");
76                         case CU_PRIM_PATH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "CurvePath");
77                         default:
78                                 return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Curve");
79                 }
80         }
81         else {
82                 switch (stype) {
83                         case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsCurve");
84                         case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsCircle");
85                         case CU_PRIM_PATH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsPath");
86                         default:
87                                 return CTX_DATA_(BLF_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_(BLF_I18NCONTEXT_ID_CURVE, "SurfCurve");
98                 case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfCircle");
99                 case CU_PRIM_PATCH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfPatch");
100                 case CU_PRIM_SPHERE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfSphere");
101                 case CU_PRIM_DONUT: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfTorus");
102                 default:
103                         return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Surface");
104         }
105 }
106
107
108 Nurb *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         View3D *v3d = CTX_wm_view3d(C);
113         RegionView3D *rv3d = ED_view3d_context_rv3d(C);
114         Nurb *nu = NULL;
115         BezTriple *bezt;
116         BPoint *bp;
117         Curve *cu = (Curve *)obedit->data;
118         float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f};
119         float umat[4][4] = MAT4_UNITY, viewmat[4][4] = MAT4_UNITY;
120         float fac;
121         int a, b;
122         const float grid = v3d ? v3d->grid : 1.0f;
123         const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
124         const int stype = (type & CU_PRIMITIVE);
125         const int force_3d = ((Curve *)obedit->data)->flag & CU_3D; /* could be adding to an existing 3D curve */
126
127         if (rv3d) {
128                 copy_m4_m4(viewmat, rv3d->viewmat);
129                 copy_v3_v3(zvec, rv3d->viewinv[2]);
130         }
131
132         BKE_nurbList_flag_set(editnurb, 0);
133
134         /* these types call this function to return a Nurb */
135         if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) {
136                 nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim");
137                 nu->type = cutype;
138                 nu->resolu = cu->resolu;
139                 nu->resolv = cu->resolv;
140         }
141
142         switch (stype) {
143                 case CU_PRIM_CURVE: /* curve */
144                         nu->resolu = cu->resolu;
145                         if (cutype == CU_BEZIER) {
146                                 if (!force_3d) nu->flag |= CU_2D;
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                                 if (!force_3d) nu->flag |= CU_2D;
249                                 nu->pntsu = 4;
250                                 nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1");
251                                 nu->flagu = CU_NURB_CYCLIC;
252                                 bezt = nu->bezt;
253
254                                 bezt->h1 = bezt->h2 = HD_AUTO;
255                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
256                                 bezt->vec[1][0] += -grid;
257                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
258                                 bezt->radius = bezt->weight = 1.0;
259
260                                 bezt++;
261                                 bezt->h1 = bezt->h2 = HD_AUTO;
262                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
263                                 bezt->vec[1][1] += grid;
264                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
265                                 bezt->radius = bezt->weight = 1.0;
266
267                                 bezt++;
268                                 bezt->h1 = bezt->h2 = HD_AUTO;
269                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
270                                 bezt->vec[1][0] += grid;
271                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
272                                 bezt->radius = bezt->weight = 1.0;
273
274                                 bezt++;
275                                 bezt->h1 = bezt->h2 = HD_AUTO;
276                                 bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
277                                 bezt->vec[1][1] += -grid;
278                                 for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
279                                 bezt->radius = bezt->weight = 1.0;
280
281                                 BKE_nurb_handles_calc(nu);
282                         }
283                         else if (cutype == CU_NURBS) { /* nurb */
284                                 nu->pntsu = 8;
285                                 nu->pntsv = 1;
286                                 nu->orderu = 4;
287                                 nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6");
288                                 nu->flagu = CU_NURB_CYCLIC;
289                                 bp = nu->bp;
290
291                                 for (a = 0; a < 8; a++) {
292                                         bp->f1 = SELECT;
293                                         if (xzproj == 0) {
294                                                 bp->vec[0] += nurbcircle[a][0] * grid;
295                                                 bp->vec[1] += nurbcircle[a][1] * grid;
296                                         }
297                                         else {
298                                                 bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid;
299                                                 bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
300                                         }
301                                         if (a & 1) bp->vec[3] = 0.25 * M_SQRT2;
302                                         else bp->vec[3] = 1.0;
303                                         mul_m4_v3(mat, bp->vec);
304                                         bp->radius = bp->weight = 1.0;
305
306                                         bp++;
307                                 }
308
309                                 BKE_nurb_knot_calc_u(nu);
310                         }
311                         break;
312                 case CU_PRIM_PATCH: /* 4x4 patch */
313                         if (cutype == CU_NURBS) { /* nurb */
314
315                                 nu->pntsu = 4;
316                                 nu->pntsv = 4;
317                                 nu->orderu = 4;
318                                 nu->orderv = 4;
319                                 nu->flag = CU_SMOOTH;
320                                 nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6");
321                                 nu->flagu = 0;
322                                 nu->flagv = 0;
323                                 bp = nu->bp;
324
325                                 for (a = 0; a < 4; a++) {
326                                         for (b = 0; b < 4; b++) {
327                                                 bp->f1 = SELECT;
328                                                 fac = (float)a - 1.5f;
329                                                 bp->vec[0] += fac * grid;
330                                                 fac = (float)b - 1.5f;
331                                                 bp->vec[1] += fac * grid;
332                                                 if ((a == 1 || a == 2) && (b == 1 || b == 2)) {
333                                                         bp->vec[2] += grid;
334                                                 }
335                                                 mul_m4_v3(mat, bp->vec);
336                                                 bp->vec[3] = 1.0;
337                                                 bp++;
338                                         }
339                                 }
340
341                                 BKE_nurb_knot_calc_u(nu);
342                                 BKE_nurb_knot_calc_v(nu);
343                         }
344                         break;
345                 case CU_PRIM_TUBE: /* Cylinder */
346                         if (cutype == CU_NURBS) {
347                                 nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
348                                 nu->resolu = cu->resolu;
349                                 nu->flag = CU_SMOOTH;
350                                 BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
351                                 vec[0] = vec[1] = 0.0;
352                                 vec[2] = -grid;
353
354                                 mul_mat3_m4_v3(mat, vec);
355
356                                 ed_editnurb_translate_flag(editnurb, 1, vec);
357                                 ed_editnurb_extrude_flag(cu->editnurb, 1);
358                                 mul_v3_fl(vec, -2.0f);
359                                 ed_editnurb_translate_flag(editnurb, 1, vec);
360
361                                 BLI_remlink(editnurb, nu);
362
363                                 a = nu->pntsu * nu->pntsv;
364                                 bp = nu->bp;
365                                 while (a-- > 0) {
366                                         bp->f1 |= SELECT;
367                                         bp++;
368                                 }
369                         }
370                         break;
371                 case CU_PRIM_SPHERE: /* sphere */
372                         if (cutype == CU_NURBS) {
373                                 float tmp_cent[3] = {0.f, 0.f, 0.f};
374                                 float tmp_vec[3] = {0.f, 0.f, 1.f};
375
376                                 nu->pntsu = 5;
377                                 nu->pntsv = 1;
378                                 nu->orderu = 3;
379                                 nu->resolu = cu->resolu;
380                                 nu->resolv = cu->resolv;
381                                 nu->flag = CU_SMOOTH;
382                                 nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6");
383                                 nu->flagu = 0;
384                                 bp = nu->bp;
385
386                                 for (a = 0; a < 5; a++) {
387                                         bp->f1 = SELECT;
388                                         bp->vec[0] += nurbcircle[a][0] * grid;
389                                         bp->vec[2] += nurbcircle[a][1] * grid;
390                                         if (a & 1) bp->vec[3] = 0.5 * M_SQRT2;
391                                         else bp->vec[3] = 1.0;
392                                         mul_m4_v3(mat, bp->vec);
393                                         bp++;
394                                 }
395                                 nu->flagu = CU_NURB_BEZIER;
396                                 BKE_nurb_knot_calc_u(nu);
397
398                                 BLI_addtail(editnurb, nu); /* temporal for spin */
399
400                                 if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0)
401                                         ed_editnurb_spin(umat, obedit, tmp_vec, tmp_cent);
402                                 else if ((U.flag & USER_ADD_VIEWALIGNED))
403                                         ed_editnurb_spin(viewmat, obedit, zvec, mat[3]);
404                                 else
405                                         ed_editnurb_spin(umat, obedit, tmp_vec, mat[3]);
406
407                                 BKE_nurb_knot_calc_v(nu);
408
409                                 a = nu->pntsu * nu->pntsv;
410                                 bp = nu->bp;
411                                 while (a-- > 0) {
412                                         bp->f1 |= SELECT;
413                                         bp++;
414                                 }
415                                 BLI_remlink(editnurb, nu);
416                         }
417                         break;
418                 case CU_PRIM_DONUT: /* torus */
419                         if (cutype == CU_NURBS) {
420                                 float tmp_cent[3] = {0.f, 0.f, 0.f};
421                                 float tmp_vec[3] = {0.f, 0.f, 1.f};
422
423                                 xzproj = 1;
424                                 nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
425                                 xzproj = 0;
426                                 nu->resolu = cu->resolu;
427                                 nu->resolv = cu->resolv;
428                                 nu->flag = CU_SMOOTH;
429                                 BLI_addtail(editnurb, nu); /* temporal for spin */
430
431                                 /* same as above */
432                                 if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0)
433                                         ed_editnurb_spin(umat, obedit, tmp_vec, tmp_cent);
434                                 else if ((U.flag & USER_ADD_VIEWALIGNED))
435                                         ed_editnurb_spin(viewmat, obedit, zvec, mat[3]);
436                                 else
437                                         ed_editnurb_spin(umat, obedit, tmp_vec, mat[3]);
438
439
440                                 BLI_remlink(editnurb, nu);
441
442                                 a = nu->pntsu * nu->pntsv;
443                                 bp = nu->bp;
444                                 while (a-- > 0) {
445                                         bp->f1 |= SELECT;
446                                         bp++;
447                                 }
448
449                         }
450                         break;
451
452                 default: /* should never happen */
453                         BLI_assert(!"invalid nurbs type");
454                         return NULL;
455         }
456
457         BLI_assert(nu != NULL);
458
459         if (nu) { /* should always be set */
460                 nu->flag |= CU_SMOOTH;
461                 cu->actnu = BLI_countlist(editnurb);
462                 cu->actvert = CU_ACT_NONE;
463
464                 BKE_nurb_test2D(nu);
465         }
466
467         return nu;
468 }
469
470 static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
471 {
472         Object *obedit = CTX_data_edit_object(C);
473         ListBase *editnurb;
474         Nurb *nu;
475         bool newob = false;
476         bool enter_editmode;
477         unsigned int layer;
478         float dia;
479         float loc[3], rot[3];
480         float mat[4][4];
481
482         WM_operator_view3d_unit_defaults(C, op);
483
484         if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
485                 return OPERATOR_CANCELLED;
486
487         if (!isSurf) { /* adding curve */
488                 if (obedit == NULL || obedit->type != OB_CURVE) {
489                         Curve *cu;
490
491                         obedit = ED_object_add_type(C, OB_CURVE, loc, rot, true, layer);
492                         newob = true;
493
494                         cu = (Curve *)obedit->data;
495                         cu->flag |= CU_DEFORM_FILL;
496
497                         if (type & CU_PRIM_PATH)
498                                 cu->flag |= CU_PATH | CU_3D;
499                 }
500                 else {
501                         DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
502                 }
503         }
504         else { /* adding surface */
505                 if (obedit == NULL || obedit->type != OB_SURF) {
506                         obedit = ED_object_add_type(C, OB_SURF, loc, rot, true, layer);
507                         newob = true;
508                 }
509                 else {
510                         DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
511                 }
512         }
513
514         /* rename here, the undo stack checks name for valid undo pushes */
515         if (newob) {
516                 if (obedit->type == OB_CURVE) {
517                         rename_id((ID *)obedit, get_curve_defname(type));
518                         rename_id((ID *)obedit->data, get_curve_defname(type));
519                 }
520                 else {
521                         rename_id((ID *)obedit, get_surf_defname(type));
522                         rename_id((ID *)obedit->data, get_surf_defname(type));
523                 }
524         }
525
526         /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */
527         if (newob && enter_editmode)
528                 ED_undo_push(C, "Enter Editmode");
529
530         ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
531         dia = RNA_float_get(op->ptr, "radius");
532         mat[0][0] *= dia;
533         mat[1][1] *= dia;
534         mat[2][2] *= dia;
535
536         nu = add_nurbs_primitive(C, obedit, mat, type, newob);
537         editnurb = object_editcurve_get(obedit);
538         BLI_addtail(editnurb, nu);
539
540         /* userdef */
541         if (newob && !enter_editmode) {
542                 ED_object_editmode_exit(C, EM_FREEDATA);
543         }
544
545         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
546
547         return OPERATOR_FINISHED;
548 }
549
550 static int curve_prim_add(bContext *C, wmOperator *op, int type)
551 {
552         return curvesurf_prim_add(C, op, type, 0);
553 }
554
555 static int surf_prim_add(bContext *C, wmOperator *op, int type)
556 {
557         return curvesurf_prim_add(C, op, type, 1);
558 }
559
560 /* ******************** Curves ******************* */
561
562 static int add_primitive_bezier_exec(bContext *C, wmOperator *op)
563 {
564         return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE);
565 }
566
567 void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot)
568 {
569         /* identifiers */
570         ot->name = "Add Bezier";
571         ot->description = "Construct a Bezier Curve";
572         ot->idname = "CURVE_OT_primitive_bezier_curve_add";
573
574         /* api callbacks */
575         ot->exec = add_primitive_bezier_exec;
576         ot->poll = ED_operator_scene_editable;
577
578         /* flags */
579         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
580
581         ED_object_add_unit_props(ot);
582         ED_object_add_generic_props(ot, true);
583 }
584
585 static int add_primitive_bezier_circle_exec(bContext *C, wmOperator *op)
586 {
587         return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE);
588 }
589
590 void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot)
591 {
592         /* identifiers */
593         ot->name = "Add Bezier Circle";
594         ot->description = "Construct a Bezier Circle";
595         ot->idname = "CURVE_OT_primitive_bezier_circle_add";
596
597         /* api callbacks */
598         ot->exec = add_primitive_bezier_circle_exec;
599         ot->poll = ED_operator_scene_editable;
600
601         /* flags */
602         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
603
604         ED_object_add_unit_props(ot);
605         ED_object_add_generic_props(ot, true);
606 }
607
608 static int add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op)
609 {
610         return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE);
611 }
612
613 void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot)
614 {
615         /* identifiers */
616         ot->name = "Add Nurbs Curve";
617         ot->description = "Construct a Nurbs Curve";
618         ot->idname = "CURVE_OT_primitive_nurbs_curve_add";
619
620         /* api callbacks */
621         ot->exec = add_primitive_nurbs_curve_exec;
622         ot->poll = ED_operator_scene_editable;
623
624         /* flags */
625         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
626
627         ED_object_add_unit_props(ot);
628         ED_object_add_generic_props(ot, true);
629 }
630
631 static int add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op)
632 {
633         return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE);
634 }
635
636 void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot)
637 {
638         /* identifiers */
639         ot->name = "Add Nurbs Circle";
640         ot->description = "Construct a Nurbs Circle";
641         ot->idname = "CURVE_OT_primitive_nurbs_circle_add";
642
643         /* api callbacks */
644         ot->exec = add_primitive_nurbs_circle_exec;
645         ot->poll = ED_operator_scene_editable;
646
647         /* flags */
648         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
649
650         ED_object_add_unit_props(ot);
651         ED_object_add_generic_props(ot, true);
652 }
653
654 static int add_primitive_curve_path_exec(bContext *C, wmOperator *op)
655 {
656         return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH);
657 }
658
659 void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot)
660 {
661         /* identifiers */
662         ot->name = "Add Path";
663         ot->description = "Construct a Path";
664         ot->idname = "CURVE_OT_primitive_nurbs_path_add";
665
666         /* api callbacks */
667         ot->exec = add_primitive_curve_path_exec;
668         ot->poll = ED_operator_scene_editable;
669
670         /* flags */
671         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
672
673         ED_object_add_unit_props(ot);
674         ED_object_add_generic_props(ot, true);
675 }
676
677 /* **************** NURBS surfaces ********************** */
678 static int add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op)
679 {
680         return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS);
681 }
682
683 void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot)
684 {
685         /* identifiers */
686         ot->name = "Add Surface Curve";
687         ot->description = "Construct a Nurbs surface Curve";
688         ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add";
689
690         /* api callbacks */
691         ot->exec = add_primitive_nurbs_surface_curve_exec;
692         ot->poll = ED_operator_scene_editable;
693
694         /* flags */
695         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
696
697         ED_object_add_unit_props(ot);
698         ED_object_add_generic_props(ot, true);
699 }
700
701 static int add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op)
702 {
703         return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS);
704 }
705
706 void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot)
707 {
708         /* identifiers */
709         ot->name = "Add Surface Circle";
710         ot->description = "Construct a Nurbs surface Circle";
711         ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add";
712
713         /* api callbacks */
714         ot->exec = add_primitive_nurbs_surface_circle_exec;
715         ot->poll = ED_operator_scene_editable;
716
717         /* flags */
718         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
719
720         ED_object_add_unit_props(ot);
721         ED_object_add_generic_props(ot, true);
722 }
723
724 static int add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op)
725 {
726         return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS);
727 }
728
729 void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot)
730 {
731         /* identifiers */
732         ot->name = "Add Surface Patch";
733         ot->description = "Construct a Nurbs surface Patch";
734         ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add";
735
736         /* api callbacks */
737         ot->exec = add_primitive_nurbs_surface_surface_exec;
738         ot->poll = ED_operator_scene_editable;
739
740         /* flags */
741         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
742
743         ED_object_add_unit_props(ot);
744         ED_object_add_generic_props(ot, true);
745 }
746
747 static int add_primitive_nurbs_surface_cylinder_exec(bContext *C, wmOperator *op)
748 {
749         return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS);
750 }
751
752 void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot)
753 {
754         /* identifiers */
755         ot->name = "Add Surface Cylinder";
756         ot->description = "Construct a Nurbs surface Cylinder";
757         ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add";
758
759         /* api callbacks */
760         ot->exec = add_primitive_nurbs_surface_cylinder_exec;
761         ot->poll = ED_operator_scene_editable;
762
763         /* flags */
764         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
765
766         ED_object_add_unit_props(ot);
767         ED_object_add_generic_props(ot, true);
768 }
769
770 static int add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op)
771 {
772         return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS);
773 }
774
775 void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot)
776 {
777         /* identifiers */
778         ot->name = "Add Surface Sphere";
779         ot->description = "Construct a Nurbs surface Sphere";
780         ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add";
781
782         /* api callbacks */
783         ot->exec = add_primitive_nurbs_surface_sphere_exec;
784         ot->poll = ED_operator_scene_editable;
785
786         /* flags */
787         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
788
789         ED_object_add_unit_props(ot);
790         ED_object_add_generic_props(ot, true);
791 }
792
793 static int add_primitive_nurbs_surface_torus_exec(bContext *C, wmOperator *op)
794 {
795         return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS);
796 }
797
798 void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot)
799 {
800         /* identifiers */
801         ot->name = "Add Surface Torus";
802         ot->description = "Construct a Nurbs surface Torus";
803         ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add";
804
805         /* api callbacks */
806         ot->exec = add_primitive_nurbs_surface_torus_exec;
807         ot->poll = ED_operator_scene_editable;
808
809         /* flags */
810         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
811
812         ED_object_add_unit_props(ot);
813         ED_object_add_generic_props(ot, true);
814 }