~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to source/blender/python/api2_2x/CurNurb.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2005-11-06 12:40:03 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051106124003-3pgs7tcg5rox96xg
Tags: 2.37a-1.1
* Non-maintainer upload.
* Split out parts of 01_SConstruct_debian.dpatch again: root_build_dir
  really needs to get adjusted before the clean target runs - closes: #333958,
  see #288882 for reference

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: CurNurb.c,v 1.11 2005/06/13 19:15:01 stiv Exp $
 
3
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (at your option) any later version. The Blender
 
9
 * Foundation also sells licenses for use in proprietary software under
 
10
 * the Blender License.  See http://www.blender.org/BL/ for information
 
11
 * about this.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software Foundation,
 
20
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
21
 *
 
22
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 
23
 * All rights reserved.
 
24
 *
 
25
 * This is a new part of Blender.
 
26
 *
 
27
 * Contributor(s): Stephen Swaney
 
28
 *
 
29
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 
30
 */
 
31
 
 
32
#include "Python.h"
 
33
#include "DNA_curve_types.h"
 
34
#include "BKE_curve.h"
 
35
#include "BDR_editcurve.h"      /* for convertspline */
 
36
#include "MEM_guardedalloc.h"
 
37
 
 
38
#include "gen_utils.h"
 
39
#include "CurNurb.h"
 
40
#include "BezTriple.h"
 
41
 
 
42
 
 
43
/*
 
44
 * forward declarations go here
 
45
 */
 
46
 
 
47
 
 
48
static PyObject *M_CurNurb_New( PyObject * self, PyObject * args );
 
49
PyObject *CurNurb_CreatePyObject( Nurb * blen_nurb );
 
50
static PyObject *CurNurb_setMatIndex( BPy_CurNurb * self, PyObject * args );
 
51
static PyObject *CurNurb_getMatIndex( BPy_CurNurb * self );
 
52
static PyObject *CurNurb_getFlagU( BPy_CurNurb * self );
 
53
static PyObject *CurNurb_setFlagU( BPy_CurNurb * self, PyObject * args );
 
54
static PyObject *CurNurb_getFlagV( BPy_CurNurb * self );
 
55
static PyObject *CurNurb_setFlagV( BPy_CurNurb * self, PyObject * args );
 
56
static PyObject *CurNurb_getType( BPy_CurNurb * self );
 
57
static PyObject *CurNurb_setType( BPy_CurNurb * self, PyObject * args );
 
58
/* static PyObject* CurNurb_setXXX( BPy_CurNurb* self, PyObject* args ); */
 
59
PyObject *CurNurb_getPoint( BPy_CurNurb * self, int index );
 
60
static int CurNurb_setPoint( BPy_CurNurb * self, int index, PyObject * ob );
 
61
static int CurNurb_length( PyInstanceObject * inst );
 
62
static PyObject *CurNurb_getIter( BPy_CurNurb * self );
 
63
static PyObject *CurNurb_iterNext( BPy_CurNurb * self );
 
64
PyObject *CurNurb_append( BPy_CurNurb * self, PyObject * args );
 
65
PyObject *CurNurb_pointAtIndex( Nurb * nurb, int index );
 
66
static PyObject *CurNurb_isNurb( BPy_CurNurb * self );
 
67
static PyObject *CurNurb_isCyclic( BPy_CurNurb * self );
 
68
static PyObject *CurNurb_dump( BPy_CurNurb * self );
 
69
 
 
70
char M_CurNurb_doc[] = "CurNurb";
 
71
 
 
72
 
 
73
/*      
 
74
  CurNurb_Type callback function prototypes:                          
 
75
*/
 
76
 
 
77
static void CurNurb_dealloc( BPy_CurNurb * self );
 
78
static int CurNurb_compare( BPy_CurNurb * a, BPy_CurNurb * b );
 
79
static PyObject *CurNurb_getAttr( BPy_CurNurb * self, char *name );
 
80
static int CurNurb_setAttr( BPy_CurNurb * self, char *name, PyObject * v );
 
81
static PyObject *CurNurb_repr( BPy_CurNurb * self );
 
82
 
 
83
 
 
84
 
 
85
/*
 
86
   table of module methods
 
87
   these are the equivalent of class or static methods.
 
88
   you do not need an object instance to call one.
 
89
  
 
90
*/
 
91
 
 
92
static PyMethodDef M_CurNurb_methods[] = {
 
93
/*   name, method, flags, doc_string                */
 
94
        {"New", ( PyCFunction ) M_CurNurb_New, METH_VARARGS | METH_KEYWORDS,
 
95
         " () - doc string"},
 
96
/*  {"Get", (PyCFunction) M_CurNurb_method, METH_NOARGS, " () - doc string"}, */
 
97
/*   {"method", (PyCFunction) M_CurNurb_method, METH_NOARGS, " () - doc string"}, */
 
98
 
 
99
        {NULL, NULL, 0, NULL}
 
100
};
 
101
 
 
102
 
 
103
 
 
104
/*
 
105
 * method table
 
106
 * table of instance methods
 
107
 * these methods are invoked on an instance of the type.
 
108
*/
 
