~ubuntu-branches/ubuntu/gutsy/pygame/gutsy

« back to all changes in this revision

Viewing changes to src/rect.c

  • Committer: Bazaar Package Importer
  • Author(s): Ed Boraas
  • Date: 2002-02-20 06:39:24 UTC
  • Revision ID: james.westby@ubuntu.com-20020220063924-amlzj7tqkeods4eq
Tags: upstream-1.4
ImportĀ upstreamĀ versionĀ 1.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    pygame - Python Game Library
 
3
    Copyright (C) 2000-2001  Pete Shinners
 
4
 
 
5
    This library is free software; you can redistribute it and/or
 
6
    modify it under the terms of the GNU Library General Public
 
7
    License as published by the Free Software Foundation; either
 
8
    version 2 of the License, or (at your option) any later version.
 
9
 
 
10
    This library is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
    Library General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU Library General Public
 
16
    License along with this library; if not, write to the Free
 
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
    Pete Shinners
 
20
    pete@shinners.org
 
21
*/
 
22
 
 
23
/*
 
24
 *  Python Rect Object -- useful 2d rectangle class
 
25
 */
 
26
#define PYGAMEAPI_RECT_INTERNAL
 
27
#include "pygame.h"
 
28
 
 
29
 
 
30
staticforward PyTypeObject PyRect_Type;
 
31
#define PyRect_Check(x) ((x)->ob_type == &PyRect_Type)
 
32
 
 
33
 
 
34
 
 
35
GAME_Rect* GameRect_FromObject(PyObject* obj, GAME_Rect* temp)
 
36
{
 
37
        short val;
 
38
 
 
39
        if(PyRect_Check(obj))
 
40
                return &((PyRectObject*)obj)->r;
 
41
 
 
42
        if(PySequence_Check(obj))
 
43
        {
 
44
                if(PySequence_Length(obj) == 4)
 
45
                {
 
46
                        if(!ShortFromObjIndex(obj, 0, &val)) return NULL; temp->x = val;
 
47
                        if(!ShortFromObjIndex(obj, 1, &val)) return NULL; temp->y = val;
 
48
                        if(!ShortFromObjIndex(obj, 2, &val)) return NULL; temp->w = val;
 
49
                        if(!ShortFromObjIndex(obj, 3, &val)) return NULL; temp->h = val;
 
50
                        return temp;
 
51
                }
 
52
                if(PySequence_Length(obj) == 2)
 
53
                {
 
54
                        PyObject* sub = PySequence_GetItem(obj, 0);
 
55
                        if(!sub || !PySequence_Check(sub) || PySequence_Length(sub)!=2)
 
56
                                {Py_XDECREF(sub); return NULL;}
 
57
                        if(!ShortFromObjIndex(sub, 0, &val)) {Py_DECREF(sub); return NULL;} temp->x = val;
 
58
                        if(!ShortFromObjIndex(sub, 1, &val)) {Py_DECREF(sub); return NULL;} temp->y = val;
 
59
                        Py_DECREF(sub);
 
60
                        sub = PySequence_GetItem(obj, 1);
 
61
                        if(!sub || !PySequence_Check(sub) || PySequence_Length(sub)!=2)
 
62
                                {Py_XDECREF(sub); return NULL;}
 
63
                        if(!ShortFromObjIndex(sub, 0, &val)) {Py_DECREF(sub); return NULL;} temp->w = val;
 
64
                        if(!ShortFromObjIndex(sub, 1, &val)) {Py_DECREF(sub); return NULL;} temp->h = val;
 
65
                        Py_DECREF(sub);
 
66
                        return temp;
 
67
                }
 
68
                if(PyTuple_Check(obj) && PyTuple_Size(obj) == 1) /*looks like an arg?*/
 
69
                {
 
70
                        PyObject* sub = PyTuple_GET_ITEM(obj, 0);
 
71
                        if(sub)
 
72
                                return GameRect_FromObject(sub, temp);
 
73
                }
 
74
        }
 
75
        return NULL;
 
76
}
 
77
 
 
78
static int Rect_SetTop(GAME_Rect* r, short val)
 
79
{
 
80
        r->y = val;
 
81
        return 0;
 
82
}       
 
83
static int Rect_SetBottom(GAME_Rect* r, short val)
 
84
{
 
85
        r->y = val - r->h;
 
86
        return 0;
 
87
}       
 
88
static int Rect_SetLeft(GAME_Rect* r, short val)
 
89
{
 
90
        r->x = val;
 
91
        return 0;
 
92
}       
 
93
static int Rect_SetRight(GAME_Rect* r, short val)
 
94
{
 
95
        r->x = val - r->w;
 
96
        return 0;
 
97
}
 
98
static int Rect_SetWidth(GAME_Rect* r, short val)
 
99
{
 
100
//      r->x -= val - r->w;
 
101
        r->w = val;
 
102
        return 0;
 
103
}
 
104
static int Rect_SetHeight(GAME_Rect* r, short val)
 
105
{
 
106
//      r->y -= val - r->h;
 
107
        r->h = val;
 
108
        return 0;
 
109
}
 
110
 
 
111
PyObject* PyRect_New(GAME_Rect* r)
 
112
{
 
113
        PyRectObject* rect = PyObject_NEW(PyRectObject, &PyRect_Type);
 
114
        if(!rect)
 
115
                return NULL;
 
116
        
 
117
        rect->r.x = r->x;
 
118
        rect->r.y = r->y;
 
119
        rect->r.w = r->w;
 
120
        rect->r.h = r->h;
 
121
 
 
122
        return (PyObject*)rect;
 
123
}
 
124
 
 
125
PyObject* PyRect_New4(short x, short y, short w, short h)
 
126
{
 
127
        PyRectObject* rect = PyObject_NEW(PyRectObject, &PyRect_Type);
 
128
        if(!rect)
 
129
                return NULL;
 
130
        
 
131
        rect->r.x = x;
 
132
        rect->r.y = y;
 
133
        rect->r.w = w;
 
134
        rect->r.h = h;
 
135
 
 
136
        return (PyObject*)rect;
 
137
}
 
138
 
 
139
static int DoRectsIntersect(GAME_Rect *A, GAME_Rect *B)
 
140
{
 
141
        return ((A->x >= B->x && A->x < B->x+B->w)  ||
 
142
                    (B->x >= A->x && B->x < A->x+A->w)) &&
 
143
                   ((A->y >= B->y && A->y < B->y+B->h)  ||
 
144
                    (B->y >= A->y && B->y < A->y+A->h));
 
145
}
 
146
 
 
147
 
 
148
 
 
149
    /*DOC*/ static char doc_normalize[] =
 
150
    /*DOC*/    "Rect.normalize() -> None\n"
 
151
    /*DOC*/    "corrects negative sizes\n"
 
152
    /*DOC*/    "\n"
 
153
    /*DOC*/    "If the rectangle has a a negative size in width or\n"
 
154
    /*DOC*/    "height, this will flip that axis so the sizes are\n"
 
155
    /*DOC*/    "positive, and the rectangle remains in the same\n"
 
156
    /*DOC*/    "place.\n"
 
157
    /*DOC*/ ;
 
158
 
 
159
static PyObject* rect_normalize(PyObject* oself, PyObject* args)
 
160
{
 
161
        PyRectObject* self = (PyRectObject*)oself;
 
162
        if(!PyArg_ParseTuple(args, ""))
 
163
                return NULL;
 
164
 
 
165
        if((short)self->r.w < 0)
 
166
        {
 
167
                self->r.x += self->r.w;
 
168
                self->r.w = -self->r.w;
 
169
        }
 
170
        if((short)self->r.h < 0)
 
171
        {
 
172
                self->r.y += self->r.h;
 
173
                self->r.h = -self->r.h;
 
174
        }
 
175
 
 
176
        RETURN_NONE
 
177
}
 
