Skip to content

Commit 83d395f

Browse files
authored
Merge pull request #3089 from bilhox/rect-center
Implementation of ``pygame.(F)Rect.relcenter``
2 parents 8d13367 + 380ad24 commit 83d395f

File tree

5 files changed

+189
-2
lines changed

5 files changed

+189
-2
lines changed

buildconfig/stubs/pygame/rect.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ class _GenericRect(Collection[_N]):
9696
@center.setter
9797
def center(self, value: Point) -> None: ...
9898
@property
99+
def relcenter(self) -> tuple[_N, _N]: ...
100+
@relcenter.setter
101+
def relcenter(self, value: Point) -> None: ...
102+
@property
99103
def centerx(self) -> _N: ...
100104
@centerx.setter
101105
def centerx(self, value: float) -> None: ...

docs/reST/ref/rect.rst

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
topleft, bottomleft, topright, bottomright
4949
midtop, midleft, midbottom, midright
5050
center, centerx, centery
51-
size, width, height
51+
size, width, height, relcenter
5252
w,h
5353

5454
All of these attributes can be assigned to:
@@ -58,7 +58,7 @@
5858
rect1.right = 10
5959
rect2.center = (20,30)
6060

61-
Assigning to size, width or height changes the dimensions of the rectangle;
61+
Assigning to size, width, height, or relcenter changes the dimensions of the rectangle;
6262
all other assignments move the rectangle without resizing it. Notice that
6363
some attributes are integers and others are pairs of integers.
6464

@@ -93,6 +93,25 @@
9393
and ``__new__()`` is assumed to take no arguments. So these methods should be
9494
overridden if any extra attributes need to be copied.
9595

96+
.. versionadded:: 2.5.6
97+
``relcenter`` added to Rect / FRect. This will return a tuple containing half
98+
the Rect's size; the center relative to the topleft of the Rect.
99+
Setting it to a ``Point`` will modify the size of the rect to 2 times
100+
the ``Point`` given. Below you can find a code example of how it should work:
101+
102+
.. code-block:: python
103+
104+
>>> my_rect = pygame.Rect(0, 0, 2, 2)
105+
>>> my_rect.relcenter
106+
(1, 1)
107+
>>> my_rect.relcenter = (128, 128)
108+
>>> my_rect.size
109+
(256, 256)
110+
111+
Beware of non-integer relative centers! For Rects (but not FRects), ``relcenter``
112+
will truncate the numbers in the returned tuple.
113+
114+
96115
.. method:: copy
97116

98117
| :sl:`copy the rectangle`