109
 
 
110
static PyMethodDef BPy_CurNurb_methods[] = {
 
111
/*   name,     method,                    flags,         doc               */
 
112
/*  {"method", (PyCFunction) CurNurb_method, METH_NOARGS, " () - doc string"} */
 
113
        {"setMatIndex", ( PyCFunction ) CurNurb_setMatIndex, METH_VARARGS,
 
114
         "( index ) - set index into materials list"},
 
115
        {"getMatIndex", ( PyCFunction ) CurNurb_getMatIndex, METH_NOARGS,
 
116
         "( ) - get current material index"},
 
117
        {"setFlagU", ( PyCFunction ) CurNurb_setFlagU, METH_VARARGS,
 
118
         "( index ) - set flagU and recalculate the knots (0: uniform, 1: endpoints, 2: bezier)"},
 
119
        {"getFlagU", ( PyCFunction ) CurNurb_getFlagU, METH_NOARGS,
 
120
         "( ) - get flagU of the knots"},
 
121
        {"setFlagV", ( PyCFunction ) CurNurb_setFlagV, METH_VARARGS,
 
122
         "( index ) - set flagV and recalculate the knots (0: uniform, 1: endpoints, 2: bezier)"},
 
123
        {"getFlagV", ( PyCFunction ) CurNurb_getFlagV, METH_NOARGS,
 
124
         "( ) - get flagV of the knots"},
 
125
        {"setType", ( PyCFunction ) CurNurb_setType, METH_VARARGS,
 
126
         "( type ) - change the type of the curve (Poly: 0, Bezier: 1, NURBS: 4)"},
 
127
        {"getType", ( PyCFunction ) CurNurb_getType, METH_NOARGS,
 
128
         "( ) - get the type of the curve (Poly: 0, Bezier: 1, NURBS: 4)"},
 
129
        {"append", ( PyCFunction ) CurNurb_append, METH_VARARGS,
 
130
         "( point ) - add a new point.  arg is BezTriple or list of x,y,z,w floats"},
 
131
        {"isNurb", ( PyCFunction ) CurNurb_isNurb, METH_NOARGS,
 
132
         "( ) - boolean function tests if this spline is type nurb or bezier"},
 
133
        {"isCyclic", ( PyCFunction ) CurNurb_isCyclic, METH_NOARGS,
 
134
         "( ) - boolean function tests if this spline is cyclic (closed) or not (open)"},
 
135
        {"dump", ( PyCFunction ) CurNurb_dump, METH_NOARGS,
 
136
         "( ) - dumps Nurb data)"},
 
137
        {NULL, NULL, 0, NULL}
 
138
};
 
139
 
 
140
/* 
 
141
 *   methods for CurNurb as sequece
 
142
 */
 
143
 
 
144
static PySequenceMethods CurNurb_as_sequence = {
 
145
        ( inquiry ) CurNurb_length,     /* sq_length   */
 
146
        ( binaryfunc ) 0,       /* sq_concat */
 
147
        ( intargfunc ) 0,       /* sq_repeat */
 
148
        ( intargfunc ) CurNurb_getPoint,        /* sq_item */
 
149
        ( intintargfunc ) 0,    /* sq_slice */
 
150
        ( intobjargproc ) CurNurb_setPoint,     /* sq_ass_item */
 
151
        0,                      /* sq_ass_slice */
 
152
        ( objobjproc ) 0,       /* sq_contains */
 
153
        0,
 
154
        0
 
155
};
 
156
 
 
157
 
 
158
 
 
159
/*
 
160
  Object Type definition
 
161
  full blown 2.3 struct
 
162
  if you are having trouble building with an earlier version of python,
 
163
   this is why.
 
164
*/
 
165
 
 
166
PyTypeObject CurNurb_Type = {
 
167
        PyObject_HEAD_INIT( NULL ) /* required py macro */
 
168
        0,      /* ob_size */
 
169
        /*  For printing, in format "<module>.<name>" */
 
170
        "CurNurb",              /* char *tp_name; */
 
171
        sizeof( CurNurb_Type ), /* int tp_basicsize, */
 
172
        0,                      /* tp_itemsize;  For allocation */
 
173
 
 
174
        /* Methods to implement standard operations */
 
175
 
 
176
        ( destructor ) CurNurb_dealloc, /*    destructor tp_dealloc; */
 
177
        0,                      /*    printfunc tp_print; */
 
178
        ( getattrfunc ) CurNurb_getAttr,        /*    getattrfunc tp_getattr; */
 
179
        ( setattrfunc ) CurNurb_setAttr,        /*    setattrfunc tp_setattr; */
 
180
        ( cmpfunc ) CurNurb_compare,    /*    cmpfunc tp_compare; */
 
181
        ( reprfunc ) CurNurb_repr,      /*    reprfunc tp_repr; */
 
182
 
 
183
        /* Method suites for standard classes */
 
184
 
 
185
        0,                      /*    PyNumberMethods *tp_as_number; */
 
186
        &CurNurb_as_sequence,   /*    PySequenceMethods *tp_as_sequence; */
 
187
        0,                      /*    PyMappingMethods *tp_as_mapping; */
 
188
 
 
189
        /* More standard operations (here for binary compatibility) */
 
190
 
 
191
        0,                      /*    hashfunc tp_hash; */
 
192
        0,                      /*    ternaryfunc tp_call; */
 
193
        0,                      /*    reprfunc tp_str; */
 
194
        0,                      /*    getattrofunc tp_getattro; */
 
195
        0,                      /*    setattrofunc tp_setattro; */
 
196
 
 
197
        /* Functions to access object as input/output buffer */
 
198
        0,                      /*    PyBufferProcs *tp_as_buffer; */
 
199
 
 
200
  /*** Flags to define presence of optional/expanded features ***/
 
201
        Py_TPFLAGS_DEFAULT,     /*    long tp_flags; */
 
202
 
 
203
        0,                      /*  char *tp_doc;  Documentation string */
 
204
  /*** Assigned meaning in release 2.0 ***/
 
205
        /* call function for all accessible objects */
 
206
        0,                      /*    traverseproc tp_traverse; */
 
207
 
 
208
        /* delete references to contained objects */
 
209
        0,                      /*    inquiry tp_clear; */
 
210
 
 
211
  /***  Assigned meaning in release 2.1 ***/
 
212
  /*** rich comparisons ***/
 
213
        0,                      /*  richcmpfunc tp_richcompare; */
 
214
 
 
215
  /***  weak reference enabler ***/
 
216
        0,                      /* long tp_weaklistoffset; */
 
217
 
 
218
  /*** Added in release 2.2 ***/
 
219
        /*   Iterators */
 
220
        ( getiterfunc ) CurNurb_getIter,        /*    getiterfunc tp_iter; */
 
221
        ( iternextfunc ) CurNurb_iterNext,      /*    iternextfunc tp_iternext; */
 
222
 
 
223
  /*** Attribute descriptor and subclassing stuff ***/
 
224
        BPy_CurNurb_methods,    /*    struct PyMethodDef *tp_methods; */
 
225
        0,                      /*    struct PyMemberDef *tp_members; */
 
226
        0,                      /*    struct PyGetSetDef *tp_getset; */
 
227
        0,                      /*    struct _typeobject *tp_base; */
 
228
        0,                      /*    PyObject *tp_dict; */
 
229
        0,                      /*    descrgetfunc tp_descr_get; */
 
230
        0,                      /*    descrsetfunc tp_descr_set; */
 
231
        0,                      /*    long tp_dictoffset; */
 
232
        0,                      /*    initproc tp_init; */
 
233
        0,                      /*    allocfunc tp_alloc; */
 
234
        0,                      /*    newfunc tp_new; */
 
235
        /*  Low-level free-memory routine */
 
236
        0,                      /*    freefunc tp_free;  */
 
237
        /* For PyObject_IS_GC */
 
238
        0,                      /*    inquiry tp_is_gc;  */
 
239
        0,                      /*    PyObject *tp_bases; */
 
240
        /* method resolution order */
 
241
        0,                      /*    PyObject *tp_mro;  */
 
242
        0,                      /*    PyObject *tp_cache; */
 
243
        0,                      /*    PyObject *tp_subclasses; */
 
244
        0,                      /*    PyObject *tp_weaklist; */
 
245
        0
 
246
};
 