178
 
 
179
 
 
180
    /*DOC*/ static char doc_move[] =
 
181
    /*DOC*/    "Rect.move(x, y) -> Rect\n"
 
182
    /*DOC*/    "new rectangle with position changed\n"
 
183
    /*DOC*/    "\n"
 
184
    /*DOC*/    "Returns a new rectangle which is the base\n"
 
185
    /*DOC*/    "rectangle moved by the given amount.\n"
 
186
    /*DOC*/ ;
 
187
 
 
188
static PyObject* rect_move(PyObject* oself, PyObject* args)
 
189
{
 
190
        PyRectObject* self = (PyRectObject*)oself;
 
191
        short x, y;
 
192
 
 
193
        if(!TwoShortsFromObj(args, &x, &y))
 
194
                return RAISE(PyExc_TypeError, "argument must contain two numbers");
 
195
 
 
196
        return PyRect_New4((short)(self->r.x+x), (short)(self->r.y+y), self->r.w, self->r.h);
 
197
}
 
198
 
 
199
    /*DOC*/ static char doc_move_ip[] =
 
200
    /*DOC*/    "Rect.move_ip(x, y) -> None\n"
 
201
    /*DOC*/    "move the Rect by the given offset\n"
 
202
    /*DOC*/    "\n"
 
203
    /*DOC*/    "Moves the rectangle which by the given amount.\n"
 
204
    /*DOC*/ ;
 
205
 
 
206
static PyObject* rect_move_ip(PyObject* oself, PyObject* args)
 
207
{
 
208
        PyRectObject* self = (PyRectObject*)oself;
 
209
        short x, y;
 
210
 
 
211
        if(!TwoShortsFromObj(args, &x, &y))
 
212
                return RAISE(PyExc_TypeError, "argument must contain two numbers");
 
213
 
 
214
        self->r.x += x;
 
215
        self->r.y += y;
 
216
        RETURN_NONE
 
217
}
 
218
 
 
219
 
 
220
 
 
221
    /*DOC*/ static char doc_inflate[] =
 
222
    /*DOC*/    "Rect.inflate(x, y) -> Rect\n"
 
223
    /*DOC*/    "new rectangle with size changed\n"
 
224
    /*DOC*/    "\n"
 
225
    /*DOC*/    "Returns a new rectangle which has the sizes\n"
 
226
    /*DOC*/    "changed by the given amounts. The rectangle\n"
 
227
    /*DOC*/    "shrinks and expands around the rectangle's center.\n"
 
228
    /*DOC*/    "Negative values will shrink the rectangle.\n"
 
229
    /*DOC*/ ;
 
230
 
 
231
static PyObject* rect_inflate(PyObject* oself, PyObject* args)
 
232
{
 
233
        PyRectObject* self = (PyRectObject*)oself;
 
234
        short x, y;
 
235
 
 
236
        if(!TwoShortsFromObj(args, &x, &y))
 
237
                return RAISE(PyExc_TypeError, "argument must contain two numbers");
 
238
 
 
239
        return PyRect_New4((short)(self->r.x-x/2), (short)(self->r.y-y/2), (short)(self->r.w+x), (short)(self->r.h+y));
 
240
}
 
241
 
 
242
 
 
243
    /*DOC*/ static char doc_inflate_ip[] =
 
244
    /*DOC*/    "Rect.inflate_ip(x, y) -> None\n"
 
245
    /*DOC*/    "changes the Rect size\n"
 
246
    /*DOC*/    "\n"
 
247
    /*DOC*/    "Changes the Rect by the given amounts. The rectangle\n"
 
248
    /*DOC*/    "shrinks and expands around the rectangle's center.\n"
 
249
    /*DOC*/    "Negative values will shrink the rectangle.\n"
 
250
    /*DOC*/ ;
 
251
 
 
252
static PyObject* rect_inflate_ip(PyObject* oself, PyObject* args)
 
253
{
 
254
        PyRectObject* self = (PyRectObject*)oself;
 
255
        short x, y;
 
256
 
 
257
        if(!TwoShortsFromObj(args, &x, &y))
 
258
                return RAISE(PyExc_TypeError, "argument must contain two numbers");
 
259
 
 
260
        self->r.x -= x/2;
 
261
        self->r.y -= y/2;
 
262
        self->r.w += x;
 
263
        self->r.h += y;
 
264
        RETURN_NONE
 
265
}
 
266
 
 
267
 
 
268
 
 
269
    /*DOC*/ static char doc_union[] =
 
270
    /*DOC*/    "Rect.union(rectstyle) -> Rect\n"
 
271
    /*DOC*/    "makes new rectangle covering both inputs\n"
 
272
    /*DOC*/    "\n"
 
273
    /*DOC*/    "Creates a new Rect to completely cover the\n"
 
274
    /*DOC*/    "given input. There may be area inside the new\n"
 
275
    /*DOC*/    "Rect that is not covered by either input.\n"
 
276
    /*DOC*/ ;
 
277
 
 
278
static PyObject* rect_union(PyObject* oself, PyObject* args)
 
279
{
 
280
        PyRectObject* self = (PyRectObject*)oself;
 
281
        GAME_Rect *argrect, temp;
 
282
        short x, y, w, h;
 
283
        if(!(argrect = GameRect_FromObject(args, &temp)))
 
284
                return RAISE(PyExc_TypeError, "Argument must be rect style object");
 
285
        
 
286
        x = min(self->r.x, argrect->x);
 
287
        y = min(self->r.y, argrect->y);
 
288
        w = max(self->r.x+self->r.w, argrect->x+argrect->w) - x;
 
289
        h = max(self->r.y+self->r.h, argrect->y+argrect->h) - y;
 
290
        return PyRect_New4(x, y, w, h);
 
291
}
 
292
 
 
293
 
 
294
 
 
295
 
 
296
    /*DOC*/ static char doc_union_ip[] =
 
297
    /*DOC*/    "Rect.union_ip(rectstyle) -> None\n"
 
298
    /*DOC*/    "rectangle covering both input\n"
 
299
    /*DOC*/    "\n"
 
300
    /*DOC*/    "Resizes the Rect to completely cover the\n"
 
301
    /*DOC*/    "given input. There may be area inside the new\n"
 
302
    /*DOC*/    "dimensions that is not covered by either input.\n"
 
303
    /*DOC*/ ;
 
304
 
 
305
static PyObject* rect_union_ip(PyObject* oself, PyObject* args)
 
306
{
 
307
        PyRectObject* self = (PyRectObject*)oself;
 
308
        GAME_Rect *argrect, temp;
 
309
        short x, y, w, h;
 
310
        if(!(argrect = GameRect_FromObject(args, &temp)))
 
311
                return RAISE(PyExc_TypeError, "Argument must be rect style object");
 
312
        
 
313
        x = min(self->r.x, argrect->x);
 
314
        y = min(self->r.y, argrect->y);
 
315
        w = max(self->r.x+self->r.w, argrect->x+argrect->w) - x;
 
316
        h = max(self->r.y+self->r.h, argrect->y+argrect->h) - y;
 
317
        self->r.x = x;
 
318
        self->r.y = y;
 
319
        self->r.w = w;
 
320
        self->r.h = h;
 
321
        RETURN_NONE
 
322
}
 
323
 
 
324
 
 
325
    /*DOC*/ static char doc_unionall[] =
 
326
    /*DOC*/    "Rect.unionall(sequence_of_rectstyles) -> Rect\n"
 
327
    /*DOC*/    "rectangle covering all inputs\n"
 
328
    /*DOC*/    "\n"
 
329
    /*DOC*/    "Returns a new rectangle that completely covers all the\n"
 
330
    /*DOC*/    "given inputs. There may be area inside the new\n"
 