src_c/rect.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ four_floats_from_obj(PyObject *obj, float *val1, float *val2, float *val3,
133133
#define RectExport_setmidright pg_rect_setmidright
134134
#define RectExport_getcenter pg_rect_getcenter
135135
#define RectExport_setcenter pg_rect_setcenter
136+
#define RectExport_getrelcenter pg_rect_getrelcenter
137+
#define RectExport_setrelcenter pg_rect_setrelcenter
136138
#define RectExport_getsize pg_rect_getsize
137139
#define RectExport_setsize pg_rect_setsize
138140
#define RectImport_primitiveType int
@@ -250,6 +252,8 @@ four_floats_from_obj(PyObject *obj, float *val1, float *val2, float *val3,
250252
#define RectExport_setmidright pg_frect_setmidright
251253
#define RectExport_getcenter pg_frect_getcenter
252254
#define RectExport_setcenter pg_frect_setcenter
255+
#define RectExport_getrelcenter pg_frect_getrelcenter
256+
#define RectExport_setrelcenter pg_frect_setrelcenter
253257
#define RectExport_getsize pg_frect_getsize
254258
#define RectExport_setsize pg_frect_setsize
255259
#define RectImport_primitiveType float
@@ -685,6 +689,8 @@ static PyGetSetDef pg_frect_getsets[] = {
685689
{"size", (getter)pg_frect_getsize, (setter)pg_frect_setsize, NULL, NULL},
686690
{"center", (getter)pg_frect_getcenter, (setter)pg_frect_setcenter, NULL,
687691
NULL},
692+
{"relcenter", (getter)pg_frect_getrelcenter, (setter)pg_frect_setrelcenter,
693+
NULL, NULL},
688694

689695
{"__safe_for_unpickling__", (getter)pg_rect_getsafepickle, NULL, NULL,
690696
NULL},
@@ -727,6 +733,8 @@ static PyGetSetDef pg_rect_getsets[] = {
727733
{"size", (getter)pg_rect_getsize, (setter)pg_rect_setsize, NULL, NULL},
728734
{"center", (getter)pg_rect_getcenter, (setter)pg_rect_setcenter, NULL,
729735
NULL},
736+
{"relcenter", (getter)pg_rect_getrelcenter, (setter)pg_rect_setrelcenter,
737+
NULL, NULL},
730738

731739
{"__safe_for_unpickling__", (getter)pg_rect_getsafepickle, NULL, NULL,
732740
NULL},

src_c/rect_impl.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@
284284
#ifndef RectExport_setcenter
285285
#error RectExport_setcenter needs to be defined
286286
#endif
287+
#ifndef RectExport_getrelcenter
288+
#error RectExport_getrelcenter needs to be defined
289+
#endif
290+
#ifndef RectExport_setrelcenter
291+
#error RectExport_setrelcenter needs to be defined
292+
#endif
287293
#ifndef RectExport_getsize
288294
#error RectExport_getsize needs to be defined
289295
#endif
@@ -605,6 +611,10 @@ RectExport_getcenter(RectObject *self, void *closure);
605611
static int
606612
RectExport_setcenter(RectObject *self, PyObject *value, void *closure);
607613
static PyObject *
614+
RectExport_getrelcenter(RectObject *self, void *closure);
615+
static int
616+
RectExport_setrelcenter(RectObject *self, PyObject *value, void *closure);
617+
static PyObject *
608618
RectExport_getsize(RectObject *self, void *closure);
609619
static int
610620
RectExport_setsize(RectObject *self, PyObject *value, void *closure);
@@ -2826,6 +2836,33 @@ RectExport_getcenter(RectObject *self, void *closure)
28262836
self->r.y + (self->r.h / 2));
28272837
}
28282838

2839+
/*relcenter*/
2840+
static PyObject *
2841+
RectExport_getrelcenter(RectObject *self, void *closure)
2842+
{
2843+
return TupleFromTwoPrimitives(self->r.w / 2, self->r.h / 2);
2844+
}
2845+
2846+
static int
2847+
RectExport_setrelcenter(RectObject *self, PyObject *value, void *closure)
2848+
{
2849+
PrimitiveType val1, val2;
2850+
2851+
if (NULL == value) {
2852+
/* Attribute deletion not supported. */
2853+
PyErr_SetString(PyExc_AttributeError, "can't delete attribute");
2854+
return -1;
2855+
}
2856+
2857+
if (!twoPrimitivesFromObj(value, &val1, &val2)) {
2858+
PyErr_SetString(PyExc_TypeError, "invalid rect assignment");
2859+
return -1;
2860+
}
2861+
self->r.w = val1 * 2;
2862+
self->r.h = val2 * 2;
2863+
return 0;
2864+
}
2865+
28292866
static int
28302867
RectExport_setcenter(RectObject *self, PyObject *value, void *closure)
28312868
{
@@ -2980,6 +3017,8 @@ RectExport_iterator(RectObject *self)
29803017
#undef RectExport_setmidright
29813018
#undef RectExport_getcenter
29823019
#undef RectExport_setcenter
3020+
#undef RectExport_getrelcenter
3021+
#undef RectExport_setrelcenter
29833022
#undef RectExport_getsize
29843023
#undef RectExport_setsize
29853024
#undef RectExport_iterator

0 commit comments

Comments
 (0)