247
 
 
248
 
 
249
 
 
250
 
 
251
void CurNurb_dealloc( BPy_CurNurb * self )
 
252
{
 
253
        PyObject_DEL( self );
 
254
}
 
255
 
 
256
 
 
257
 
 
258
static PyObject *CurNurb_getAttr( BPy_CurNurb * self, char *name )
 
259
{
 
260
        PyObject *attr = Py_None;
 
261
 
 
262
        if( strcmp( name, "mat_index" ) == 0 )
 
263
                attr = PyInt_FromLong( self->nurb->mat_nr );
 
264
 
 
265
        else if( strcmp( name, "points" ) == 0 )
 
266
                attr = PyInt_FromLong( self->nurb->pntsu );
 
267
 
 
268
        else if( strcmp( name, "flagU" ) == 0 )
 
269
                attr = CurNurb_getFlagU( self );
 
270
 
 
271
        else if( strcmp( name, "flagV" ) == 0 )
 
272
                attr = CurNurb_getFlagV( self );
 
273
 
 
274
        else if( strcmp( name, "type" ) == 0 )
 
275
                attr = CurNurb_getType( self );
 
276
 
 
277
        else if( strcmp( name, "__members__" ) == 0 )
 
278
                attr = Py_BuildValue( "[s,s,s,s,s]", "mat_index", "points", "flagU", "flagV", "type" );
 
279
 
 
280
        if( !attr )
 
281
                return EXPP_ReturnPyObjError( PyExc_MemoryError,
 
282
                                              "couldn't create PyObject" );
 
283
 
 
284
        /* member attribute found, return it */
 
285
        if( attr != Py_None )
 
286
                return attr;
 
287
 
 
288
        /* not an attribute, search the methods table */
 
289
        return Py_FindMethod( BPy_CurNurb_methods, ( PyObject * ) self, name );
 
290
}
 
291
 
 
292
 
 
293
/*
 
294
  setattr
 
295
*/
 
296
 
 
297
static int CurNurb_setAttr( BPy_CurNurb * self, char *name, PyObject * value )
 
298
{
 
299
        PyObject *valtuple;
 
300
        PyObject *error = NULL;
 
301
 
 
302
        /* make a tuple to pass to our type methods */
 
303
        valtuple = Py_BuildValue( "(O)", value );
 
304
 
 
305
        if( !valtuple )
 
306
                return EXPP_ReturnIntError( PyExc_MemoryError,
 
307
                                            "CurNurb.setAttr: cannot create pytuple" );
 
308
 
 
309
        if( strcmp( name, "mat_index" ) == 0 )
 
310
                error = CurNurb_setMatIndex( self, valtuple );
 
311
 
 
312
        else if( strcmp( name, "flagU" ) == 0 )
 
313
                error = CurNurb_setFlagU( self, valtuple );
 
314
 
 
315
        else if( strcmp( name, "flagV" ) == 0 )
 
316
                error = CurNurb_setFlagV( self, valtuple );
 
317
 
 
318
        else if( strcmp( name, "type" ) == 0 )
 
319
                error = CurNurb_setType( self, valtuple );
 
320
 
 
321
        else {                  /* error - no match for name */
 
322
                Py_DECREF( valtuple );
 
323
 
 
324
                if( ( strcmp( name, "ZZZZ" ) == 0 ) ||  /* user tried to change a */
 
325
                    ( strcmp( name, "ZZZZ" ) == 0 ) )   /* constant dict type ... */
 
326
                        return EXPP_ReturnIntError( PyExc_AttributeError,
 
327
                                                    "constant dictionary -- cannot be changed" );
 
328
                else
 
329
                        return EXPP_ReturnIntError( PyExc_KeyError,
 
330
                                                    "attribute not found" );
 
331
        }
 
332
 
 
333
 
 
334
        Py_DECREF( valtuple );  /* since it is not being returned */
 
335
        if( error != Py_None )
 
336
                return -1;
 
337
 
 
338
        Py_DECREF( Py_None );
 
339
        return 0;               /* normal exit */
 
340
}
 