331
    /*DOC*/    "rectangle that is not covered by the inputs.\n"
 
332
    /*DOC*/ ;
 
333
 
 
334
static PyObject* rect_unionall(PyObject* oself, PyObject* args)
 
335
{
 
336
        PyRectObject* self = (PyRectObject*)oself;
 
337
        GAME_Rect *argrect, temp;
 
338
        int loop, size;
 
339
        PyObject* list, *obj;
 
340
        int t, l, b, r;
 
341
 
 
342
        if(!PyArg_ParseTuple(args, "O", &list))
 
343
                return NULL;
 
344
        if(!PySequence_Check(list))
 
345
                return RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects.");
 
346
 
 
347
        l = self->r.x;
 
348
        t = self->r.y;
 
349
        r = self->r.x + self->r.w;
 
350
        b = self->r.y + self->r.h;
 
351
 
 
352
        size = PySequence_Length(list); /*warning, size could be -1 on error?*/
 
353
        if(size < 1)
 
354
                return PyRect_New4((short)l, (short)t, (short)(r-l), (short)(b-t));
 
355
 
 
356
        for(loop = 0; loop < size; ++loop)
 
357
        {
 
358
                obj = PySequence_GetItem(list, loop);
 
359
                if(!obj || !(argrect = GameRect_FromObject(obj, &temp)))
 
360
                {
 
361
                        RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects.");
 
362
                        Py_XDECREF(obj);
 
363
                        break;
 
364
                }
 
365
                t = min(t, argrect->x);
 
366
                l = min(l, argrect->y);
 
367
                r = max(b, argrect->x+argrect->w);
 
368
                b = max(b, argrect->y+argrect->h);
 
369
                Py_DECREF(obj);
 
370
        }
 
371
 
 
372
        return PyRect_New4((short)l, (short)t, (short)(r-l), (short)(b-t));
 
373
}
 
374
 
 
375
 
 
376
    /*DOC*/ static char doc_unionall_ip[] =
 
377
    /*DOC*/    "Rect.unionall_ip(sequence_of_rectstyles) -> None\n"
 
378
    /*DOC*/    "rectangle covering all inputs\n"
 
379
    /*DOC*/    "\n"
 
380
    /*DOC*/    "Returns a new rectangle that completely covers all the\n"
 
381
    /*DOC*/    "given inputs. There may be area inside the new\n"
 
382
    /*DOC*/    "rectangle that is not covered by the inputs.\n"
 
383
    /*DOC*/ ;
 
384
 
 
385
static PyObject* rect_unionall_ip(PyObject* oself, PyObject* args)
 
386
{
 
387
        PyRectObject* self = (PyRectObject*)oself;
 
388
        GAME_Rect *argrect, temp;
 
389
        int loop, size;
 
390
        PyObject* list, *obj;
 
391
        int t, l, b, r;
 
392
 
 
393
        if(!PyArg_ParseTuple(args, "O", &list))
 
394
                return NULL;
 
395
        if(!PySequence_Check(list))
 
396
                return RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects.");
 
397
 
 
398
        l = self->r.x;
 
399
        t = self->r.y;
 
400
        r = self->r.x + self->r.w;
 
401
        b = self->r.y + self->r.h;
 
402
 
 
403
        size = PySequence_Length(list); /*warning, size could be -1 on error?*/
 
404
        if(size < 1)
 
405
                return PyRect_New4((short)l, (short)t, (short)(r-l), (short)(b-t));
 
406
 
 
407
        for(loop = 0; loop < size; ++loop)
 
408
        {
 
409
                obj = PySequence_GetItem(list, loop);
 
410
                if(!obj || !(argrect = GameRect_FromObject(obj, &temp)))
 
411
                {
 
412
                        RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects.");
 
413
                        Py_XDECREF(obj);
 
414
                        break;
 
415
                }
 
416
                t = min(t, argrect->x);
 
417
                l = min(l, argrect->y);
 
418
                r = max(b, argrect->x+argrect->w);
 
419
                b = max(b, argrect->y+argrect->h);
 
420
                Py_DECREF(obj);
 
421
        }
 
422
 
 
423
        self->r.x = l;
 
424
        self->r.y = t;
 
425
        self->r.w = r-l;
 
426
        self->r.h = b-t;
 
427
        RETURN_NONE
 
428
}
 
429
 
 
430
 
 
431
    /*DOC*/ static char doc_collidepoint[] =
 
432
    /*DOC*/    "Rect.collidepoint(x, y) -> bool\n"
 
433
    /*DOC*/    "point inside rectangle\n"
 
434
    /*DOC*/    "\n"
 
435
    /*DOC*/    "Returns true if the given point position is inside\n"
 
436
    /*DOC*/    "the rectangle. If a point is on the border, it is\n"
 
437
    /*DOC*/    "counted as inside.\n"
 
438
    /*DOC*/ ;
 
439
 
 
440
static PyObject* rect_collidepoint(PyObject* oself, PyObject* args)
 
441
{
 
442
        PyRectObject* self = (PyRectObject*)oself;
 
443
        short x, y;
 
444
        int inside;
 
445
 
 
446
        if(!TwoShortsFromObj(args, &x, &y))
 
447
                return RAISE(PyExc_TypeError, "argument must contain two numbers");
 
448
 
 
449
        inside = x>=self->r.x && x<self->r.x+self->r.w && 
 
450
                                y>=self->r.y && y<self->r.y+self->r.h;
 
451
 
 
452
        return PyInt_FromLong(inside);
 
453
}
 
454
 
 
455
 
 
456
 
 
457
    /*DOC*/ static char doc_colliderect[] =
 
458
    /*DOC*/    "Rect.colliderect(rectstyle) -> bool\n"
 
459
    /*DOC*/    "check overlapping rectangles\n"
 
460
    /*DOC*/    "\n"
 
461
    /*DOC*/    "Returns true if any area of the two rectangles\n"
 
462
    /*DOC*/    "overlaps.\n"
 
463
    /*DOC*/ ;
 
464
 
 
465
static PyObject* rect_colliderect(PyObject* oself, PyObject* args)
 
466
{
 
467
        PyRectObject* self = (PyRectObject*)oself;
 
468
        GAME_Rect *argrect, temp;
 
469
        if(!(argrect = GameRect_FromObject(args, &temp)))
 
470
                return RAISE(PyExc_TypeError, "Argument must be rect style object");
 
471
 
 
472
        return PyInt_FromLong(DoRectsIntersect(&self->r, argrect));
 
473
}
 
474
 
 
475
 
 
476
 
 
477
    /*DOC*/ static char doc_collidelist[] =
 
478
    /*DOC*/    "Rect.collidelist(rectstyle list) -> int index\n"
 
479
    /*DOC*/    "find overlapping rectangle\n"
 
480
    /*DOC*/    "\n"
 
481
    /*DOC*/    "Returns the index of the first rectangle in the\n"
 
482
    /*DOC*/    "list to overlap the base rectangle. Once an\n"
 
483
    /*DOC*/    "overlap is found, this will stop checking the\n"
 
484
    /*DOC*/    "remaining list. If no overlap is found, it will\n"
 
485
    /*DOC*/    "return -1.\n"
 
486
    /*DOC*/ ;
 
487
 
 
488
static PyObject* rect_collidelist(PyObject* oself, PyObject* args)
 
