Skip to content

Commit 4920fcf

Browse files
authored
Merge pull request #2111 from ScriptLineStudios/Surface.set_at
vector2 support for Surface.get_at and set_at
2 parents 8b40aee + 3741623 commit 4920fcf

File tree

4 files changed

+50
-17
lines changed

4 files changed

+50
-17
lines changed

buildconfig/stubs/pygame/surface.pyi

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ from pygame.rect import FRect, Rect
77
from ._common import (
88
ColorValue,
99
Coordinate,
10-
IntCoordinate,
1110
Literal,
1211
RectValue,
1312
RGBAOutput,
@@ -117,9 +116,9 @@ class Surface:
117116
def mustlock(self) -> bool: ...
118117
def get_locked(self) -> bool: ...
119118
def get_locks(self) -> Tuple[Any, ...]: ...
120-
def get_at(self, x_y: IntCoordinate) -> Color: ...
121-
def set_at(self, x_y: IntCoordinate, color: ColorValue) -> None: ...
122-
def get_at_mapped(self, x_y: IntCoordinate) -> int: ...
119+
def get_at(self, x_y: Coordinate) -> Color: ...
120+
def set_at(self, x_y: Coordinate, color: ColorValue) -> None: ...
121+
def get_at_mapped(self, x_y: Coordinate) -> int: ...
123122
def get_palette(self) -> List[Color]: ...
124123
def get_palette_at(self, index: int) -> Color: ...
125124
def set_palette(self, palette: Sequence[ColorValue]) -> None: ...

docs/reST/ref/surface.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -445,12 +445,15 @@
445445
methods - or by using :mod:`pygame.surfarray`/:mod:`pygame.PixelArray`.
446446

447447
This function will temporarily lock and unlock the Surface as needed.
448-
449-
.. versionaddedold:: 1.9
448+
449+
.. versionchanged:: 2.3.1 can now also accept both float coordinates and Vector2s for pixels.
450+
450451
Returning a Color instead of tuple. Use ``tuple(surf.get_at((x,y)))``
451452
if you want a tuple, and not a Color. This should only matter if
452453
you want to use the color as a key in a dict.
453-
454+
455+
.. versionaddedold:: 1.9
456+
454457
.. ## Surface.get_at ##
455458
456459
.. method:: set_at
@@ -471,6 +474,8 @@
471474
.. note:: If the surface is palettized, the pixel color will be set to the
472475
most similar color in the palette.
473476

477+
.. versionchanged:: 2.3.1 can now also accept both float coordinates and Vector2s for pixels.
478+
474479
.. ## Surface.set_at ##
475480
476481
.. method:: get_at_mapped
@@ -489,6 +494,8 @@
489494

490495
.. versionaddedold:: 1.9.2
491496

497+
.. versionchanged:: 2.3.1 can now also accept both float coordinates and Vector2s for pixels.
498+
492499
.. ## Surface.get_at_mapped ##
493500
494501
.. method:: get_palette

src_c/surface.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,9 @@ static PyGetSetDef surface_getsets[] = {
304304
{NULL, NULL, NULL, NULL, NULL}};
305305

306306
static struct PyMethodDef surface_methods[] = {
307-
{"get_at", surf_get_at, METH_VARARGS, DOC_SURFACE_GETAT},
307+
{"get_at", surf_get_at, METH_O, DOC_SURFACE_GETAT},
308308
{"set_at", surf_set_at, METH_VARARGS, DOC_SURFACE_SETAT},
309-
{"get_at_mapped", surf_get_at_mapped, METH_VARARGS,
310-
DOC_SURFACE_GETATMAPPED},
309+
{"get_at_mapped", surf_get_at_mapped, METH_O, DOC_SURFACE_GETATMAPPED},
311310
{"map_rgb", surf_map_rgb, METH_VARARGS, DOC_SURFACE_MAPRGB},
312311
{"unmap_rgb", surf_unmap_rgb, METH_O, DOC_SURFACE_UNMAPRGB},
313312

@@ -774,7 +773,7 @@ _raise_create_surface_error(void)
774773

775774
/* surface object methods */
776775
static PyObject *
777-
surf_get_at(PyObject *self, PyObject *args)
776+
surf_get_at(PyObject *self, PyObject *position)
778777
{
779778
SDL_Surface *surf = pgSurface_AsSurface(self);
780779
SDL_PixelFormat *format = NULL;
@@ -784,10 +783,13 @@ surf_get_at(PyObject *self, PyObject *args)
784783
Uint8 *pix;
785784
Uint8 rgba[4] = {0, 0, 0, 255};
786785

787-
if (!PyArg_ParseTuple(args, "(ii)", &x, &y))
788-
return NULL;
789786
SURF_INIT_CHECK(surf)
790787

788+
if (!pg_TwoIntsFromObj(position, &x, &y)) {
789+
return RAISE(PyExc_TypeError,
790+
"position must be a sequence of two numbers");
791+
}
792+
791793
if (x < 0 || x >= surf->w || y < 0 || y >= surf->h)
792794
return RAISE(PyExc_IndexError, "pixel index out of range");
793795

@@ -838,17 +840,23 @@ surf_set_at(PyObject *self, PyObject *args)
838840
SDL_PixelFormat *format = NULL;
839841
Uint8 *pixels;
840842
int x, y;
843+
PyObject *position;
841844
Uint32 color;
842845
Uint8 rgba[4] = {0, 0, 0, 0};
843846
PyObject *rgba_obj;
844847
Uint8 *byte_buf;
845848

846-
if (!PyArg_ParseTuple(args, "(ii)O", &x, &y, &rgba_obj))
849+
if (!PyArg_ParseTuple(args, "OO", &position, &rgba_obj))
847850
return NULL;
848851
SURF_INIT_CHECK(surf)
849852

850853
format = surf->format;
851854

855+
if (!pg_TwoIntsFromObj(position, &x, &y)) {
856+
return RAISE(PyExc_TypeError,
857+
"position must be a sequence of two numbers");
858+
}
859+
852860
if (format->BytesPerPixel < 1 || format->BytesPerPixel > 4)
853861
return RAISE(PyExc_RuntimeError, "invalid color depth for surface");
854862

@@ -913,7 +921,7 @@ surf_set_at(PyObject *self, PyObject *args)
913921
}
914922

915923
static PyObject *
916-
surf_get_at_mapped(PyObject *self, PyObject *args)
924+
surf_get_at_mapped(PyObject *self, PyObject *position)
917925
{
918926
SDL_Surface *surf = pgSurface_AsSurface(self);
919927
SDL_PixelFormat *format = NULL;
@@ -922,10 +930,13 @@ surf_get_at_mapped(PyObject *self, PyObject *args)
922930
Sint32 color;
923931
Uint8 *pix;
924932

925-
if (!PyArg_ParseTuple(args, "(ii)", &x, &y))
926-
return NULL;
927933
SURF_INIT_CHECK(surf)
928934

935+
if (!pg_TwoIntsFromObj(position, &x, &y)) {
936+
return RAISE(PyExc_TypeError,
937+
"position must be a sequence of two numbers");
938+
}
939+
929940
if (x < 0 || x >= surf->w || y < 0 || y >= surf->h)
930941
return RAISE(PyExc_IndexError, "pixel index out of range");
931942

test/surface_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ def test_set_at(self):
114114
self.assertIsInstance(r, pygame.Color)
115115
self.assertEqual(r, (10, 10, 10, 255))
116116

117+
s.set_at(pygame.Vector2(0, 0), (10, 10, 10, 255))
118+
r = s.get_at(pygame.Vector2(0, 0))
119+
self.assertIsInstance(r, pygame.Color)
120+
self.assertEqual(r, (10, 10, 10, 255))
121+
117122
# try setting a color with a single integer.
118123
s.fill((0, 0, 0, 255))
119124
s.set_at((10, 1), 0x0000FF)
@@ -1905,10 +1910,15 @@ def test_get_at(self):
19051910
surf.set_at((1, 1), c11)
19061911
c = surf.get_at((0, 0))
19071912
self.assertIsInstance(c, pygame.Color)
1913+
c = surf.get_at(pygame.Vector2(0, 0))
1914+
self.assertIsInstance(c, pygame.Color)
19081915
self.assertEqual(c, c00)
19091916
self.assertEqual(surf.get_at((0, 1)), c01)
19101917
self.assertEqual(surf.get_at((1, 0)), c10)
19111918
self.assertEqual(surf.get_at((1, 1)), c11)
1919+
self.assertEqual(surf.get_at(pygame.Vector2(0, 1)), c01)
1920+
self.assertEqual(surf.get_at(pygame.Vector2(1, 0)), c10)
1921+
self.assertEqual(surf.get_at(pygame.Vector2(1, 1)), c11)
19121922
for p in [(-1, 0), (0, -1), (2, 0), (0, 2)]:
19131923
self.assertRaises(IndexError, surf.get_at, p)
19141924

@@ -1923,6 +1933,12 @@ def test_get_at_mapped(self):
19231933
surf.map_rgb(color),
19241934
"%i != %i, bitsize: %i" % (pixel, surf.map_rgb(color), bitsize),
19251935
)
1936+
pixel = surf.get_at_mapped(pygame.Vector2(0, 0))
1937+
self.assertEqual(
1938+
pixel,
1939+
surf.map_rgb(color),
1940+
"%i != %i, bitsize: %i" % (pixel, surf.map_rgb(color), bitsize),
1941+
)
19261942

19271943
def test_get_bitsize(self):
19281944
pygame.display.init()

0 commit comments

Comments
 (0)