341
 
 
342
/*
 
343
  compare
 
344
  in this case, we consider two CurNurbs equal, if they point to the same
 
345
  blender data.
 
346
*/
 
347
 
 
348
static int CurNurb_compare( BPy_CurNurb * a, BPy_CurNurb * b )
 
349
{
 
350
        Nurb *pa = a->nurb;
 
351
        Nurb *pb = b->nurb;
 
352
 
 
353
        return ( pa == pb ) ? 0 : -1;
 
354
}
 
355
 
 
356
 
 
357
/*
 
358
  factory method to create a BPy_CurNurb from a Blender Nurb
 
359
*/
 
360
 
 
361
PyObject *CurNurb_CreatePyObject( Nurb * blen_nurb )
 
362
{
 
363
        BPy_CurNurb *pyNurb;
 
364
 
 
365
        pyNurb = ( BPy_CurNurb * ) PyObject_NEW( BPy_CurNurb, &CurNurb_Type );
 
366
 
 
367
        if( !pyNurb )
 
368
                return EXPP_ReturnPyObjError( PyExc_MemoryError,
 
369
                                              "could not create BPy_CurNurb PyObject" );
 
370
 
 
371
        pyNurb->nurb = blen_nurb;
 
372
        return ( PyObject * ) pyNurb;
 
373
}
 
374
 
 
375
 
 
376
/*
 
377
 *  CurNurb_repr
 
378
 */
 
379
static PyObject *CurNurb_repr( BPy_CurNurb * self )
 
380
{                               /* used by 'repr' */
 
381
 
 
382
        return PyString_FromFormat( "[CurNurb \"%d\"]", self->nurb->type );
 
383
}
 
384
 
 
385
/* XXX Can't this be simply removed? */
 
386
static PyObject *M_CurNurb_New( PyObject * self, PyObject * args )
 
387
{
 
388
        return ( PyObject * ) 0;
 
389
 
 
390
}
 
391
 
 
392
/*
 
393
 *      Curve.getType
 
394
 */
 
395
static PyObject *CurNurb_getType( BPy_CurNurb * self )
 
396
{
 
397
        /* type is on 3 first bits only */
 
398
        return PyInt_FromLong( self->nurb->type & 7 );
 
399
}
 
400
 
 
401
/*
 
402
 *      Curve.setType
 
403
 *
 
404
 *      Convert the curve using Blender's convertspline fonction
 
405
 */
 
406
static PyObject *CurNurb_setType( BPy_CurNurb * self, PyObject * args )
 
407
{
 
408
        Nurb *nurb = self->nurb;
 
409
        int type;
 
410
 
 
411
        /* parameter type checking */
 
412
        if( !PyArg_ParseTuple( args, "i", &type ) )
 
413
                return EXPP_ReturnPyObjError
 
414
                        ( PyExc_TypeError, "expected integer argument" );
 
415
 
 
416
        /* parameter value checking */
 
417
        if (type != CU_POLY &&
 
418
                type != CU_BEZIER &&
 
419
                type != CU_NURBS)
 
420
                return EXPP_ReturnPyObjError
 
421
                         ( PyExc_ValueError, "expected integer argument" );
 
422
 
 
423
        /* convert and raise error if impossible */
 
424
        if (convertspline(type, nurb))
 
425
                return EXPP_ReturnPyObjError
 
426
                         ( PyExc_ValueError, "Conversion Impossible" );
 
427
 
 
428
        return EXPP_incr_ret( Py_None );
 
429
}
 
430
 
 
431
 
 
432
 
 
433
/*
 
434
 * CurNurb_append( point )
 
435
 * append a new point to a nurb curve.
 
436
 * arg is BezTriple or list of xyzw floats 
 
437
 */
 
438
 
 
439
PyObject *CurNurb_append( BPy_CurNurb * self, PyObject * args )
 
440
{
 
441
        Nurb *nurb = self->nurb;
 
442
 
 
443
        return CurNurb_appendPointToNurb( nurb, args );
 
444
}
 
445
 
 
446
 
 
447
/*
 
448
 * CurNurb_appendPointToNurb
 
449
 * this is a non-bpy utility func to add a point to a given nurb.
 
450
 * notice the first arg is Nurb*.
 
451
 */
 
452
 
 
453
PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * args )
 