489
{
 
490
        PyRectObject* self = (PyRectObject*)oself;
 
491
        GAME_Rect *argrect, temp;
 
492
        int loop, size;
 
493
        PyObject* list, *obj;
 
494
        PyObject* ret = NULL;
 
495
 
 
496
        if(!PyArg_ParseTuple(args, "O", &list))
 
497
                return NULL;
 
498
 
 
499
        if(!PySequence_Check(list))
 
500
                return RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects.");
 
501
 
 
502
        size = PySequence_Length(list); /*warning, size could be -1 on error?*/
 
503
        for(loop = 0; loop < size; ++loop)
 
504
        {
 
505
                obj = PySequence_GetItem(list, loop);
 
506
                if(!obj || !(argrect = GameRect_FromObject(obj, &temp)))
 
507
                {       
 
508
                        RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects.");
 
509
                        Py_XDECREF(obj);
 
510
                        break;
 
511
                }
 
512
                if(DoRectsIntersect(&self->r, argrect))
 
513
                {
 
514
                        ret = PyInt_FromLong(loop);
 
515
                        Py_DECREF(obj);
 
516
                        break;
 
517
                }
 
518
                Py_DECREF(obj);
 
519
        }
 
520
        if(loop == size)
 
521
                ret = PyInt_FromLong(-1);
 
522
 
 
523
        return ret;     
 
524
}
 
525
 
 
526
 
 
527
    /*DOC*/ static char doc_collidelistall[] =
 
528
    /*DOC*/    "Rect.collidelistall(rectstyle list) -> int index\n"
 
529
    /*DOC*/    "find all overlapping rectangles\n"
 
530
    /*DOC*/    "\n"
 
531
    /*DOC*/    "Returns a list of the indexes that contain\n"
 
532
    /*DOC*/    "rectangles overlapping the base rectangle. If no\n"
 
533
    /*DOC*/    "overlap is found, it will return an empty\n"
 
534
    /*DOC*/    "sequence.\n"
 
535
    /*DOC*/ ;
 
536
 
 
537
static PyObject* rect_collidelistall(PyObject* oself, PyObject* args)
 
538
{
 
539
        PyRectObject* self = (PyRectObject*)oself;
 
540
        GAME_Rect *argrect, temp;
 
541
        int loop, size;
 
542
        PyObject* list, *obj;
 
543
        PyObject* ret = NULL;
 
544
 
 
545
        if(!PyArg_ParseTuple(args, "O", &list))
 
546
                return NULL;
 
547
 
 
548
        if(!PySequence_Check(list))
 
549
                return RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects.");
 
550
 
 
551
        ret = PyList_New(0);
 
552
        if(!ret)
 
553
                return NULL;
 
554
 
 
555
        size = PySequence_Length(list); /*warning, size could be -1?*/
 
556
        for(loop = 0; loop < size; ++loop)
 
557
        {
 
558
                obj = PySequence_GetItem(list, loop);
 
559
 
 
560
                if(!obj || !(argrect = GameRect_FromObject(obj, &temp)))
 
561
                {       
 
562
                        Py_XDECREF(obj);
 
563
                        Py_DECREF(ret);
 
564
                        return RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects.");
 
565
                }
 
566
 
 
567
                if(DoRectsIntersect(&self->r, argrect))
 
568
                {
 
569
                        PyObject* num = PyInt_FromLong(loop);
 
570
                        if(!num)
 
571
                        {
 
572
                                Py_DECREF(obj);
 
573
                                return NULL;
 
574
                        }
 
575
                        PyList_Append(ret, num);
 
576
                        Py_DECREF(num);
 
577
                }
 
578
                Py_DECREF(obj);
 
579
        }
 
580
 
 
581
        return ret;     
 
582
}
 
583
 
 
584
 
 
585
 
 
586
    /*DOC*/ static char doc_clip[] =
 
587
    /*DOC*/    "Rect.clip(rectstyle) -> Rect\n"
 
588
    /*DOC*/    "rectangle cropped inside another\n"
 
589
    /*DOC*/    "\n"
 
590
    /*DOC*/    "Returns a new rectangle that is the given\n"
 
591
    /*DOC*/    "rectangle cropped to the inside of the base\n"
 
592
    /*DOC*/    "rectangle. If the two rectangles do not overlap to\n"
 
593
    /*DOC*/    "begin with, you will get a rectangle with 0 size.\n"
 
594
    /*DOC*/ ;
 
595
 
 
596
static PyObject* rect_clip(PyObject* self, PyObject* args)
 
597
{
 
598
        GAME_Rect *A, *B, temp;
 
599
        short x, y, w, h;
 
600
 
 
601
        A = &((PyRectObject*)self)->r;
 
602
        if(!(B = GameRect_FromObject(args, &temp)))
 
603
                return RAISE(PyExc_TypeError, "Argument must be rect style object");
 
604
 
 
605
        /* Left */
 
606
        if((A->x >= B->x) && (A->x < (B->x+B->w)))
 
607
                x = A->x;
 
608
        else if((B->x >= A->x) && (B->x < (A->x+A->w)))
 
609
                x = B->x;
 
610
        else
 
611
                goto nointersect;
 
612
        /* Right */
 
613
        if(((A->x+A->w) > B->x) && ((A->x+A->w) <= (B->x+B->w)))
 
614
                w = (A->x+A->w) - x;
 
615
        else if(((B->x+B->w) > A->x) && ((B->x+B->w) <= (A->x+A->w)))
 
616
                w = (B->x+B->w) - x;
 
617
        else
 
618
                goto nointersect;
 
619
        
 
620
        /* Top */
 
621
        if((A->y >= B->y) && (A->y < (B->y+B->h)))
 
622
                y = A->y;
 
623
        else if((B->y >= A->y) && (B->y < (A->y+A->h)))
 
624
                y = B->y;
 
625
        else
 
626
                goto nointersect;
 
627
        /* Bottom */
 
628
        if (((A->y+A->h) > B->y) && ((A->y+A->h) <= (B->y+B->h)))
 
629
                h = (A->y+A->h) - y;
 
630
        else if(((B->y+B->h) > A->y) && ((B->y+B->h) <= (A->y+A->h)))
 
631
                h = (B->y+B->h) - y;
 
632
        else
 
633
                goto nointersect;
 
634
 
 
635
        return PyRect_New4(x, y, w, h);
 
636
 
 
637
nointersect:
 
638
        return PyRect_New4(A->x, A->y, 0, 0);
 
639
}
 
640
 
 
641
 
 
642
    /*DOC*/ static char doc_contains[] =
 
643
    /*DOC*/    "Rect.contains(rectstyle) -> bool\n"
 
644
    /*DOC*/    "check if rectangle fully inside another\n"
 
645
    /*DOC*/    "\n"
 
646
    /*DOC*/    "Returns true when the given rectangle is entirely\n"
 
647
    /*DOC*/    "inside the base rectangle.\n"
 
648
    /*DOC*/ ;
 
649
 
 
650
static PyObject* rect_contains(PyObject* oself, PyObject* args)
 
651
{
 
652
        int contained;
 
653
        PyRectObject* self = (PyRectObject*)oself;
 
654
        GAME_Rect *argrect, temp;
 
655
        if(!(argrect = GameRect_FromObject(args, &temp)))
 
656
                return RAISE(PyExc_TypeError, "Argument must be rect style object");
 
657
 
 
658
        contained = (self->r.x <= argrect->x) && (self->r.y <= argrect->y) &&
 
659
                    (self->r.x + self->r.w >= argrect->x + argrect->w) &&
 
660
                    (self->r.y + self->r.h >= argrect->y + argrect->h) &&
 
661
                    (self->r.x + self->r.w > argrect->x) &&
 
662
                    (self->r.y + self->r.h > argrect->y);
 
663
 
 
664
        return PyInt_FromLong(contained);
 
665
}
 
666
 
 
667
 
 
668
    /*DOC*/ static char doc_clamp[] =
 
669
    /*DOC*/    "Rect.clamp(rectstyle) -> Rect\n"
 
670
    /*DOC*/    "move rectangle inside another\n"
 
671
    /*DOC*/    "\n"
 
672
    /*DOC*/    "Returns a new rectangle that is moved to be\n"
 
