30
30
staticforward PyTypeObject PyRect_Type;
31
31
#define PyRect_Check(x) ((x)->ob_type == &PyRect_Type)
33
#if PYTHON_API_VERSION >= 1011 /*this is the python-2.2 constructor*/
34
static PyObject* rect_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
35
39
GAME_Rect* GameRect_FromObject(PyObject* obj, GAME_Rect* temp)
39
44
if(PyRect_Check(obj))
40
45
return &((PyRectObject*)obj)->r;
42
if(PySequence_Check(obj))
46
if(PySequence_Check(obj) && (length=PySequence_Length(obj))>0)
44
if(PySequence_Length(obj) == 4)
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
if(!IntFromObjIndex(obj, 0, &val)) return NULL; temp->x = val;
51
if(!IntFromObjIndex(obj, 1, &val)) return NULL; temp->y = val;
52
if(!IntFromObjIndex(obj, 2, &val)) return NULL; temp->w = val;
53
if(!IntFromObjIndex(obj, 3, &val)) return NULL; temp->h = val;
52
if(PySequence_Length(obj) == 2)
54
58
PyObject* sub = PySequence_GetItem(obj, 0);
55
59
if(!sub || !PySequence_Check(sub) || PySequence_Length(sub)!=2)
56
60
{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;
61
if(!IntFromObjIndex(sub, 0, &val)) {Py_DECREF(sub); return NULL;} temp->x = val;
62
if(!IntFromObjIndex(sub, 1, &val)) {Py_DECREF(sub); return NULL;} temp->y = val;
60
64
sub = PySequence_GetItem(obj, 1);
61
65
if(!sub || !PySequence_Check(sub) || PySequence_Length(sub)!=2)
62
66
{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;
67
if(!IntFromObjIndex(sub, 0, &val)) {Py_DECREF(sub); return NULL;} temp->w = val;
68
if(!IntFromObjIndex(sub, 1, &val)) {Py_DECREF(sub); return NULL;} temp->h = val;
68
if(PyTuple_Check(obj) && PyTuple_Size(obj) == 1) /*looks like an arg?*/
72
if(PyTuple_Check(obj) && length == 1) /*looks like an arg?*/
70
74
PyObject* sub = PyTuple_GET_ITEM(obj, 0);
72
76
return GameRect_FromObject(sub, temp);
79
if(PyObject_HasAttrString(obj, "rect"))
82
GAME_Rect *returnrect;
83
rectattr = PyObject_GetAttrString(obj, "rect");
84
if(PyCallable_Check(rectattr)) /*call if it's a method*/
86
PyObject *rectresult = PyObject_CallObject(rectattr, NULL);
90
rectattr = rectresult;
92
returnrect = GameRect_FromObject(rectattr, temp);
78
static int Rect_SetTop(GAME_Rect* r, short val)
99
static int Rect_SetTop(GAME_Rect* r, int val)
83
static int Rect_SetBottom(GAME_Rect* r, short val)
104
static int Rect_SetBottom(GAME_Rect* r, int val)
85
106
r->y = val - r->h;
88
static int Rect_SetLeft(GAME_Rect* r, short val)
109
static int Rect_SetLeft(GAME_Rect* r, int val)
93
static int Rect_SetRight(GAME_Rect* r, short val)
114
static int Rect_SetRight(GAME_Rect* r, int val)
95
116
r->x = val - r->w;
98
static int Rect_SetWidth(GAME_Rect* r, short val)
119
static int Rect_SetWidth(GAME_Rect* r, int val)
100
121
// r->x -= val - r->w;
104
static int Rect_SetHeight(GAME_Rect* r, short val)
125
static int Rect_SetHeight(GAME_Rect* r, int val)
106
127
// r->y -= val - r->h;
111
PyObject* PyRect_New(GAME_Rect* r)
132
PyObject* PyRect_New(SDL_Rect* r)
113
134
PyRectObject* rect = PyObject_NEW(PyRectObject, &PyRect_Type);
117
138
rect->r.x = r->x;
118
139
rect->r.y = r->y;
119
140
rect->r.w = r->w;
604
/*DOC*/ static char doc_collidedict[] =
605
/*DOC*/ "Rect.collidedict(dict if rectstyle keys) -> key/value pair\n"
606
/*DOC*/ "find overlapping rectangle in a dictionary\n"
608
/*DOC*/ "Returns the key/value pair of the first rectangle key\n"
609
/*DOC*/ "in the dict that overlaps the base rectangle. Once an\n"
610
/*DOC*/ "overlap is found, this will stop checking the\n"
611
/*DOC*/ "remaining list. If no overlap is found, it will\n"
612
/*DOC*/ "return None.\n"
614
/*DOC*/ "Remember python dictionary keys must be immutable,\n"
615
/*DOC*/ "Rects are not immutable, so they cannot directly be,\n"
616
/*DOC*/ "dictionary keys. You can convert the Rect to a tuple\n"
617
/*DOC*/ "with the tuple() builtin command.\n"
620
static PyObject* rect_collidedict(PyObject* oself, PyObject* args)
622
PyRectObject* self = (PyRectObject*)oself;
623
GAME_Rect *argrect, temp;
625
PyObject* dict, *key, *val;
626
PyObject* ret = NULL;
628
if(!PyArg_ParseTuple(args, "O", &dict))
630
if(!PyDict_Check(dict))
631
return RAISE(PyExc_TypeError, "Argument must be a dict with rectstyle keys.");
633
while(PyDict_Next(dict, &loop, &key, &val))
635
if(!(argrect = GameRect_FromObject(key, &temp)))
637
RAISE(PyExc_TypeError, "Argument must be a dict with rectstyle keys.");
640
if(DoRectsIntersect(&self->r, argrect))
642
ret = Py_BuildValue("(OO)", key, val);
656
/*DOC*/ static char doc_collidedictall[] =
657
/*DOC*/ "Rect.collidedictall(rectstyle list) -> key/val list\n"
658
/*DOC*/ "find all overlapping rectangles\n"
660
/*DOC*/ "Returns a list of the indexes that contain\n"
661
/*DOC*/ "rectangles overlapping the base rectangle. If no\n"
662
/*DOC*/ "overlap is found, it will return an empty\n"
663
/*DOC*/ "sequence.\n"
665
/*DOC*/ "Remember python dictionary keys must be immutable,\n"
666
/*DOC*/ "Rects are not immutable, so they cannot directly be,\n"
667
/*DOC*/ "dictionary keys. You can convert the Rect to a tuple\n"
668
/*DOC*/ "with the tuple() builtin command.\n"
671
static PyObject* rect_collidedictall(PyObject* oself, PyObject* args)
673
PyRectObject* self = (PyRectObject*)oself;
674
GAME_Rect *argrect, temp;
676
PyObject* dict, *key, *val;
677
PyObject* ret = NULL;
679
if(!PyArg_ParseTuple(args, "O", &dict))
681
if(!PyDict_Check(dict))
682
return RAISE(PyExc_TypeError, "Argument must be a dict with rectstyle keys.");
688
while(PyDict_Next(dict, &loop, &key, &val))
690
if(!(argrect = GameRect_FromObject(key, &temp)))
693
return RAISE(PyExc_TypeError, "Argument must be a dict with rectstyle keys.");
696
if(DoRectsIntersect(&self->r, argrect))
698
PyObject* num = Py_BuildValue("(OO)", key, val);
701
PyList_Append(ret, num);
755
895
{"clamp_ip", (PyCFunction)rect_clamp_ip, 1, doc_clamp_ip},
757
897
{"move", (PyCFunction)rect_move, 1, doc_move},
758
{"inflate", (PyCFunction)rect_inflate, 1, doc_inflate},
898
{"inflate", (PyCFunction)rect_inflate, 1, doc_inflate},
759
899
{"union", (PyCFunction)rect_union, 1, doc_union},
760
900
{"unionall", (PyCFunction)rect_unionall, 1, doc_unionall},
762
902
{"move_ip", (PyCFunction)rect_move_ip, 1, doc_move_ip},
763
{"inflate_ip", (PyCFunction)rect_inflate_ip, 1, doc_inflate_ip},
903
{"inflate_ip", (PyCFunction)rect_inflate_ip, 1, doc_inflate_ip},
764
904
{"union_ip", (PyCFunction)rect_union_ip, 1, doc_union_ip},
765
905
{"unionall_ip", (PyCFunction)rect_unionall_ip, 1, doc_unionall_ip},
768
908
{"colliderect", (PyCFunction)rect_colliderect, 1, doc_colliderect},
769
909
{"collidelist", (PyCFunction)rect_collidelist, 1, doc_collidelist},
770
910
{"collidelistall", (PyCFunction)rect_collidelistall,1,doc_collidelistall},
911
{"collidedict", (PyCFunction)rect_collidedict, 1, doc_collidedict},
912
{"collidedictall", (PyCFunction)rect_collidedictall,1,doc_collidedictall},
771
913
{"contains", (PyCFunction)rect_contains, 1, doc_contains},
772
914
/* these are totally unwritten. volunteers? */
773
915
/* {"cleanup", (PyCFunction)rect_cleanup, 1, doc_cleanup}, */
774
916
/* {"remove", (PyCFunction)rect_remove, 1, doc_remove}, */
918
{"__reduce__", (PyCFunction)rect_reduce, 0, NULL},
1003
1148
PyObject *ret = NULL;
1004
1149
GAME_Rect *r = &self->r;
1006
if(!strcmp(name, "top"))
1151
if(!strcmp(name, "top") || !strcmp(name, "y"))
1007
1152
ret = PyInt_FromLong(r->y);
1008
1153
else if(!strcmp(name, "bottom"))
1009
1154
ret = PyInt_FromLong(r->y + r->h);
1010
else if(!strcmp(name, "left"))
1155
else if(!strcmp(name, "left") || !strcmp(name, "x"))
1011
1156
ret = PyInt_FromLong(r->x);
1012
1157
else if(!strcmp(name, "right"))
1013
1158
ret = PyInt_FromLong(r->x + r->w);
1014
else if(!strcmp(name, "width"))
1159
else if(!strcmp(name, "width") || !strcmp(name, "w"))
1015
1160
ret = PyInt_FromLong(r->w);
1016
else if(!strcmp(name, "height"))
1161
else if(!strcmp(name, "height") || !strcmp(name, "h"))
1017
1162
ret = PyInt_FromLong(r->h);
1018
1163
else if(!strcmp(name, "centerx"))
1019
1164
ret = PyInt_FromLong(r->x+r->w/2);
1051
1198
static int rect_setattr(PyRectObject *self, char *name, PyObject *op)
1055
1202
GAME_Rect *r = &self->r;
1057
if(!strcmp(name, "top"))
1204
if(!strcmp(name, "top") || !strcmp(name, "y"))
1059
if(ShortFromObj(op, &val1))
1206
if(IntFromObj(op, &val1))
1060
1207
ret = Rect_SetTop(r, val1);
1062
1209
else if(!strcmp(name, "bottom"))
1064
if(ShortFromObj(op, &val1))
1211
if(IntFromObj(op, &val1))
1065
1212
ret = Rect_SetBottom(r, val1);
1067
else if(!strcmp(name, "left"))
1214
else if(!strcmp(name, "left") || !strcmp(name, "x"))
1069
if(ShortFromObj(op, &val1))
1216
if(IntFromObj(op, &val1))
1070
1217
ret = Rect_SetLeft(r, val1);
1072
1219
else if(!strcmp(name, "right"))
1074
if(ShortFromObj(op, &val1))
1221
if(IntFromObj(op, &val1))
1075
1222
ret = Rect_SetRight(r, val1);
1077
else if(!strcmp(name, "width"))
1224
else if(!strcmp(name, "width") || !strcmp(name, "w"))
1079
if(ShortFromObj(op, &val1))
1226
if(IntFromObj(op, &val1))
1080
1227
ret = Rect_SetWidth(r, val1);
1082
else if(!strcmp(name, "height"))
1229
else if(!strcmp(name, "height") || !strcmp(name, "h"))
1084
if(ShortFromObj(op, &val1))
1231
if(IntFromObj(op, &val1))
1085
1232
ret = Rect_SetHeight(r, val1);
1087
1234
else if(!strcmp(name, "topleft"))
1089
if(TwoShortsFromObj(op, &val1, &val2))
1236
if(TwoIntsFromObj(op, &val1, &val2))
1091
1238
Rect_SetLeft(r, val1);
1092
1239
ret = Rect_SetTop(r, val2);
1095
1242
else if(!strcmp(name, "bottomleft"))
1097
if(TwoShortsFromObj(op, &val1, &val2))
1244
if(TwoIntsFromObj(op, &val1, &val2))
1099
1246
Rect_SetLeft(r, val1);
1100
1247
ret = Rect_SetBottom(r, val2);
1103
1250
else if(!strcmp(name, "topright"))
1105
if(TwoShortsFromObj(op, &val1, &val2))
1252
if(TwoIntsFromObj(op, &val1, &val2))
1107
1254
Rect_SetRight(r, val1);
1108
1255
ret = Rect_SetTop(r, val2);
1111
1258
else if(!strcmp(name, "bottomright"))
1113
if(TwoShortsFromObj(op, &val1, &val2))
1260
if(TwoIntsFromObj(op, &val1, &val2))
1115
1262
Rect_SetRight(r, val1);
1116
1263
ret = Rect_SetBottom(r, val2);
1119
1266
else if(!strcmp(name, "size"))
1121
if(TwoShortsFromObj(op, &val1, &val2))
1268
if(TwoIntsFromObj(op, &val1, &val2))
1123
1270
Rect_SetWidth(r, val1);
1124
1271
ret = Rect_SetHeight(r, val2);
1127
1274
else if(!strcmp(name, "center"))
1129
if(TwoShortsFromObj(op, &val1, &val2))
1276
if(TwoIntsFromObj(op, &val1, &val2))
1131
1278
r->x += val1 - (r->x + r->w / 2);
1132
1279
r->y += val2 - (r->y + r->h / 2);
1203
1350
/*DOC*/ static char doc_Rect_MODULE[] =
1204
1351
/*DOC*/ "The rectangle object is a useful object\n"
1205
1352
/*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"
1353
/*DOC*/ "created from the pygame.Rect() function. This routine\n"
1354
/*DOC*/ "is also in the locals module, so importing the locals\n"
1355
/*DOC*/ "into your namespace allows you to just use Rect().\n"
1210
1357
/*DOC*/ "Rect contains helpful methods, as well as a list of\n"
1211
1358
/*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"
1360
/*NODOC*/ "top, bottom, left, right, topleft, topright,\n"
1361
/*NODOC*/ "bottomleft, bottomright, size, width, height,\n"
1362
/*NODOC*/ "center, centerx, centery, midleft, midright, midtop,\n"
1363
/*NODOC*/ "midbottom.\n"
1365
/*DOC*/ "<table border="0" cellspacing=0 cellpadding=0 width=66%><tr valign=top><td align=left><ul><li>top<li>bottom<li>left<li>right</ul></td>\n"
1366
/*DOC*/ "<td align=left><ul><li>topleft<li>topright<li>bottomleft<li>bottomright</ul></td>\n"
1367
/*DOC*/ "<td align=left><ul><li>midleft<li>midright<li>midtop<li>midbottom</ul></td>\n"
1368
/*DOC*/ "<td align=left><ul><li>center<li>centerx<li>centery</ul></td>\n"
1369
/*DOC*/ "<td align=left><ul><li>size<li>width<li>height</ul></td>\n"
1370
/*DOC*/ "</tr></table><br>\n"
1372
/*DOC*/ "When changing these members, the rectangle\n"
1216
1373
/*DOC*/ "will be moved to the given assignment. (except when\n"
1217
1374
/*DOC*/ "changing the size, width, or height member, which will\n"
1218
1375
/*DOC*/ "resize the rectangle from the topleft corner)\n"
1220
1377
/*DOC*/ "The rectstyle arguments used frequently with the\n"
1221
1378
/*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"
1379
/*DOC*/ "the following things.\n"
1381
/*NODOC*/ "First, an actual Rect\n"
1382
/*NODOC*/ "object. Second, a sequence of [xpos, ypos, width,\n"
1383
/*NODOC*/ "height]. Lastly, a pair of sequences, representing\n"
1384
/*NODOC*/ "the position and size [[xpos, ypos], [width,\n"
1385
/*NODOC*/ "height]]. Also, if a method takes a rectstyle\n"
1386
/*NODOC*/ "argument as its only argument, you can simply pass\n"
1387
/*NODOC*/ "four arguments representing xpos, ypos, width,\n"
1388
/*NODOC*/ "height. A rectstyle argument can also be _any_ python\n"
1389
/*NODOC*/ "object with an attribute named 'rect'.\n"
1391
/*DOC*/ "<table border=0 cellspacing=0 cellpadding=0 width=80%>\n"
1392
/*DOC*/ "<tr align=left valign=top><td align=left valign=middle width=20%><blockquote> </blockquote></td><td align=left valign=top><ul>\n"
1393
/*DOC*/ "<li>an actual Rect object. \n"
1394
/*DOC*/ "<li>a sequence of [xpos, ypos, width, height]. \n"
1395
/*DOC*/ "<li>a pair of sequences, representing the position and size [[xpos, ypos], [width,height]]. \n"
1396
/*DOC*/ "<li>if a method takes a rectstyle argument <b>as its <i>only</i> argument</b>, you can simply pass four arguments representing xpos, ypos, width, height. \n"
1397
/*DOC*/ "</ul>and perhaps most importantly:\n"
1398
/*DOC*/ "<ul><li>A rectstyle argument can also be <b><strong>_any_ python object</b> with an attribute named <b>'rect'.</b></strong>\n"
1399
/*DOC*/ "</ul></td></tr></table>\n"
1232
static PyTypeObject PyRect_Type = {
1403
static PyTypeObject PyRect_Type = {
1233
1404
PyObject_HEAD_INIT(0)
1235
1406
"Rect", /*name*/
1483
#if PYTHON_API_VERSION >= 1011 /*this is the python-2.2 constructor*/
1484
static PyObject* rect_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1486
GAME_Rect *argrect, temp;
1487
if(!(argrect = GameRect_FromObject(args, &temp)))
1488
return RAISE(PyExc_TypeError, "Argument must be rect style object");
1490
return PyRect_New4(argrect->x, argrect->y, argrect->w, argrect->h);
1289
1495
static PyMethodDef rect__builtins__[] =
1291
{ "Rect", RectInit, 1, doc_Rect },
1497
#if PYTHON_API_VERSION < 1011 /*PYTHON2.2*/
1498
{ "Rect", RectInit, 1, doc_Rect },