454
{
 
455
 
 
456
        int i;
 
457
        int size;
 
458
        PyObject *pyOb;
 
459
        int npoints = nurb->pntsu;
 
460
 
 
461
        /*
 
462
           do we have a list of four floats or a BezTriple?
 
463
        */
 
464
        if( !PyArg_ParseTuple( args, "O", &pyOb ))
 
465
                return EXPP_ReturnPyObjError
 
466
                                ( PyExc_RuntimeError,
 
467
                                  "Internal error parsing arguments" );
 
468
 
 
469
 
 
470
 
 
471
        /* if curve is empty, adjust type depending on input type */
 
472
        if (nurb->bezt==NULL && nurb->bp==NULL) {
 
473
                if (BezTriple_CheckPyObject( pyOb ))
 
474
                        nurb->type |= CU_BEZIER;
 
475
                else if (PySequence_Check( pyOb ))
 
476
                        nurb->type |= CU_NURBS;
 
477
                else
 
478
                        return( EXPP_ReturnPyObjError( PyExc_TypeError,
 
479
                                          "Expected a BezTriple or a Sequence of 4 (or 5) floats" ) );
 
480
        }
 
481
 
 
482
 
 
483
 
 
484
        if ((nurb->type & 7)==CU_BEZIER) {
 
485
                BezTriple *tmp;
 
486
 
 
487
                if( !BezTriple_CheckPyObject( pyOb ) )
 
488
                        return( EXPP_ReturnPyObjError( PyExc_TypeError,
 
489
                                          "Expected a BezTriple\n" ) );
 
490
 
 
491
/*              printf("\ndbg: got a BezTriple\n"); */
 
492
                tmp = nurb->bezt;       /* save old points */
 
493
                nurb->bezt =
 
494
                        ( BezTriple * ) MEM_mallocN( sizeof( BezTriple ) *
 
495
                                                     ( npoints + 1 ),
 
496
                                                     "CurNurb_append2" );
 
497
 
 
498
                if( !nurb->bezt )
 
499
                        return ( EXPP_ReturnPyObjError
 
500
                                 ( PyExc_MemoryError, "allocation failed" ) );
 
501
 
 
502
                /* copy old points to new */
 
503
                memmove( nurb->bezt, tmp, sizeof( BezTriple ) * npoints );
 
504
                if( tmp )
 
505
                        MEM_freeN( tmp );
 
506
                nurb->pntsu++;
 
507
                /* add new point to end of list */
 
508
                memcpy( nurb->bezt + npoints,
 
509
                        BezTriple_FromPyObject( pyOb ), sizeof( BezTriple ) );
 
510
 
 
511
        }
 
512
        else if( PySequence_Check( pyOb ) ) {
 
513
                size = PySequence_Size( pyOb );
 
514
/*              printf("\ndbg: got a sequence of size %d\n", size );  */
 
515
                if( size == 4 || size == 5 ) {
 
516
                        BPoint *tmp;
 
517
 
 
518
                        tmp = nurb->bp; /* save old pts */
 
519
 
 
520
                        nurb->bp =
 
521
                                ( BPoint * ) MEM_mallocN( sizeof( BPoint ) *
 
522
                                                          ( npoints + 1 ),
 
523
                                                          "CurNurb_append1" );
 
524
                        if( !nurb->bp )
 
525
                                return ( EXPP_ReturnPyObjError
 
526
                                         ( PyExc_MemoryError,
 
527
                                           "allocation failed" ) );
 
528
 
 
529
                        memmove( nurb->bp, tmp, sizeof( BPoint ) * npoints );
 
530
                        if( tmp )
 
531
                                MEM_freeN( tmp );
 
532
 
 
533
                        ++nurb->pntsu;
 
534
                        /* initialize new BPoint from old */
 
535
                        memcpy( nurb->bp + npoints, nurb->bp,
 
536
                                sizeof( BPoint ) );
 
537
 
 
538
                        for( i = 0; i < 4; ++i ) {
 
539
                                float tmpx =
 
540
                                        ( float ) PyFloat_AsDouble
 
541
                                        ( PySequence_GetItem( pyOb, i ) );
 
542
                                nurb->bp[npoints].vec[i] = tmpx;
 
543
 
 
544
                        }
 
545
 
 
546
                        if (size == 5) {
 
547
                                nurb->bp[npoints].alfa = (float)PyFloat_AsDouble( PySequence_GetItem( pyOb, 4 ) );
 
548
                        }
 
549
                        else {
 
550
                                nurb->bp[npoints].alfa = 0.0f;
 
551
                        }
 
552
 
 
553
                        makeknots( nurb, 1, nurb->flagu >> 1 );
 
554
 
 
555
                } else if( size == 3 ) {        /* 3 xyz coords */
 
556
                        printf( "\nNot Yet Implemented!\n" );
 
557
 
 
558
                }
 
559
 
 
560
        } else {
 
561
                /* bail with error */
 
562
                return EXPP_ReturnPyObjError( PyExc_TypeError,
 
563
                                        "expected a sequence of 4 (or optionaly 5) floats\n" );
 
564
 
 
565
        }
 
566
 
 
567
        return ( EXPP_incr_ret( Py_None ) );
 
568
}
 
569
 
 
570
 
 
571
/*
 
572
 *  CurNurb_setMatIndex
 
573
 *
 
574
 *  set index into material list
 
575
 */
 
576
 
 
577
static PyObject *CurNurb_setMatIndex( BPy_CurNurb * self, PyObject * args )
 
578
{
 
579
        int index;
 
580
 
 
581
        if( !PyArg_ParseTuple( args, "i", &( index ) ) )
 
582
                return ( EXPP_ReturnPyObjError
 
583
                         ( PyExc_AttributeError,
 
584
                           "expected integer argument" ) );
 
585
 
 
586
        /* fixme:  some range checking would be nice! */
 
587
        self->nurb->mat_nr = index;
 
588
 
 
589
        Py_INCREF( Py_None );
 
590
        return Py_None;
 
591
}
 
592
 
 
593
/*
 
594
 * CurNurb_getMatIndex
 
595
 *
 
596
 * returns index into material list
 
597
 */
 
598
 
 
599
static PyObject *CurNurb_getMatIndex( BPy_CurNurb * self )
 
600
{
 
601
        PyObject *index = PyInt_FromLong( ( long ) self->nurb->mat_nr );
 
602
 
 
603
        if( index )
 
604
                return index;
 
605
 
 
606
        return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 
607
                                        "could not get material index" ) );
 
608
}
 
609
 
 
610
/*
 
611
 * CurNurb_getFlagU
 
612
 *
 
613
 * returns curve's flagu
 
614
 */
 
615
 
 
616
static PyObject *CurNurb_getFlagU( BPy_CurNurb * self )
 