673
    /*DOC*/    "completely inside the argument rectangle. If the base\n"
 
674
    /*DOC*/    "rectangle is too large for the argument rectangle in\n"
 
675
    /*DOC*/    "an axis, it will be centered on that axis.\n"
 
676
    /*DOC*/ ;
 
677
 
 
678
static PyObject* rect_clamp(PyObject* oself, PyObject* args)
 
679
{
 
680
        PyRectObject* self = (PyRectObject*)oself;
 
681
        GAME_Rect *argrect, temp;
 
682
        short x, y;
 
683
        if(!(argrect = GameRect_FromObject(args, &temp)))
 
684
                return RAISE(PyExc_TypeError, "Argument must be rect style object");
 
685
 
 
686
        if(self->r.w >= argrect->w)
 
687
                x = argrect->x + argrect->w / 2 - self->r.w / 2;
 
688
        else if(self->r.x < argrect->x)
 
689
                x = argrect->x;
 
690
        else if(self->r.x + self->r.w > argrect->x + argrect->w)
 
691
                x = argrect->x + argrect->w - self->r.w;
 
692
        else
 
693
                x = self->r.x;
 
694
 
 
695
        if(self->r.h >= argrect->h)
 
696
                y = argrect->y + argrect->h / 2 - self->r.h / 2;
 
697
        else if(self->r.y < argrect->y)
 
698
                y = argrect->y;
 
699
        else if(self->r.y + self->r.h > argrect->y + argrect->h)
 
700
                y = argrect->y + argrect->h - self->r.h;
 
701
        else
 
702
                y = self->r.y;
 
703
 
 
704
        return PyRect_New4(x, y, self->r.w, self->r.h);
 
705
}
 
706
 
 
707
 
 
708
    /*DOC*/ static char doc_clamp_ip[] =
 
709
    /*DOC*/    "Rect.clamp_ip(rectstyle) -> None\n"
 
710
    /*DOC*/    "moves the rectangle inside another\n"
 
711
    /*DOC*/    "\n"
 
712
    /*DOC*/    "Moves the Rect to be\n"
 
713
    /*DOC*/    "completely inside the argument rectangle. If the given\n"
 
714
    /*DOC*/    "rectangle is too large for the argument rectangle in\n"
 
715
    /*DOC*/    "an axis, it will be centered on that axis.\n"
 
716
    /*DOC*/ ;
 
717
 
 
718
static PyObject* rect_clamp_ip(PyObject* oself, PyObject* args)
 
719
{
 
720
        PyRectObject* self = (PyRectObject*)oself;
 
721
        GAME_Rect *argrect, temp;
 
722
        short x, y;
 
723
        if(!(argrect = GameRect_FromObject(args, &temp)))
 
724
                return RAISE(PyExc_TypeError, "Argument must be rect style object");
 
725
 
 
726
        if(self->r.w >= argrect->w)
 
727
                x = argrect->x + argrect->w / 2 - self->r.w / 2;
 
728
        else if(self->r.x < argrect->x)
 
729
                x = argrect->x;
 
730
        else if(self->r.x + self->r.w > argrect->x + argrect->w)
 
731
                x = argrect->x + argrect->w - self->r.w;
 
732
        else
 
733
                x = self->r.x;
 
734
 
 
735
        if(self->r.h >= argrect->h)
 
736
                y = argrect->y + argrect->h / 2 - self->r.h / 2;
 
737
        else if(self->r.y < argrect->y)
 
738
                y = argrect->y;
 
739
        else if(self->r.y + self->r.h > argrect->y + argrect->h)
 
740
                y = argrect->y + argrect->h - self->r.h;
 
741
        else
 
742
                y = self->r.y;
 
743
 
 
744
        self->r.x = x;
 
745
        self->r.y = y;
 
746
        RETURN_NONE
 
747
}
 
748
 
 
749
 
 
750
static struct PyMethodDef rect_methods[] =
 
751
{
 
752
        {"normalize",           (PyCFunction)rect_normalize,    1, doc_normalize},
 
753
        {"clip",                        (PyCFunction)rect_clip,                 1, doc_clip},
 
754
        {"clamp",                       (PyCFunction)rect_clamp,                1, doc_clamp},
 
755
        {"clamp_ip",                     (PyCFunction)rect_clamp_ip,              1,        doc_clamp_ip},
 
756
 
 
757
        {"move",                        (PyCFunction)rect_move,                 1, doc_move},
 
758
        {"inflate",                     (PyCFunction)rect_inflate,              1, doc_inflate},                
 
759
        {"union",                       (PyCFunction)rect_union,                1, doc_union},
 
760
        {"unionall",            (PyCFunction)rect_unionall,             1, doc_unionall},
 
761
 
 
762
        {"move_ip",                     (PyCFunction)rect_move_ip,              1, doc_move_ip},
 
763
        {"inflate_ip",          (PyCFunction)rect_inflate_ip,   1, doc_inflate_ip},             
 
764
        {"union_ip",            (PyCFunction)rect_union_ip,             1, doc_union_ip},
 
765
        {"unionall_ip",         (PyCFunction)rect_unionall_ip,  1, doc_unionall_ip},
 
766
 
 
767
        {"collidepoint",        (PyCFunction)rect_collidepoint, 1, doc_collidepoint},
 
768
        {"colliderect",         (PyCFunction)rect_colliderect,  1, doc_colliderect},
 
769
        {"collidelist",         (PyCFunction)rect_collidelist,  1, doc_collidelist},
 
770
        {"collidelistall",      (PyCFunction)rect_collidelistall,1,doc_collidelistall},
 
771
        {"contains",            (PyCFunction)rect_contains,             1, doc_contains},
 
772
/* these are totally unwritten. volunteers? */
 
773
/*      {"cleanup",                     (PyCFunction)rect_cleanup,              1, doc_cleanup}, */
 
774
/*      {"remove",                      (PyCFunction)rect_remove,               1, doc_remove}, */
 
775
        {NULL,          NULL}
 
776
};
 
777
 
 
778
 
 
779
 
 
780
 
 
781
/* sequence functions */
 
782
 
 
783
static int rect_length(PyRectObject *self)
 
784
{
 
785
        return 4;
 
786
}
 
787
 
 
788
static PyObject* rect_item(PyRectObject *self, int i)
 
789
{
 
790
        short* data = (short*)&self->r;
 
791
        if(i<0 || i>3)
 
792
                return RAISE(PyExc_IndexError, "Invalid rect Index");
 
793
 
 
794
        return PyInt_FromLong(data[i]);
 
795
}
 
796
 
 
797
static int rect_ass_item(PyRectObject *self, int i, PyObject *v)
 
798
{
 
799
        short val;
 
800
        short* data = (short*)&self->r;
 
801
        if(i<0 || i>3)
 
802
        {
 
803
                RAISE(PyExc_IndexError, "Invalid rect Index");
 
804
                return -1;
 
805
        }
 
806
        if(!ShortFromObj(v, &val))
 
807
        {
 
808
                RAISE(PyExc_TypeError, "Must assign numeric values");
 
809
                return -1;
 
810
        }
 
811
        data[i] = (short)val;
 
812
        return 0;
 
813
}
 
814
 
 
815
 
 
816
static PyObject* rect_slice(PyRectObject *self, int ilow, int ihigh)
 
817
{
 
818
        PyObject *list;
 
819
        short* data = (short*)&self->r;
 
820
        int numitems, loop, l = 4;
 
821
        
 
822
        if (ihigh < 0) ihigh += l;
 
823
        if (ilow  < 0) ilow  += l;
 
824
        if (ilow < 0) ilow = 0;
 
825
        else if (ilow > l) ilow = l;
 
826
        if (ihigh < 0) ihigh = 0;
 
827
        else if (ihigh > l) ihigh = l;
 
828
        if (ihigh < ilow) ihigh = ilow;
 
829
 
 
830
        numitems = ihigh - ilow;
 
831
        list = PyList_New(numitems);
 
832
        for(loop = 0; loop < numitems; ++loop)
 
833
                PyList_SET_ITEM(list, loop, PyInt_FromLong(data[loop+ilow]));
 
834
 
 
835
        return list;
 
836
}
 