617
{
 
618
        PyObject *flagu = PyInt_FromLong( ( long ) self->nurb->flagu );
 
619
 
 
620
        if( flagu )
 
621
                return flagu;
 
622
 
 
623
        return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 
624
                                        "could not get CurNurb.flagu index" ) );
 
625
}
 
626
 
 
627
/*
 
628
 *  CurNurb_setFlagU
 
629
 *
 
630
 *  set curve's flagu and recalculate the knots
 
631
 *
 
632
 *  Possible values: 0 - uniform, 1 - endpoints, 2 - bezier
 
633
 */
 
634
 
 
635
static PyObject *CurNurb_setFlagU( BPy_CurNurb * self, PyObject * args )
 
636
{
 
637
        int flagu;
 
638
 
 
639
        if( !PyArg_ParseTuple( args, "i", &( flagu ) ) )
 
640
                return ( EXPP_ReturnPyObjError
 
641
                         ( PyExc_AttributeError,
 
642
                           "expected integer argument" ) );
 
643
 
 
644
        if( self->nurb->flagu != flagu ) {
 
645
                self->nurb->flagu = flagu;
 
646
                makeknots( self->nurb, 1, self->nurb->flagu >> 1 );
 
647
        }
 
648
 
 
649
        Py_INCREF( Py_None );
 
650
        return Py_None;
 
651
}
 
652
 
 
653
/*
 
654
 * CurNurb_getFlagV
 
655
 *
 
656
 * returns curve's flagu
 
657
 */
 
658
 
 
659
static PyObject *CurNurb_getFlagV( BPy_CurNurb * self )
 
660
{
 
661
        PyObject *flagv = PyInt_FromLong( ( long ) self->nurb->flagv );
 
662
 
 
663
        if( flagv )
 
664
                return flagv;
 
665
 
 
666
        return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 
667
                                        "could not get CurNurb.flagv" ) );
 
668
}
 
669
 
 
670
/*
 
671
 *  CurNurb_setFlagV
 
672
 *
 
673
 *  set curve's flagu and recalculate the knots
 
674
 *
 
675
 *  Possible values: 0 - uniform, 1 - endpoints, 2 - bezier
 
676
 */
 
677
 
 
678
static PyObject *CurNurb_setFlagV( BPy_CurNurb * self, PyObject * args )
 
679
{
 
680
        int flagv;
 
681
 
 
682
        if( !PyArg_ParseTuple( args, "i", &( flagv ) ) )
 
683
                return ( EXPP_ReturnPyObjError
 
684
                         ( PyExc_AttributeError,
 
685
                           "expected integer argument" ) );
 
686
 
 
687
        if( self->nurb->flagv != flagv ) {
 
688
                self->nurb->flagv = flagv;
 
689
                makeknots( self->nurb, 2, self->nurb->flagv >> 1 );
 
690
        }
 
691
 
 
692
        Py_INCREF( Py_None );
 
693
        return Py_None;
 
694
}
 
695
 
 
696
/*
 
697
 * CurNurb_getIter
 
698
 *
 
699
 * create an iterator for our CurNurb.
 
700
 * this iterator returns the points for this CurNurb.
 
701
 */
 
702
 
 
703
static PyObject *CurNurb_getIter( BPy_CurNurb * self )
 
704
{
 
705
        self->bp = self->nurb->bp;
 
706
        self->bezt = self->nurb->bezt;
 
707
        self->atEnd = 0;
 
708
        self->nextPoint = 0;
 
709
 
 
710
        /* set exhausted flag if both bp and bezt are zero */
 
711
        if( ( !self->bp ) && ( !self->bezt ) )
 
712
                self->atEnd = 1;
 
713
 
 
714
        Py_INCREF( self );
 
715
        return ( PyObject * ) self;
 
716
}
 
717
 
 
718
 
 
719
 
 
720
static PyObject *CurNurb_iterNext( BPy_CurNurb * self )
 
721
{
 
722
        PyObject *po;           /* return value */
 
723
        Nurb *pnurb = self->nurb;
 
724
        int npoints = pnurb->pntsu;
 
725
 
 
726
        /* are we at end already? */
 
727
        if( self->atEnd )
 
728
                return ( EXPP_ReturnPyObjError( PyExc_StopIteration,
 
729
                                                "iterator at end" ) );
 
730
 
 
731
        if( self->nextPoint < npoints ) {
 
732
 
 
733
                po = CurNurb_pointAtIndex( self->nurb, self->nextPoint );
 
734
                self->nextPoint++;
 
735
 
 
736
                return po;
 
737
 
 
738
        } else {
 
739
                self->atEnd = 1;        /* set flag true */
 
740
        }
 
741
 
 
742
        return ( EXPP_ReturnPyObjError( PyExc_StopIteration,
 
743
                                        "iterator at end" ) );
 
744
}
 
745
 
 
746
 
 
747
 
 
748
/*
 
749
 * CurNurb_isNurb()
 
750
 * test whether spline nurb or bezier
 
751
 */
 
752
 
 
753
static PyObject *CurNurb_isNurb( BPy_CurNurb * self )
 
754
{
 
755
        /* NOTE: a Nurb has bp and bezt pointers
 
756
         * depending on type.
 
757
         * It is possible both are NULL if no points exist.
 
758
         * in that case, we return False
 
759
         */
 
760
 
 
761
        if( self->nurb->bp ) {
 
762
                return EXPP_incr_ret_True();
 
763
        } else {
 
764
                return EXPP_incr_ret_False();
 
765
        }
 
766
}
 
767
 
 
768
/*
 
769
 * CurNurb_isCyclic()
 
770
 * test whether spline cyclic (closed) or not (open)
 
771
 */
 
772
 
 
773
static PyObject *CurNurb_isCyclic( BPy_CurNurb * self )
 
774
{
 
775
        /* supposing that the flagu is always set */ 
 
776
 
 
777
        if( self->nurb->flagu & CU_CYCLIC ) {
 
778
                return EXPP_incr_ret_True();
 
779
        } else {
 
780
                return EXPP_incr_ret_False();
 
781
        }
 
782
}
 
783
 
 
784
/*
 
785
 * CurNurb_length
 
786
 * returns the number of points in a Nurb
 
787
 * this is a tp_as_sequence method, not a regular instance method.
 
788
 */
 
789
 
 
790
static int CurNurb_length( PyInstanceObject * inst )
 
791
{
 
792
        Nurb *nurb;
 
793
        int len;
 
794
 
 
795
        if( CurNurb_CheckPyObject( ( PyObject * ) inst ) ) {
 
796
                nurb = ( ( BPy_CurNurb * ) inst )->nurb;
 
797
                len = nurb->pntsu;
 
798
                return len;
 
799
        }
 
800
 
 
801
        return EXPP_ReturnIntError( PyExc_RuntimeError,
 
802
                                    "arg is not a BPy_CurNurb" );
 
803
}
 
804
 
 
805
 
 
806
/*
 
807
 * CurNurb_getPoint
 
808
 * returns the Nth point in a Nurb
 
809
 * this is one of the tp_as_sequence methods, hence the int N argument.
 
810
 * it is called via the [] operator, not as a usual instance method.
 
811
 */
 
812
 
 
813
PyObject *CurNurb_getPoint( BPy_CurNurb * self, int index )
 
814
{
 
815
        Nurb *myNurb;
 
816
 
 
817
        int npoints;
 
818
 
 
819
        /* for convenince */
 
820
        myNurb = self->nurb;
 
821
        npoints = myNurb->pntsu;
 
822
 
 
823
        /* DELETED: bail if index < 0 */
 
824
        /* actually, this check is not needed since python treats */
 
825
        /* negative indices as starting from the right end of a sequence */
 
826
        /* 
 
827
        THAT IS WRONG, when passing a negative index, python adjusts it to be positive
 
828
        BUT it can still overflow in the negatives if the index is too small.
 
829
        For example, list[-6] when list contains 5 items means index = -1 in here.
 
830
        (theeth)
 
831
        */
 
832
 
 
833
        /* bail if no Nurbs in Curve */
 
834
        if( npoints == 0 )
 
835
                return ( EXPP_ReturnPyObjError( PyExc_IndexError,
 
836
                                                "no points in this CurNurb" ) );
 
837
 
 
838
        /* check index limits */
 
839
        if( index >= npoints || index < 0 )
 
840
                return ( EXPP_ReturnPyObjError( PyExc_IndexError,
 
841
                                                "index out of range" ) );
 
842
 
 
843
        return CurNurb_pointAtIndex( myNurb, index );
 
844
}
 
845
 
 
846
/*
 
847
 * CurNurb_setPoint
 
848
 * modifies the Nth point in a Nurb
 
849
 * this is one of the tp_as_sequence methods, hence the int N argument.
 
850
 * it is called via the [] = operator, not as a usual instance method.
 
851
 */
 
852
static int CurNurb_setPoint( BPy_CurNurb * self, int index, PyObject * pyOb )
 
853
{
 
854
        Nurb *nurb = self->nurb;
 
855
        int size;
 
856
 
 
857
        /* check index limits */
 
858
        if( index < 0 || index >= nurb->pntsu )
 
859
                return EXPP_ReturnIntError( PyExc_IndexError,
 
860
                                            "array assignment index out of range\n" );
 
861
 
 
862
 
 
863
        /* branch by curve type */
 
864
        if ((nurb->type & 7)==CU_BEZIER) {      /* BEZIER */
 
865
                /* check parameter type */
 
866
                if( !BezTriple_CheckPyObject( pyOb ) )
 
867
                        return EXPP_ReturnIntError( PyExc_TypeError,
 
868
                                                        "expected a BezTriple\n" );
 
869
 
 
870
                /* copy bezier in array */
 
871
                memcpy( nurb->bezt + index,
 
872
                        BezTriple_FromPyObject( pyOb ), sizeof( BezTriple ) );
 
873
 
 
874
                return 0;       /* finished correctly */
 
875
        }
 
876
        else {  /* NURBS or POLY */
 
877
                int i;
 
878
 
 
879
                /* check parameter type */
 
880
                if (!PySequence_Check( pyOb ))
 
881
                        return EXPP_ReturnIntError( PyExc_TypeError,
 
882
                                                        "expected a list of 4 (or optionaly 5 if the curve is 3D) floats\n" );
 
883
 
 
884
                size = PySequence_Size( pyOb );
 
885
 
 
886
                /* check sequence size */
 
887
                if( size != 4 && size != 5 ) 
 
888
                        return EXPP_ReturnIntError( PyExc_TypeError,
 
889
                                                        "expected a list of 4 (or optionaly 5 if the curve is 3D) floats\n" );
 
890
 
 
891
                /* copy x, y, z, w */
 
892
                for( i = 0; i < 4; ++i ) {
 
893
                        float tmpx =
 
894
                                ( float ) PyFloat_AsDouble
 
895
                                ( PySequence_GetItem( pyOb, i ) );
 
896
                        nurb->bp[index].vec[i] = tmpx;
 
897
 
 
898
                }
 
899
 
 
900
                if (size == 5) {        /* set tilt, if present */
 
901
                        nurb->bp[index].alfa = (float)PyFloat_AsDouble( PySequence_GetItem( pyOb, 4 ) );
 
902
                }
 
903
                else {                          /* if not, set default  */
 
904
                        nurb->bp[index].alfa = 0.0f;
 
905
                }
 
906
 
 
907
                return 0;       /* finished correctly */
 
908
        }
 
909
}
 