837
 
 
838
 
 
839
 
 
840
static int rect_ass_slice(PyRectObject *self, int ilow, int ihigh, PyObject *v)
 
841
{
 
842
        short* data = (short*)&self->r;
 
843
        int numitems, loop, l = 4;
 
844
        short val;
 
845
        
 
846
        if(!PySequence_Check(v))
 
847
        {
 
848
                RAISE(PyExc_TypeError, "Assigned slice must be a sequence");
 
849
                return -1;
 
850
        }
 
851
 
 
852
        if (ihigh < 0) ihigh += l;
 
853
        if (ilow  < 0) ilow  += l;
 
854
        if (ilow < 0) ilow = 0;
 
855
        else if (ilow > l) ilow = l;
 
856
        if (ihigh < 0) ihigh = 0;
 
857
        else if (ihigh > l) ihigh = l;
 
858
        if (ihigh < ilow) ihigh = ilow;
 
859
 
 
860
        numitems = ihigh - ilow;
 
861
        if(numitems != PySequence_Length(v))
 
862
        {
 
863
                RAISE(PyExc_ValueError, "Assigned slice must be same length");
 
864
                return -1;
 
865
        }
 
866
 
 
867
        for(loop = 0; loop < numitems; ++loop)
 
868
        {
 
869
                if(!ShortFromObjIndex(v, loop, &val)) return -1;
 
870
                data[loop+ilow] = val;
 
871
        }
 
872
 
 
873
        return 0;
 
874
}
 
875
 
 
876
static PySequenceMethods rect_as_sequence = {
 
877
        (inquiry)rect_length,                           /*length*/
 
878
        (binaryfunc)NULL,                                       /*concat*/
 
879
        (intargfunc)NULL,                                       /*repeat*/
 
880
        (intargfunc)rect_item,                          /*item*/
 
881
        (intintargfunc)rect_slice,                      /*slice*/
 
882
        (intobjargproc)rect_ass_item,           /*ass_item*/
 
883
        (intintobjargproc)rect_ass_slice,       /*ass_slice*/
 
884
};
 
885
 
 
886
 
 
887
 
 
888
/* numeric functions */
 
889
 
 
890
static int rect_nonzero(PyRectObject *self)
 
891
{
 
892
        return self->r.w != 0 && self->r.h != 0;
 
893
}
 
894
 
 
895
static int rect_coerce(PyObject** o1, PyObject** o2)
 
896
{
 
897
        PyObject* new1;
 
898
        PyObject* new2;
 
899
        GAME_Rect* r, temp;
 
900
 
 
901
        if(PyRect_Check(*o1))
 
902
        {
 
903
                new1 = *o1;
 
904
                Py_INCREF(new1);
 
905
        }
 
906
        else if((r = GameRect_FromObject(*o1, &temp)))
 
907
                new1 = PyRect_New(r);
 
908
        else
 
909
                return 1;
 
910
 
 
911
        if(PyRect_Check(*o2))
 
912
        {
 
913
                new2 = *o2;
 
914
                Py_INCREF(new2);
 
915
        }
 
916
        else if((r = GameRect_FromObject(*o2, &temp)))
 
917
                new2 = PyRect_New(r);
 
918
        else
 
919
        {
 
920
                Py_DECREF(new1);
 
921
                return 1;
 
922
        }
 
923
 
 
924
        *o1 = new1;
 
925
        *o2 = new2;
 
926
        return 0;
 
927
}
 
928
 
 
929
static PyNumberMethods rect_as_number = {
 
930
        (binaryfunc)NULL,               /*add*/
 
931
        (binaryfunc)NULL,               /*subtract*/
 
932
        (binaryfunc)NULL,               /*multiply*/
 
933
        (binaryfunc)NULL,               /*divide*/
 
934
        (binaryfunc)NULL,               /*remainder*/
 
935
        (binaryfunc)NULL,               /*divmod*/
 
936
        (ternaryfunc)NULL,              /*power*/
 
937
        (unaryfunc)NULL,                /*negative*/
 
938
        (unaryfunc)NULL,                /*pos*/ 
 
939
        (unaryfunc)NULL,                /*abs*/
 
940
        (inquiry)rect_nonzero,  /*nonzero*/
 
941
        (unaryfunc)NULL,                /*invert*/
 
942
        (binaryfunc)NULL,               /*lshift*/
 
943
        (binaryfunc)NULL,               /*rshift*/
 
944
        (binaryfunc)NULL,               /*and*/
 
945
        (binaryfunc)NULL,               /*xor*/
 
946
        (binaryfunc)NULL,               /*or*/
 
947
        (coercion)rect_coerce,  /*coerce*/
 
948
        (unaryfunc)NULL,                /*int*/
 
949
        (unaryfunc)NULL,                /*long*/
 
950
        (unaryfunc)NULL,                /*float*/
 
951
        (unaryfunc)NULL,                /*oct*/
 
952
        (unaryfunc)NULL,                /*hex*/
 
953
};
 
954
 
 
955
 
 
956
/* object type functions */
 
957
static void rect_dealloc(PyRectObject *self)
 
958
{
 
959
        PyObject_DEL(self);
 
960
}
 
961
 
 
962
 
 
963
static PyObject *rect_repr(PyRectObject *self)
 
964
{
 
965
        char string[256];       
 
966
        sprintf(string, "<rect(%d, %d, %d, %d)>", self->r.x, self->r.y, self->r.w, self->r.h);  
 
967
        return PyString_FromString(string);
 
968
}
 
969
 
 
970
 
 
971
static PyObject *rect_str(PyRectObject *self)
 
972
{
 
973
        return rect_repr(self);
 
974
}
 
975
 
 
976
 
 
977
static int rect_compare(PyRectObject *self, PyObject *other)
 
978
{
 
979
        GAME_Rect *orect, temp;
 
980
 
 
981
        orect = GameRect_FromObject(other, &temp);
 
982
        if(!orect)
 
983
        {
 
984
                RAISE(PyExc_TypeError, "must compare rect with rect style object");
 
985
                return -1;
 
986
        }
 
987
 
 
988
        if(self->r.x != orect->x)
 
989
                return self->r.x < orect->x ? -1 : 1;
 
990
        if(self->r.y != orect->y)
 
991
                return self->r.y < orect->y ? -1 : 1;
 
992
        if(self->r.w != orect->w)
 
993
                return self->r.w < orect->w ? -1 : 1;
 
994
        if(self->r.h != orect->h)
 
995
                return self->r.h < orect->h ? -1 : 1;
 
996
 
 
997
        return 0;
 
998
}
 
999
 
 
1000
 
 
1001
static PyObject *rect_getattr(PyRectObject *self, char *name)
 