910
 
 
911
 
 
912
/* 
 
913
 * this is an internal routine.  not callable directly from python
 
914
 */
 
915
 
 
916
PyObject *CurNurb_pointAtIndex( Nurb * nurb, int index )
 
917
{
 
918
        PyObject *pyo;
 
919
 
 
920
        if( nurb->bp ) {        /* we have a nurb curve */
 
921
                int i;
 
922
 
 
923
                /* add Tilt only if curve is 3D */
 
924
                if (nurb->flag & CU_3D)
 
925
                        pyo = PyList_New( 5 );
 
926
                else
 
927
                        pyo = PyList_New( 4 );
 
928
 
 
929
                for( i = 0; i < 4; i++ ) {
 
930
                        PyList_SetItem( pyo, i,
 
931
                                        PyFloat_FromDouble( nurb->bp[index].
 
932
                                                            vec[i] ) );
 
933
                }
 
934
 
 
935
                /* add Tilt only if curve is 3D */
 
936
                if (nurb->flag & CU_3D)
 
937
                        PyList_SetItem( pyo, 4, PyFloat_FromDouble( nurb->bp[index].alfa ) );
 
938
 
 
939
        } else if( nurb->bezt ) {       /* we have a bezier */
 
940
                /* if an error occurs, we just pass it on */
 
941
                pyo = BezTriple_CreatePyObject( &( nurb->bezt[index] ) );
 
942
 
 
943
        } else                  /* something is horribly wrong */
 
944
                /* neither bp or bezt is set && pntsu != 0 */
 
945
                return ( EXPP_ReturnPyObjError( PyExc_SystemError,
 
946
                                                "inconsistant structure found" ) );
 
947
 
 
948
        return ( pyo );
 
949
}
 
950
 
 
951
 
 
952
int CurNurb_CheckPyObject( PyObject * py_obj )
 
953
{
 
954
        return ( py_obj->ob_type == &CurNurb_Type );
 
955
}
 
956
 
 
957
 
 
958
PyObject *CurNurb_Init( void )
 
959
{
 
960
        PyObject *submodule;
 
961
 
 
962
        CurNurb_Type.ob_type = &PyType_Type;
 
963
 
 
964
        submodule =
 
965
                Py_InitModule3( "Blender.CurNurb", M_CurNurb_methods,
 
966
                                M_CurNurb_doc );
 
967
        return ( submodule );
 
968
}
 
969
 
 
970
 
 
971
/*
 
972
  dump nurb
 
973
*/
 
974
 
 
975
PyObject *CurNurb_dump( BPy_CurNurb * self )
 
976
{
 
977
        BPoint *bp = NULL;
 
978
        BezTriple *bezt = NULL;
 
979
        Nurb *nurb = self->nurb;
 
980
        int npoints = 0;
 
981
 
 
982
        if( ! self->nurb ){  /* bail on error */
 
983
                printf("\n no Nurb in this CurNurb");
 
984
                Py_RETURN_NONE;
 
985
        }
 
986
 
 
987
        printf(" type: %d, mat_nr: %d hide: %d flag: %d",
 
988
                   nurb->type, nurb->mat_nr, nurb->hide, nurb->flag);
 
989
        printf("\n pntsu: %d, pntsv: %d, resolu: %d resolv: %d",
 
990
                   nurb->pntsu, nurb->pntsv, nurb->resolu, nurb->resolv );
 
991
        printf("\n orderu: %d  orderv: %d", nurb->orderu, nurb->orderv );
 
992
        printf("\n flagu: %d flagv: %d",
 
993
                   nurb->flagu, nurb->flagv );
 
994
 
 
995
        npoints = nurb->pntsu;
 
996
 
 
997
        if( nurb->bp ) { /* we have a BPoint  */
 
998
                int n;
 
999
                for( n = 0, bp = nurb->bp;
 
1000
                         n < npoints;
 
1001
                         n++, bp++ )
 
1002
                {
 
1003
                        /* vec[4] */
 
1004
                        printf( "\ncoords[%d]: ", n);
 
1005
                        {
 
1006
                                int i;
 
1007
                                for( i = 0; i < 4; i++){
 
1008
                                        printf("%10.3f ", bp->vec[i] );
 
1009
                                }
 
1010
                        }
 
1011
                
 
1012
                        /* alfa, s[2] */
 
1013
                        printf("\n alpha: %5.2f   s: %d %d ", 
 
1014
                                   bp->alfa, bp->s[0], bp->s[1] );
 
1015
                        /* f1, hide */
 
1016
                        printf(" f1 %d  hide %d", bp->f1, bp->hide );
 
1017
                        printf("\n");
 
1018
                }
 
1019
        }
 
1020
        else { /* we have a BezTriple */
 
1021
                int n;
 
1022
                for( n = 0, bezt = nurb->bezt;
 
1023
                         n < npoints;
 
1024
                         n++, bezt++ )
 
1025
                {
 
1026
                        int i, j;
 
1027
                        printf("\npoint %d: ", n);
 
1028
                        for( i = 0; i < 3; i++ ) {
 
1029
                                printf("\nvec[%i] ",i );
 
1030
                                for( j = 0; j < 3; j++ ) {
 
1031
                                        printf(" %5.2f ", bezt->vec[i][j] );
 
1032
                                }
 
1033
                        }
 
1034
                                
 
1035
 
 
1036
                }
 
1037
                printf("\n");
 
1038
        }
 
1039
 
 
1040
        Py_RETURN_NONE;
 
1041
}