1002
{
 
1003
        PyObject *ret = NULL;
 
1004
        GAME_Rect *r = &self->r;
 
1005
        
 
1006
        if(!strcmp(name, "top"))
 
1007
                ret = PyInt_FromLong(r->y);
 
1008
        else if(!strcmp(name, "bottom"))
 
1009
                ret = PyInt_FromLong(r->y + r->h);
 
1010
        else if(!strcmp(name, "left"))
 
1011
                ret = PyInt_FromLong(r->x);
 
1012
        else if(!strcmp(name, "right"))
 
1013
                ret = PyInt_FromLong(r->x + r->w);
 
1014
        else if(!strcmp(name, "width"))
 
1015
                ret = PyInt_FromLong(r->w);
 
1016
        else if(!strcmp(name, "height"))
 
1017
                ret = PyInt_FromLong(r->h);
 
1018
        else if(!strcmp(name, "centerx"))
 
1019
                ret = PyInt_FromLong(r->x+r->w/2);
 
1020
        else if(!strcmp(name, "centery"))
 
1021
                ret = PyInt_FromLong(r->y+r->h/2);
 
1022
 
 
1023
        else if(!strcmp(name, "topleft"))
 
1024
                ret = Py_BuildValue("(ii)", r->x, r->y);
 
1025
        else if(!strcmp(name, "bottomleft"))
 
1026
                ret = Py_BuildValue("(ii)", r->x, r->y + r->h);
 
1027
        else if(!strcmp(name, "topright"))
 
1028
                ret = Py_BuildValue("(ii)", r->x + r->w, r->y);
 
1029
        else if(!strcmp(name, "bottomright"))
 
1030
                ret = Py_BuildValue("(ii)", r->x + r->w, r->y + r->h);
 
1031
        else if(!strcmp(name, "size"))
 
1032
                ret = Py_BuildValue("(ii)", r->w, r->h);
 
1033
        else if(!strcmp(name, "center"))
 
1034
                ret = Py_BuildValue("(ii)", r->x + r->w / 2, r->y + r->h / 2);
 
1035
 
 
1036
        else if(!strcmp(name, "midleft"))
 
1037
                ret = Py_BuildValue("(ii)", r->x, r->y + r->h / 2);
 
1038
        else if(!strcmp(name, "midright"))
 
1039
                ret = Py_BuildValue("(ii)", r->x + r->w, r->y + r->h / 2);
 
1040
        else if(!strcmp(name, "midtop"))
 
1041
                ret = Py_BuildValue("(ii)", r->x + r->w / 2, r->y);
 
1042
        else if(!strcmp(name, "midbottom"))
 
1043
                ret = Py_BuildValue("(ii)", r->x + r->w / 2, r->y + r->h);
 
1044
        
 
1045
        else
 
1046
                ret = Py_FindMethod(rect_methods, (PyObject *)self, name);
 
1047
 
 
1048
        return ret;
 
1049
}
 
1050
 
 
1051
static int rect_setattr(PyRectObject *self, char *name, PyObject *op)
 
1052
{
 
1053
        int ret = -1;
 
1054
        short val1, val2;
 
1055
        GAME_Rect *r = &self->r;
 
1056
        
 
1057
        if(!strcmp(name, "top"))
 
1058
        {
 
1059
                if(ShortFromObj(op, &val1))
 
1060
                        ret = Rect_SetTop(r, val1);
 
1061
        }       
 
1062
        else if(!strcmp(name, "bottom"))
 
1063
        {
 
1064
                if(ShortFromObj(op, &val1))
 
1065
                        ret = Rect_SetBottom(r, val1);
 
1066
        }       
 
1067
        else if(!strcmp(name, "left"))
 
1068
        {
 
1069
                if(ShortFromObj(op, &val1))
 
1070
                        ret = Rect_SetLeft(r, val1);
 
1071
        }       
 
1072
        else if(!strcmp(name, "right"))
 
1073
        {
 
1074
                if(ShortFromObj(op, &val1))
 
1075
                        ret = Rect_SetRight(r, val1);
 
1076
        }       
 
1077
        else if(!strcmp(name, "width"))
 
1078
        {
 
1079
                if(ShortFromObj(op, &val1))
 
1080
                        ret = Rect_SetWidth(r, val1);
 
1081
        }       
 
1082
        else if(!strcmp(name, "height"))
 
1083
        {
 
1084
                if(ShortFromObj(op, &val1))
 
1085
                        ret = Rect_SetHeight(r, val1);
 
1086
        }       
 
1087
        else if(!strcmp(name, "topleft"))
 
1088
        {
 
1089
                if(TwoShortsFromObj(op, &val1, &val2))
 
1090
                {
 
1091
                        Rect_SetLeft(r, val1);
 
1092
                        ret = Rect_SetTop(r, val2);
 
1093
                }
 
1094
        }       
 
1095
        else if(!strcmp(name, "bottomleft"))
 
1096
        {
 
1097
                if(TwoShortsFromObj(op, &val1, &val2))
 
1098
                {
 
1099
                        Rect_SetLeft(r, val1);
 
1100
                        ret = Rect_SetBottom(r, val2);
 
1101
                }
 
1102
        }       
 
1103
        else if(!strcmp(name, "topright"))
 
1104
        {
 
1105
                if(TwoShortsFromObj(op, &val1, &val2))
 
1106
                {
 
1107
                        Rect_SetRight(r, val1);
 
1108
                        ret = Rect_SetTop(r, val2);
 
1109
                }
 
1110
        }       
 
1111
        else if(!strcmp(name, "bottomright"))
 
1112
        {
 
1113
                if(TwoShortsFromObj(op, &val1, &val2))
 
1114
                {
 
1115
                        Rect_SetRight(r, val1);
 
1116
                        ret = Rect_SetBottom(r, val2);
 
1117
                }
 
1118
        }       
 
1119
        else if(!strcmp(name, "size"))
 
1120
        {
 
1121
                if(TwoShortsFromObj(op, &val1, &val2))
 
1122
                {
 
1123
                        Rect_SetWidth(r, val1);
 
1124
                        ret = Rect_SetHeight(r, val2);
 
1125
                }
 
1126
        }       
 
1127
        else if(!strcmp(name, "center"))
 
1128
        {
 
1129
                if(TwoShortsFromObj(op, &val1, &val2))
 
1130
                {
 
1131
                        r->x += val1 - (r->x + r->w / 2);
 
1132
                        r->y += val2 - (r->y + r->h / 2);
 
1133
                        ret = 0;
 
1134
                }
 
1135
        }
 
1136
        else if(!strcmp(name, "centerx"))
 
1137
        {
 
1138
                if(ShortFromObj(op, &val1))
 
1139
                {
 
1140
                        r->x += val1 - (r->x + r->w / 2);
 
1141
                        ret = 0;
 
1142
                }
 
1143
        }
 
1144
        else if(!strcmp(name, "centery"))
 
1145
        {
 
1146
                if(ShortFromObj(op, &val1))
 
1147
                {
 
1148
                        r->y += val1 - (r->y + r->h / 2);
 
1149
                        ret = 0;
 
1150
                }
 
1151
        }
 
1152
 
 
1153
        else if(!strcmp(name, "midleft"))
 
1154
        {
 
1155
                if(TwoShortsFromObj(op, &val1, &val2))
 
1156
                {
 
1157
                        r->x = val1;
 
1158
                        r->y += val2 - (r->y + r->h / 2);
 
1159
                        ret = 0;
 
1160
                }
 
1161
        }
 
1162
        else if(!strcmp(name, "midright"))
 
1163
        {
 
1164
                if(TwoShortsFromObj(op, &val1, &val2))
 
1165
                {
 
1166
                        r->x = val1 - r->w;
 
1167
                        r->y += val2 - (r->y + r->h / 2);
 
1168
                        ret = 0;
 
1169
                }
 
1170
        }
 
1171
        else if(!strcmp(name, "midtop"))
 
1172
        {
 
1173
                if(TwoShortsFromObj(op, &val1, &val2))
 
1174
                {
 
1175
                        r->x += val1 - (r->x + r->w / 2);
 
1176
                        r->y = val2;
 
1177
                        ret = 0;
 
1178
                }
 
1179
        }
 
1180
        else if(!strcmp(name, "midbottom"))
 
1181
        {
 
1182
                if(TwoShortsFromObj(op, &val1, &val2))
 
1183
                {
 
1184
                        r->x += val1 - (r->x + r->w / 2);
 
1185
                        r->y = val2 - r->h;
 
1186
                        ret = 0;
 
1187
                }
 
1188
        }
 
1189
        
 
1190
        else    
 
1191
        {
 
1192
                RAISE(PyExc_AttributeError, "Attribute cannot be modified");
 
1193
                return -1;
 
1194
        }
 
1195
 
 
1196
        if(ret == -1)
 
1197
                RAISE(PyExc_TypeError, "Unable to assign to rect attribute");
 
1198
 
 
1199
        return ret;
 
1200
}
 
1201
 
 
1202
 
 
1203
    /*DOC*/ static char doc_Rect_MODULE[] =
 
1204
    /*DOC*/    "The rectangle object is a useful object\n"
 
1205
    /*DOC*/    "representing a rectangle area. Rectangles are\n"
 
1206
        /*DOC*/    "created from the pygame.Rect() function. This routine\n"
 
1207
        /*DOC*/    "is also in the locals module, so importing the locals\n"
 
1208
        /*DOC*/    "into your namespace allows you to just use Rect().\n"
 
1209
    /*DOC*/    "\n"
 
1210
    /*DOC*/    "Rect contains helpful methods, as well as a list of\n"
 
1211
    /*DOC*/    "modifiable members:\n"
 
1212
    /*DOC*/    "top, bottom, left, right, topleft, topright,\n"
 
1213
    /*DOC*/    "bottomleft, bottomright, size, width, height,\n"
 
1214
    /*DOC*/    "center, centerx, centery, midleft, midright, midtop,\n"
 
1215
        /*DOC*/    "midbottom. When changing thesemembers, the rectangle\n"
 
1216
    /*DOC*/    "will be moved to the given assignment. (except when\n"
 
1217
    /*DOC*/    "changing the size, width, or height member, which will\n"
 
1218
    /*DOC*/    "resize the rectangle from the topleft corner)\n"
 
1219
    /*DOC*/    "\n"
 
1220
    /*DOC*/    "The rectstyle arguments used frequently with the\n"
 
1221
    /*DOC*/    "Rect object (and elsewhere in pygame) is one of\n"
 
1222
    /*DOC*/    "the following things. First, an actual Rect\n"
 
1223
    /*DOC*/    "object. Second, a sequence of [xpos, ypos, width,\n"
 
1224
    /*DOC*/    "height]. Lastly, a pair of sequences, representing\n"
 
1225
    /*DOC*/    "the position and size [[xpos, ypos], [width,\n"
 
1226
    /*DOC*/    "height]]. Also, if a method takes a rectstyle\n"
 
1227
    /*DOC*/    "argument as its only argument, you can simply pass\n"
 
1228
    /*DOC*/    "four arguments representing xpos, ypos, width,\n"
 
1229
    /*DOC*/    "height.\n"
 
1230
    /*DOC*/ ;
 
1231
 
 
1232
static PyTypeObject PyRect_Type = { 
 
1233
        PyObject_HEAD_INIT(0)
 
1234
        0,                                                      /*size*/
 
1235
        "Rect",                                         /*name*/
 
1236
        sizeof(PyRectObject),           /*basicsize*/
 
1237
        0,                                                      /*itemsize*/
 
1238
        /* methods */
 
1239
        (destructor)rect_dealloc,       /*dealloc*/
 
1240
        (printfunc)NULL,                        /*print*/
 
1241
        (getattrfunc)rect_getattr,      /*getattr*/
 
1242
        (setattrfunc)rect_setattr,      /*setattr*/
 
1243
        (cmpfunc)rect_compare,          /*compare*/
 
1244
        (reprfunc)rect_repr,            /*repr*/
 
1245
        &rect_as_number,                        /*as_number*/
 
1246
        &rect_as_sequence,                      /*as_sequence*/
 
1247
        NULL,                                           /*as_mapping*/
 
1248
        (hashfunc)NULL,                         /*hash*/
 
1249
        (ternaryfunc)NULL,                      /*call*/
 
1250
        (reprfunc)rect_str,                     /*str*/
 
1251
 
 
1252
        /* Space for future expansion */
 
1253
        0L,0L,0L,0L,
 
1254
        doc_Rect_MODULE /* Documentation string */
 
1255
};
 
1256
 
 
1257
 
 
1258
 
 
1259
/*module globals*/
 
1260
 
 
1261
    /*DOC*/ static char doc_Rect[] =
 
1262
    /*DOC*/    "pygame.Rect(rectstyle) -> Rect\n"
 
1263
    /*DOC*/    "create a new rectangle\n"
 
1264
    /*DOC*/    "\n"
 
1265
    /*DOC*/    "Creates a new rectangle object. The given\n"
 
1266
    /*DOC*/    "rectstyle represents one of the various ways of\n"
 
1267
    /*DOC*/    "representing rectangle data. This is usually a\n"
 
1268
    /*DOC*/    "sequence of x and y position for the topleft\n"
 
1269
    /*DOC*/    "corner, and the width and height.\n"
 
1270
    /*DOC*/    "\n"
 
1271
    /*DOC*/    "For some of the Rect methods there are two version.\n"
 
1272
    /*DOC*/    "For example, there is move() and move_ip(). The methods\n"
 
1273
    /*DOC*/    "witht the '_ip' suffix on the name are the 'in-place'\n"
 
1274
    /*DOC*/    "version of those functions. They effect the actual\n"
 
1275
    /*DOC*/    "source object, instead of returning a new Rect object.\n"
 
1276
    /*DOC*/ ;
 
1277
 
 
1278
static PyObject* RectInit(PyObject* self, PyObject* args)
 
1279
{
 
1280
        GAME_Rect *argrect, temp;
 
1281
        if(!(argrect = GameRect_FromObject(args, &temp)))
 
1282
                return RAISE(PyExc_TypeError, "Argument must be rect style object");
 
1283
 
 
1284
        return PyRect_New4(argrect->x, argrect->y, argrect->w, argrect->h);
 
1285
}
 
1286
 
 
1287
 
 
1288
 
 
1289
static PyMethodDef rect__builtins__[] =
 
1290
{
 
1291
        { "Rect", RectInit, 1, doc_Rect }, 
 
1292
        {NULL, NULL}
 
1293
};
 
1294
 
 
1295
 
 
1296
 
 
1297
 
 
1298
    /*DOC*/ static char rectangle_doc[] =
 
1299
    /*DOC*/    "Module for the rectangle object\n";
 
1300
 
 
1301
PYGAME_EXPORT
 
1302
void initrect(void)
 
1303
{
 
1304
        PyObject *module, *dict, *apiobj;
 
1305
        static void* c_api[PYGAMEAPI_RECT_NUMSLOTS];
 
1306
        
 
1307
        PyGAME_C_API[0] = PyGAME_C_API[0]; /*this cleans a compiler warning*/
 
1308
 
 
1309
        /* Create the module and add the functions */
 
1310
        PyType_Init(PyRect_Type);
 
1311
 
 
1312
 
 
1313
        module = Py_InitModule3("rect", rect__builtins__, rectangle_doc);
 
1314
        dict = PyModule_GetDict(module);
 
1315
 
 
1316
        PyDict_SetItemString(dict, "RectType", (PyObject *)&PyRect_Type);
 
1317
 
 
1318
        /* export the c api */
 
1319
        c_api[0] = &PyRect_Type;
 
1320
        c_api[1] = PyRect_New;
 
1321
        c_api[2] = PyRect_New4;
 
1322
        c_api[3] = GameRect_FromObject;
 
1323
        apiobj = PyCObject_FromVoidPtr(c_api, NULL);
 
1324
        PyDict_SetItemString(dict, PYGAMEAPI_LOCAL_ENTRY, apiobj);
 
1325
        Py_DECREF(apiobj);
 
1326
 
 
1327
        /*imported needed apis*/
 
1328
        import_pygame_base();
 
1329
}