From 914e7639041154710bb2e3494f31fb2131ee8f19 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 16:13:53 +0200 Subject: [PATCH 01/13] EXAMPLE COMMIT --- buildconfig/Setup.Android.SDL2.in | 1 - buildconfig/Setup.Emscripten.SDL2.in | 1 - buildconfig/Setup.SDL2.in | 1 - buildconfig/stubs/gen_stubs.py | 4 +-- src_c/_pygame.h | 4 +-- src_c/geometry.c | 43 +++++++++++++++++++++++++--- src_c/include/_pygame.h | 27 ++++++++--------- src_c/meson.build | 9 ------ src_c/rect.c | 19 ++++++++---- src_c/rect_impl.h | 22 ++++++++++++++ src_c/static.c | 3 -- src_py/meson.build | 1 + src_py/rect.py | 1 + 13 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 src_py/rect.py diff --git a/buildconfig/Setup.Android.SDL2.in b/buildconfig/Setup.Android.SDL2.in index fc556ad024..ad9c7527f9 100644 --- a/buildconfig/Setup.Android.SDL2.in +++ b/buildconfig/Setup.Android.SDL2.in @@ -46,7 +46,6 @@ display src_c/display.c $(SDL) $(DEBUG) event src_c/event.c $(SDL) $(DEBUG) key src_c/key.c $(SDL) $(DEBUG) mouse src_c/mouse.c $(SDL) $(DEBUG) -rect src_c/rect.c src_c/pgcompat_rect.c $(SDL) $(DEBUG) rwobject src_c/rwobject.c $(SDL) $(DEBUG) surface src_c/simd_blitters_sse2.c src_c/simd_blitters_avx2.c src_c/surface.c src_c/alphablit.c src_c/surface_fill.c src_c/simd_surface_fill_avx2.c src_c/simd_surface_fill_sse2.c $(SDL) $(DEBUG) surflock src_c/surflock.c $(SDL) $(DEBUG) diff --git a/buildconfig/Setup.Emscripten.SDL2.in b/buildconfig/Setup.Emscripten.SDL2.in index 23b22f5766..34497162cb 100644 --- a/buildconfig/Setup.Emscripten.SDL2.in +++ b/buildconfig/Setup.Emscripten.SDL2.in @@ -59,7 +59,6 @@ pixelcopy src_c/void.c pixelarray src_c/void.c surface src_c/void.c surflock src_c/void.c -rect src_c/void.c rwobject src_c/void.c system src_c/void.c window src_c/void.c diff --git a/buildconfig/Setup.SDL2.in b/buildconfig/Setup.SDL2.in index 2fd66eeea3..a2a5263857 100644 --- a/buildconfig/Setup.SDL2.in +++ b/buildconfig/Setup.SDL2.in @@ -56,7 +56,6 @@ display src_c/display.c $(SDL) $(DEBUG) event src_c/event.c $(SDL) $(DEBUG) key src_c/key.c $(SDL) $(DEBUG) mouse src_c/mouse.c $(SDL) $(DEBUG) -rect src_c/rect.c src_c/pgcompat_rect.c $(SDL) $(DEBUG) rwobject src_c/rwobject.c $(SDL) $(DEBUG) surface src_c/simd_blitters_sse2.c src_c/simd_blitters_avx2.c src_c/surface.c src_c/alphablit.c src_c/surface_fill.c src_c/simd_surface_fill_avx2.c src_c/simd_surface_fill_sse2.c $(SDL) $(DEBUG) surflock src_c/surflock.c $(SDL) $(DEBUG) diff --git a/buildconfig/stubs/gen_stubs.py b/buildconfig/stubs/gen_stubs.py index 670db2f951..e6f718155d 100644 --- a/buildconfig/stubs/gen_stubs.py +++ b/buildconfig/stubs/gen_stubs.py @@ -55,7 +55,7 @@ # pygame classes that are autoimported into main namespace are kept in this dict PG_AUTOIMPORT_CLASSES = { - "rect": ["Rect", "FRect"], + #"rect": ["Rect", "FRect"], "surface": ["Surface", "SurfaceType"], "color": ["Color"], "pixelarray": ["PixelArray"], @@ -72,7 +72,7 @@ "window": ["Window"], "base": ["__version__"], # need an explicit import # uncomment below line if Circle is added to the base namespace later - # "geometry": ["Circle"], + "geometry": ["Circle", "Rect", "FRect"], } # pygame modules from which __init__.py does the equivalent of diff --git a/src_c/_pygame.h b/src_c/_pygame.h index aa13a70bb0..f4f2cec5df 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -523,7 +523,7 @@ typedef enum { * Remember to keep these constants up to date. */ -#define PYGAMEAPI_RECT_NUMSLOTS 10 +//#define PYGAMEAPI_RECT_NUMSLOTS 10 #define PYGAMEAPI_JOYSTICK_NUMSLOTS 3 #define PYGAMEAPI_DISPLAY_NUMSLOTS 2 #define PYGAMEAPI_SURFACE_NUMSLOTS 4 @@ -535,6 +535,6 @@ typedef enum { #define PYGAMEAPI_BASE_NUMSLOTS 29 #define PYGAMEAPI_EVENT_NUMSLOTS 10 #define PYGAMEAPI_WINDOW_NUMSLOTS 1 -#define PYGAMEAPI_GEOMETRY_NUMSLOTS 1 +#define PYGAMEAPI_GEOMETRY_NUMSLOTS 11 #endif /* _PYGAME_INTERNAL_H */ diff --git a/src_c/geometry.c b/src_c/geometry.c index 4ccb0ad22d..4dd47c696a 100644 --- a/src_c/geometry.c +++ b/src_c/geometry.c @@ -1,3 +1,4 @@ +#include "rect.c" #include "circle.c" #include "geometry_common.c" @@ -21,12 +22,11 @@ MODINIT_DEFINE(geometry) return NULL; } - import_pygame_rect(); - if (PyErr_Occurred()) { + if (PyType_Ready(&pgCircle_Type) < 0) { return NULL; } - if (PyType_Ready(&pgCircle_Type) < 0) { + if (PyType_Ready(&pgRect_Type) < 0 || PyType_Ready(&pgFRect_Type) < 0) { return NULL; } @@ -35,6 +35,31 @@ MODINIT_DEFINE(geometry) return NULL; } + Py_INCREF(&pgRect_Type); + if (PyModule_AddObject(module, "RectType", (PyObject *)&pgRect_Type)) { + Py_DECREF(&pgRect_Type); + Py_DECREF(module); + return NULL; + } + Py_INCREF(&pgRect_Type); + if (PyModule_AddObject(module, "Rect", (PyObject *)&pgRect_Type)) { + Py_DECREF(&pgRect_Type); + Py_DECREF(module); + return NULL; + } + Py_INCREF(&pgFRect_Type); + if (PyModule_AddObject(module, "FRectType", (PyObject *)&pgFRect_Type)) { + Py_DECREF(&pgFRect_Type); + Py_DECREF(module); + return NULL; + } + Py_INCREF(&pgFRect_Type); + if (PyModule_AddObject(module, "FRect", (PyObject *)&pgFRect_Type)) { + Py_DECREF(&pgFRect_Type); + Py_DECREF(module); + return NULL; + } + Py_INCREF(&pgCircle_Type); if (PyModule_AddObject(module, "Circle", (PyObject *)&pgCircle_Type)) { Py_DECREF(&pgCircle_Type); @@ -42,7 +67,17 @@ MODINIT_DEFINE(geometry) return NULL; } - c_api[0] = &pgCircle_Type; + c_api[0] = &pgRect_Type; + c_api[1] = pgRect_New; + c_api[2] = pgRect_New4; + c_api[3] = pgRect_FromObject; + c_api[4] = pgRect_Normalize; + c_api[5] = &pgFRect_Type; + c_api[6] = pgFRect_New; + c_api[7] = pgFRect_New4; + c_api[8] = pgFRect_FromObject; + c_api[9] = pgFRect_Normalize; + c_api[10] = &pgCircle_Type; apiobj = encapsulate_api(c_api, "geometry"); if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) { Py_XDECREF(apiobj); diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index 1477fe24cc..e3dd1bd154 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -202,37 +202,38 @@ typedef struct { PyObject *weakreflist; } pgFRectObject; + #define pgRect_AsRect(x) (((pgRectObject *)x)->r) #define pgFRect_AsRect(x) (((pgFRectObject *)x)->r) #ifndef PYGAMEAPI_RECT_INTERNAL -#define pgRect_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(rect, 0)) +#define pgRect_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(geometry, 0)) #define pgRect_Check(x) ((x)->ob_type == &pgRect_Type) -#define pgRect_New (*(PyObject * (*)(SDL_Rect *)) PYGAMEAPI_GET_SLOT(rect, 1)) +#define pgRect_New (*(PyObject * (*)(SDL_Rect *)) PYGAMEAPI_GET_SLOT(geometry, 1)) #define pgRect_New4 \ - (*(PyObject * (*)(int, int, int, int)) PYGAMEAPI_GET_SLOT(rect, 2)) + (*(PyObject * (*)(int, int, int, int)) PYGAMEAPI_GET_SLOT(geometry, 2)) #define pgRect_FromObject \ - (*(SDL_Rect * (*)(PyObject *, SDL_Rect *)) PYGAMEAPI_GET_SLOT(rect, 3)) + (*(SDL_Rect * (*)(PyObject *, SDL_Rect *)) PYGAMEAPI_GET_SLOT(geometry, 3)) -#define pgRect_Normalize (*(void (*)(SDL_Rect *))PYGAMEAPI_GET_SLOT(rect, 4)) +#define pgRect_Normalize (*(void (*)(SDL_Rect *))PYGAMEAPI_GET_SLOT(geometry, 4)) -#define pgFRect_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(rect, 5)) +#define pgFRect_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(geometry, 5)) #define pgFRect_Check(x) ((x)->ob_type == &pgFRect_Type) #define pgFRect_New \ - (*(PyObject * (*)(SDL_FRect *)) PYGAMEAPI_GET_SLOT(rect, 6)) + (*(PyObject * (*)(SDL_FRect *)) PYGAMEAPI_GET_SLOT(geometry, 6)) #define pgFRect_New4 \ - (*(PyObject * (*)(float, float, float, float)) PYGAMEAPI_GET_SLOT(rect, 7)) + (*(PyObject * (*)(float, float, float, float)) PYGAMEAPI_GET_SLOT(geometry, 7)) #define pgFRect_FromObject \ - (*(SDL_FRect * (*)(PyObject *, SDL_FRect *)) PYGAMEAPI_GET_SLOT(rect, 8)) + (*(SDL_FRect * (*)(PyObject *, SDL_FRect *)) PYGAMEAPI_GET_SLOT(geometry, 8)) -#define pgFRect_Normalize (*(void (*)(SDL_FRect *))PYGAMEAPI_GET_SLOT(rect, 9)) +#define pgFRect_Normalize (*(void (*)(SDL_FRect *))PYGAMEAPI_GET_SLOT(geometry, 9)) -#define import_pygame_rect() IMPORT_PYGAME_MODULE(rect) +#define import_pygame_rect() IMPORT_PYGAME_MODULE(geometry) #endif /* ~PYGAMEAPI_RECT_INTERNAL */ /* @@ -531,7 +532,7 @@ typedef struct { */ #ifdef PYGAME_H PYGAMEAPI_DEFINE_SLOTS(base); -PYGAMEAPI_DEFINE_SLOTS(rect); +//PYGAMEAPI_DEFINE_SLOTS(rect); PYGAMEAPI_DEFINE_SLOTS(joystick); PYGAMEAPI_DEFINE_SLOTS(display); PYGAMEAPI_DEFINE_SLOTS(surface); @@ -545,7 +546,7 @@ PYGAMEAPI_DEFINE_SLOTS(window); PYGAMEAPI_DEFINE_SLOTS(geometry); #else /* ~PYGAME_H */ PYGAMEAPI_EXTERN_SLOTS(base); -PYGAMEAPI_EXTERN_SLOTS(rect); +//PYGAMEAPI_EXTERN_SLOTS(rect); PYGAMEAPI_EXTERN_SLOTS(joystick); PYGAMEAPI_EXTERN_SLOTS(display); PYGAMEAPI_EXTERN_SLOTS(surface); diff --git a/src_c/meson.build b/src_c/meson.build index 8e8287c834..3cb09d2211 100644 --- a/src_c/meson.build +++ b/src_c/meson.build @@ -62,15 +62,6 @@ mouse = py.extension_module( subdir: pg, ) -rect = py.extension_module( - 'rect', - ['rect.c', 'pgcompat_rect.c'], - c_args: warnings_error, - dependencies: pg_base_deps, - install: true, - subdir: pg, -) - rwobject = py.extension_module( 'rwobject', 'rwobject.c', diff --git a/src_c/rect.c b/src_c/rect.c index b300c2f97f..bd52d53605 100644 --- a/src_c/rect.c +++ b/src_c/rect.c @@ -36,6 +36,8 @@ #include +#include "geometry_common.h" + static PyTypeObject pgRect_Type; static PyTypeObject pgFRect_Type; #define pgRect_Check(x) (PyObject_IsInstance(x, (PyObject *)&pgRect_Type)) @@ -69,6 +71,7 @@ four_floats_from_obj(PyObject *obj, float *val1, float *val2, float *val3, #define RectExport_unionallIp pg_rect_unionall_ip #define RectExport_collidepoint pg_rect_collidepoint #define RectExport_colliderect pg_rect_colliderect +#define RectExport_collidecircle pg_rect_collidecircle #define RectExport_collidelist pg_rect_collidelist #define RectExport_collidelistall pg_rect_collidelistall #define RectExport_RectFromObjectAndKeyFunc pgRect_FromObjectAndKeyFunc @@ -184,6 +187,7 @@ four_floats_from_obj(PyObject *obj, float *val1, float *val2, float *val3, #define RectExport_unionallIp pg_frect_unionall_ip #define RectExport_collidepoint pg_frect_collidepoint #define RectExport_colliderect pg_frect_colliderect +#define RectExport_collidecircle pg_frect_collidecircle #define RectExport_collidelist pg_frect_collidelist #define RectExport_collidelistall pg_frect_collidelistall #define RectExport_RectFromObjectAndKeyFunc pgFRect_FromObjectAndKeyFunc @@ -487,6 +491,8 @@ static struct PyMethodDef pg_rect_methods[] = { DOC_RECT_COLLIDEPOINT}, {"colliderect", (PyCFunction)pg_rect_colliderect, METH_FASTCALL, DOC_RECT_COLLIDERECT}, + {"collidecircle", (PyCFunction)pg_rect_collidecircle, METH_FASTCALL, + DOC_RECT_COLLIDERECT}, {"collidelist", (PyCFunction)pg_rect_collidelist, METH_O, DOC_RECT_COLLIDELIST}, {"collidelistall", (PyCFunction)pg_rect_collidelistall, METH_O, @@ -538,6 +544,8 @@ static struct PyMethodDef pg_frect_methods[] = { DOC_RECT_COLLIDEPOINT}, {"colliderect", (PyCFunction)pg_frect_colliderect, METH_FASTCALL, DOC_RECT_COLLIDERECT}, + {"collidecircle", (PyCFunction)pg_frect_collidecircle, METH_FASTCALL, + DOC_RECT_COLLIDERECT}, {"collidelist", (PyCFunction)pg_frect_collidelist, METH_O, DOC_RECT_COLLIDELIST}, {"collidelistall", (PyCFunction)pg_frect_collidelistall, METH_O, @@ -760,7 +768,7 @@ static PyTypeObject pgFRect_Type = { .tp_getset = pg_frect_getsets, .tp_init = (initproc)pg_frect_init, .tp_new = pg_frect_new}; -static PyMethodDef _pg_module_methods[] = {{NULL, NULL, 0, NULL}}; +/*static PyMethodDef _pg_module_methods[] = {{NULL, NULL, 0, NULL}}; static char _pg_module_doc[] = "Module for the rectangle object\n"; @@ -779,15 +787,15 @@ MODINIT_DEFINE(rect) NULL, NULL}; - /* import needed apis; Do this first so if there is an error + / import needed apis; Do this first so if there is an error the module is not loaded. - */ + / import_pygame_base(); if (PyErr_Occurred()) { return NULL; } - /* Create the module and add the functions */ + / Create the module and add the functions / if (PyType_Ready(&pgRect_Type) < 0 || PyType_Ready(&pgFRect_Type) < 0) { return NULL; } @@ -822,7 +830,7 @@ MODINIT_DEFINE(rect) return NULL; } - /* export the c api */ + /* export the c api/ c_api[0] = &pgRect_Type; c_api[1] = pgRect_New; c_api[2] = pgRect_New4; @@ -841,3 +849,4 @@ MODINIT_DEFINE(rect) } return module; } +*/ \ No newline at end of file diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index 0187f07768..21135f65c1 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -34,6 +34,8 @@ #include +#include "geometry_common.h" + // #region RectExport #ifndef RectExport_init #error RectExport_init needs to be defined @@ -95,6 +97,9 @@ #ifndef RectExport_colliderect #error RectExport_colliderect needs to be defined #endif +#ifndef RectExport_collidecircle +#error RectExport_collidecircle needs to be defined +#endif #ifndef RectExport_collidelist #error RectExport_collidelist needs to be defined #endif @@ -485,6 +490,9 @@ static PyObject * RectExport_colliderect(RectObject *self, PyObject *const *args, Py_ssize_t nargs); static PyObject * +RectExport_collidecircle(RectObject *self, PyObject *const *args, + Py_ssize_t nargs); +static PyObject * RectExport_collidelist(RectObject *self, PyObject *args); static PyObject * RectExport_collidelistall(RectObject *self, PyObject *args); @@ -1337,6 +1345,20 @@ RectExport_colliderect(RectObject *self, PyObject *const *args, return PyBool_FromLong(_pg_do_rects_intersect(&self->r, argrect)); } +static PyObject * +RectExport_collidecircle(RectObject *self, PyObject *const *args, + Py_ssize_t nargs) { + pgCircleBase circle; + InnerRect srect = self->r; + + if (!pgCircle_FromObjectFastcall(args, nargs, &circle)) { + return RAISE(PyExc_TypeError, "A CircleType object was expected"); + } + + return PyBool_FromLong( + pgCollision_RectCircle(srect.x, srect.y, srect.w, srect.h, &circle)); +} + #ifndef OPTIMIZED_COLLIDERECT_SETUP /* This macro is used to optimize the colliderect function. It calculates * the left, top, right and bottom values of the calling rect only once diff --git a/src_c/static.c b/src_c/static.c index b7e8d1ec66..5bd4a8033a 100644 --- a/src_c/static.c +++ b/src_c/static.c @@ -89,8 +89,6 @@ PyInit_constants(void); PyMODINIT_FUNC PyInit_version(void); PyMODINIT_FUNC -PyInit_rect(void); -PyMODINIT_FUNC PyInit_geometry(void); PyMODINIT_FUNC PyInit_surflock(void); @@ -287,7 +285,6 @@ PyInit_pygame_static() load_submodule("pygame", PyInit_system(), "system"); load_submodule("pygame", PyInit_key(), "key"); - load_submodule("pygame", PyInit_rect(), "rect"); load_submodule("pygame", PyInit_geometry(), "geometry"); load_submodule("pygame", PyInit_gfxdraw(), "gfxdraw"); load_submodule("pygame", PyInit_pg_time(), "time"); diff --git a/src_py/meson.build b/src_py/meson.build index 561aebaadb..6f303ac645 100644 --- a/src_py/meson.build +++ b/src_py/meson.build @@ -19,6 +19,7 @@ python_sources = files( 'surfarray.py', 'sysfont.py', 'version.py', + 'rect.py`, ) py.install_sources(python_sources, subdir: pg) diff --git a/src_py/rect.py b/src_py/rect.py new file mode 100644 index 0000000000..a1e72d40c0 --- /dev/null +++ b/src_py/rect.py @@ -0,0 +1 @@ +from pygame.geometry import Rect, FRect, RectType, FRectType \ No newline at end of file From 1976400b0a0c624fb3f6748170b3a158f7f04a42 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 16:42:10 +0200 Subject: [PATCH 02/13] polish changes --- buildconfig/stubs/gen_stubs.py | 5 +- buildconfig/stubs/pygame/geometry.pyi | 288 +++++++++++++++++++++++++- buildconfig/stubs/pygame/rect.pyi | 286 ------------------------- src_c/_pygame.h | 1 - src_c/include/_pygame.h | 36 ++-- src_c/rect_impl.h | 5 +- src_c/static.c | 1 - src_py/rect.py | 2 +- 8 files changed, 311 insertions(+), 313 deletions(-) delete mode 100644 buildconfig/stubs/pygame/rect.pyi diff --git a/buildconfig/stubs/gen_stubs.py b/buildconfig/stubs/gen_stubs.py index e6f718155d..101898e112 100644 --- a/buildconfig/stubs/gen_stubs.py +++ b/buildconfig/stubs/gen_stubs.py @@ -55,7 +55,6 @@ # pygame classes that are autoimported into main namespace are kept in this dict PG_AUTOIMPORT_CLASSES = { - #"rect": ["Rect", "FRect"], "surface": ["Surface", "SurfaceType"], "color": ["Color"], "pixelarray": ["PixelArray"], @@ -71,8 +70,8 @@ "joystick": ["Joystick"], "window": ["Window"], "base": ["__version__"], # need an explicit import - # uncomment below line if Circle is added to the base namespace later - "geometry": ["Circle", "Rect", "FRect"], + # Add "Circle" to the list if Circle is added to the base namespace later + "geometry": ["Rect", "FRect"], } # pygame modules from which __init__.py does the equivalent of diff --git a/buildconfig/stubs/pygame/geometry.pyi b/buildconfig/stubs/pygame/geometry.pyi index fb7c8de850..53f58de9f7 100644 --- a/buildconfig/stubs/pygame/geometry.pyi +++ b/buildconfig/stubs/pygame/geometry.pyi @@ -1,17 +1,37 @@ +import sys from typing import ( + Dict, + List, overload, Union, + Optional, Callable, Protocol, Tuple, + TypeVar, Sequence, ) -from pygame import Rect, FRect -from ._common import Coordinate, RectValue -from .rect import Rect, FRect +from ._common import Coordinate, Literal, RectValue, SupportsIndex, Sequence from .math import Vector2 +if sys.version_info >= (3, 11): + from typing import Self +else: + from typing_extensions import Self + +if sys.version_info >= (3, 9): + from collections.abc import Collection, Iterator +else: + from typing import Collection, Iterator + +_N = TypeVar("_N", int, float) +_K = TypeVar("_K") +_V = TypeVar("_V") +_T = TypeVar("_T") + +_RectTypeCompatible_co = TypeVar("_RectTypeCompatible_co", bound=RectValue, covariant=True) + _CanBeCircle = Union[Circle, Tuple[Coordinate, float], Sequence[float]] class _HasCirclettribute(Protocol): @@ -22,6 +42,268 @@ class _HasCirclettribute(Protocol): _CircleValue = Union[_CanBeCircle, _HasCirclettribute] _CanBeCollided = Union[Circle, Rect, FRect, Coordinate, Vector2] +class _GenericRect(Collection[_N]): + @property + def x(self) -> _N: ... + @x.setter + def x(self, value: float) -> None: ... + @property + def y(self) -> _N: ... + @y.setter + def y(self, value: float) -> None: ... + @property + def top(self) -> _N: ... + @top.setter + def top(self, value: float) -> None: ... + @property + def left(self) -> _N: ... + @left.setter + def left(self, value: float) -> None: ... + @property + def bottom(self) -> _N: ... + @bottom.setter + def bottom(self, value: float) -> None: ... + @property + def right(self) -> _N: ... + @right.setter + def right(self, value: float) -> None: ... + @property + def topleft(self) -> Tuple[_N, _N]: ... + @topleft.setter + def topleft(self, value: Coordinate) -> None: ... + @property + def bottomleft(self) -> Tuple[_N, _N]: ... + @bottomleft.setter + def bottomleft(self, value: Coordinate) -> None: ... + @property + def topright(self) -> Tuple[_N, _N]: ... + @topright.setter + def topright(self, value: Coordinate) -> None: ... + @property + def bottomright(self) -> Tuple[_N, _N]: ... + @bottomright.setter + def bottomright(self, value: Coordinate) -> None: ... + @property + def midtop(self) -> Tuple[_N, _N]: ... + @midtop.setter + def midtop(self, value: Coordinate) -> None: ... + @property + def midleft(self) -> Tuple[_N, _N]: ... + @midleft.setter + def midleft(self, value: Coordinate) -> None: ... + @property + def midbottom(self) -> Tuple[_N, _N]: ... + @midbottom.setter + def midbottom(self, value: Coordinate) -> None: ... + @property + def midright(self) -> Tuple[_N, _N]: ... + @midright.setter + def midright(self, value: Coordinate) -> None: ... + @property + def center(self) -> Tuple[_N, _N]: ... + @center.setter + def center(self, value: Coordinate) -> None: ... + @property + def centerx(self) -> _N: ... + @centerx.setter + def centerx(self, value: float) -> None: ... + @property + def centery(self) -> _N: ... + @centery.setter + def centery(self, value: float) -> None: ... + @property + def size(self) -> Tuple[_N, _N]: ... + @size.setter + def size(self, value: Coordinate) -> None: ... + @property + def width(self) -> _N: ... + @width.setter + def width(self, value: float) -> None: ... + @property + def height(self) -> _N: ... + @height.setter + def height(self, value: float) -> None: ... + @property + def w(self) -> _N: ... + @w.setter + def w(self, value: float) -> None: ... + @property + def h(self) -> _N: ... + @h.setter + def h(self, value: float) -> None: ... + __hash__: None # type: ignore + __safe_for_unpickling__: Literal[True] + @overload + def __init__( + self, left: float, top: float, width: float, height: float + ) -> None: ... + @overload + def __init__(self, left_top: Coordinate, width_height: Coordinate) -> None: ... + @overload + def __init__(self, single_arg: RectValue) -> None: ... + @overload + def __init__(self) -> None: ... + def __len__(self) -> Literal[4]: ... + def __iter__(self) -> Iterator[_N]: ... + @overload + def __getitem__(self, i: SupportsIndex) -> _N: ... + @overload + def __getitem__(self, s: slice) -> List[_N]: ... + @overload + def __setitem__(self, key: int, value: float) -> None: ... + @overload + def __setitem__(self, key: slice, value: Union[float, RectValue]) -> None: ... + def __copy__(self) -> Self: ... + copy = __copy__ + @overload + def move(self, x: float, y: float, /) -> Self: ... + @overload + def move(self, move_by: Coordinate, /) -> Self: ... + @overload + def move_ip(self, x: float, y: float, /) -> None: ... + @overload + def move_ip(self, move_by: Coordinate, /) -> None: ... + def move_to(self, **kwargs: Union[float, Coordinate]) -> Self: ... + @overload + def inflate(self, x: float, y: float, /) -> Self: ... + @overload + def inflate(self, inflate_by: Coordinate, /) -> Self: ... + @overload + def inflate_ip(self, x: float, y: float, /) -> None: ... + @overload + def inflate_ip(self, inflate_by: Coordinate, /) -> None: ... + @overload + def scale_by(self, x: float, y: float = ...) -> Self: ... + @overload + def scale_by(self, scale_by: Coordinate) -> Self: ... + @overload + def scale_by_ip(self, x: float, y: float = ...) -> None: ... + @overload + def scale_by_ip(self, scale_by: Coordinate) -> None: ... + @overload + def update(self, left: float, top: float, width: float, height: float, /) -> None: ... + @overload + def update(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... + @overload + def update(self, single_arg: RectValue, /) -> None: ... + @overload + def clamp(self, rect: RectValue, /) -> Self: ... + @overload + def clamp(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... + @overload + def clamp(self, left: float, top: float, width: float, height: float, /) -> Self: ... + @overload + def clamp_ip(self, rect: RectValue, /) -> None: ... + @overload + def clamp_ip(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... + @overload + def clamp_ip( + self, left: float, top: float, width: float, height: float, / + ) -> None: ... + @overload + def clip(self, rect: RectValue, /) -> Self: ... + @overload + def clip(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... + @overload + def clip(self, left: float, top: float, width: float, height: float, /) -> Self: ... + @overload + def clipline( + self, x1: float, x2: float, x3: float, x4: float, / + ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... + @overload + def clipline( + self, first_coordinate: Coordinate, second_coordinate: Coordinate, / + ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... + @overload + def clipline( + self, rect_arg: RectValue, / + ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... + @overload + def union(self, rect: RectValue, /) -> Self: ... + @overload + def union(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... + @overload + def union(self, left: float, top: float, width: float, height: float, /) -> Self: ... + @overload + def union_ip(self, rect: RectValue, /) -> None: ... + @overload + def union_ip(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... + @overload + def union_ip( + self, left: float, top: float, width: float, height: float, / + ) -> None: ... + def unionall(self, rect: Sequence[_RectTypeCompatible_co], /) -> Self: ... + def unionall_ip(self, rect_sequence: Sequence[_RectTypeCompatible_co], /) -> None: ... + @overload + def fit(self, rect: RectValue, /) -> Self: ... + @overload + def fit(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... + @overload + def fit(self, left: float, top: float, width: float, height: float, /) -> Self: ... + def normalize(self) -> None: ... + def __contains__(self, rect: Union[RectValue, _N], /) -> bool: ... # type: ignore[override] + @overload + def contains(self, rect: RectValue, /) -> bool: ... + @overload + def contains(self, left_top: Coordinate, width_height: Coordinate, /) -> bool: ... + @overload + def contains( + self, left: float, top: float, width: float, height: float, / + ) -> bool: ... + @overload + def collidepoint(self, x: float, y: float, /) -> bool: ... + @overload + def collidepoint(self, x_y: Coordinate, /) -> bool: ... + @overload + def colliderect(self, rect: RectValue, /) -> bool: ... + @overload + def colliderect(self, left_top: Coordinate, width_height: Coordinate, /) -> bool: ... + @overload + def colliderect( + self, left: float, top: float, width: float, height: float, / + ) -> bool: ... + @overload + def collidecircle(self, circle: _CircleValue, /) -> bool: ... + @overload + def collidecircle(self, pos: Coordinate, r: float, /) -> bool: ... + @overload + def collidecircle(self, x: float, y: float, r: float, /) -> bool: ... + def collidelist(self, rect_list: Sequence[_RectTypeCompatible_co], /) -> int: ... + def collidelistall(self, rect_list: Sequence[_RectTypeCompatible_co], /) -> List[int]: ... + def collideobjectsall( + self, objects: Sequence[_T], key: Optional[Callable[[_T], RectValue]] = None + ) -> List[_T]: ... + def collideobjects( + self, objects: Sequence[_T], key: Optional[Callable[[_T], RectValue]] = None + ) -> Optional[_T]: ... + @overload + def collidedict( + self, rect_dict: Dict[_RectTypeCompatible_co, _V], values: Literal[False] = False + ) -> Optional[Tuple[_RectTypeCompatible_co, _V]]: ... + @overload + def collidedict( + self, rect_dict: Dict[_K, _RectTypeCompatible_co], values: Literal[True] + ) -> Optional[Tuple[_K, _RectTypeCompatible_co]]: ... + @overload + def collidedictall( + self, rect_dict: Dict[_RectTypeCompatible_co, _V], values: Literal[False] = False + ) -> List[Tuple[_RectTypeCompatible_co, _V]]: ... + @overload + def collidedictall( + self, rect_dict: Dict[_K, _RectTypeCompatible_co], values: Literal[True] + ) -> List[Tuple[_K, _RectTypeCompatible_co]]: ... + +# Rect confirms to the Collection ABC, since it also confirms to +# Sized, Iterable and Container ABCs +class Rect(_GenericRect[int]): + ... + +class FRect(_GenericRect[float]): + ... + +RectType = Rect +FRectType = FRect + class Circle: @property def x(self) -> float: ... diff --git a/buildconfig/stubs/pygame/rect.pyi b/buildconfig/stubs/pygame/rect.pyi deleted file mode 100644 index b401f9a930..0000000000 --- a/buildconfig/stubs/pygame/rect.pyi +++ /dev/null @@ -1,286 +0,0 @@ -import sys -from typing import ( - Dict, - List, - Tuple, - TypeVar, - Union, - overload, - Callable, - Optional, -) - -from ._common import Coordinate, Literal, RectValue, SupportsIndex, Sequence - -if sys.version_info >= (3, 11): - from typing import Self -else: - from typing_extensions import Self - -if sys.version_info >= (3, 9): - from collections.abc import Collection, Iterator -else: - from typing import Collection, Iterator - -_N = TypeVar("_N", int, float) -_K = TypeVar("_K") -_V = TypeVar("_V") -_T = TypeVar("_T") - -_RectTypeCompatible_co = TypeVar("_RectTypeCompatible_co", bound=RectValue, covariant=True) - -class _GenericRect(Collection[_N]): - @property - def x(self) -> _N: ... - @x.setter - def x(self, value: float) -> None: ... - @property - def y(self) -> _N: ... - @y.setter - def y(self, value: float) -> None: ... - @property - def top(self) -> _N: ... - @top.setter - def top(self, value: float) -> None: ... - @property - def left(self) -> _N: ... - @left.setter - def left(self, value: float) -> None: ... - @property - def bottom(self) -> _N: ... - @bottom.setter - def bottom(self, value: float) -> None: ... - @property - def right(self) -> _N: ... - @right.setter - def right(self, value: float) -> None: ... - @property - def topleft(self) -> Tuple[_N, _N]: ... - @topleft.setter - def topleft(self, value: Coordinate) -> None: ... - @property - def bottomleft(self) -> Tuple[_N, _N]: ... - @bottomleft.setter - def bottomleft(self, value: Coordinate) -> None: ... - @property - def topright(self) -> Tuple[_N, _N]: ... - @topright.setter - def topright(self, value: Coordinate) -> None: ... - @property - def bottomright(self) -> Tuple[_N, _N]: ... - @bottomright.setter - def bottomright(self, value: Coordinate) -> None: ... - @property - def midtop(self) -> Tuple[_N, _N]: ... - @midtop.setter - def midtop(self, value: Coordinate) -> None: ... - @property - def midleft(self) -> Tuple[_N, _N]: ... - @midleft.setter - def midleft(self, value: Coordinate) -> None: ... - @property - def midbottom(self) -> Tuple[_N, _N]: ... - @midbottom.setter - def midbottom(self, value: Coordinate) -> None: ... - @property - def midright(self) -> Tuple[_N, _N]: ... - @midright.setter - def midright(self, value: Coordinate) -> None: ... - @property - def center(self) -> Tuple[_N, _N]: ... - @center.setter - def center(self, value: Coordinate) -> None: ... - @property - def centerx(self) -> _N: ... - @centerx.setter - def centerx(self, value: float) -> None: ... - @property - def centery(self) -> _N: ... - @centery.setter - def centery(self, value: float) -> None: ... - @property - def size(self) -> Tuple[_N, _N]: ... - @size.setter - def size(self, value: Coordinate) -> None: ... - @property - def width(self) -> _N: ... - @width.setter - def width(self, value: float) -> None: ... - @property - def height(self) -> _N: ... - @height.setter - def height(self, value: float) -> None: ... - @property - def w(self) -> _N: ... - @w.setter - def w(self, value: float) -> None: ... - @property - def h(self) -> _N: ... - @h.setter - def h(self, value: float) -> None: ... - __hash__: None # type: ignore - __safe_for_unpickling__: Literal[True] - @overload - def __init__( - self, left: float, top: float, width: float, height: float - ) -> None: ... - @overload - def __init__(self, left_top: Coordinate, width_height: Coordinate) -> None: ... - @overload - def __init__(self, single_arg: RectValue) -> None: ... - @overload - def __init__(self) -> None: ... - def __len__(self) -> Literal[4]: ... - def __iter__(self) -> Iterator[_N]: ... - @overload - def __getitem__(self, i: SupportsIndex) -> _N: ... - @overload - def __getitem__(self, s: slice) -> List[_N]: ... - @overload - def __setitem__(self, key: int, value: float) -> None: ... - @overload - def __setitem__(self, key: slice, value: Union[float, RectValue]) -> None: ... - def __copy__(self) -> Self: ... - copy = __copy__ - @overload - def move(self, x: float, y: float, /) -> Self: ... - @overload - def move(self, move_by: Coordinate, /) -> Self: ... - @overload - def move_ip(self, x: float, y: float, /) -> None: ... - @overload - def move_ip(self, move_by: Coordinate, /) -> None: ... - def move_to(self, **kwargs: Union[float, Coordinate]) -> Self: ... - @overload - def inflate(self, x: float, y: float, /) -> Self: ... - @overload - def inflate(self, inflate_by: Coordinate, /) -> Self: ... - @overload - def inflate_ip(self, x: float, y: float, /) -> None: ... - @overload - def inflate_ip(self, inflate_by: Coordinate, /) -> None: ... - @overload - def scale_by(self, x: float, y: float = ...) -> Self: ... - @overload - def scale_by(self, scale_by: Coordinate) -> Self: ... - @overload - def scale_by_ip(self, x: float, y: float = ...) -> None: ... - @overload - def scale_by_ip(self, scale_by: Coordinate) -> None: ... - @overload - def update(self, left: float, top: float, width: float, height: float, /) -> None: ... - @overload - def update(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... - @overload - def update(self, single_arg: RectValue, /) -> None: ... - @overload - def clamp(self, rect: RectValue, /) -> Self: ... - @overload - def clamp(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... - @overload - def clamp(self, left: float, top: float, width: float, height: float, /) -> Self: ... - @overload - def clamp_ip(self, rect: RectValue, /) -> None: ... - @overload - def clamp_ip(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... - @overload - def clamp_ip( - self, left: float, top: float, width: float, height: float, / - ) -> None: ... - @overload - def clip(self, rect: RectValue, /) -> Self: ... - @overload - def clip(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... - @overload - def clip(self, left: float, top: float, width: float, height: float, /) -> Self: ... - @overload - def clipline( - self, x1: float, x2: float, x3: float, x4: float, / - ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... - @overload - def clipline( - self, first_coordinate: Coordinate, second_coordinate: Coordinate, / - ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... - @overload - def clipline( - self, rect_arg: RectValue, / - ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... - @overload - def union(self, rect: RectValue, /) -> Self: ... - @overload - def union(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... - @overload - def union(self, left: float, top: float, width: float, height: float, /) -> Self: ... - @overload - def union_ip(self, rect: RectValue, /) -> None: ... - @overload - def union_ip(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... - @overload - def union_ip( - self, left: float, top: float, width: float, height: float, / - ) -> None: ... - def unionall(self, rect: Sequence[_RectTypeCompatible_co], /) -> Self: ... - def unionall_ip(self, rect_sequence: Sequence[_RectTypeCompatible_co], /) -> None: ... - @overload - def fit(self, rect: RectValue, /) -> Self: ... - @overload - def fit(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... - @overload - def fit(self, left: float, top: float, width: float, height: float, /) -> Self: ... - def normalize(self) -> None: ... - def __contains__(self, rect: Union[RectValue, _N], /) -> bool: ... # type: ignore[override] - @overload - def contains(self, rect: RectValue, /) -> bool: ... - @overload - def contains(self, left_top: Coordinate, width_height: Coordinate, /) -> bool: ... - @overload - def contains( - self, left: float, top: float, width: float, height: float, / - ) -> bool: ... - @overload - def collidepoint(self, x: float, y: float, /) -> bool: ... - @overload - def collidepoint(self, x_y: Coordinate, /) -> bool: ... - @overload - def colliderect(self, rect: RectValue, /) -> bool: ... - @overload - def colliderect(self, left_top: Coordinate, width_height: Coordinate, /) -> bool: ... - @overload - def colliderect( - self, left: float, top: float, width: float, height: float, / - ) -> bool: ... - def collidelist(self, rect_list: Sequence[_RectTypeCompatible_co], /) -> int: ... - def collidelistall(self, rect_list: Sequence[_RectTypeCompatible_co], /) -> List[int]: ... - def collideobjectsall( - self, objects: Sequence[_T], key: Optional[Callable[[_T], RectValue]] = None - ) -> List[_T]: ... - def collideobjects( - self, objects: Sequence[_T], key: Optional[Callable[[_T], RectValue]] = None - ) -> Optional[_T]: ... - @overload - def collidedict( - self, rect_dict: Dict[_RectTypeCompatible_co, _V], values: Literal[False] = False - ) -> Optional[Tuple[_RectTypeCompatible_co, _V]]: ... - @overload - def collidedict( - self, rect_dict: Dict[_K, _RectTypeCompatible_co], values: Literal[True] - ) -> Optional[Tuple[_K, _RectTypeCompatible_co]]: ... - @overload - def collidedictall( - self, rect_dict: Dict[_RectTypeCompatible_co, _V], values: Literal[False] = False - ) -> List[Tuple[_RectTypeCompatible_co, _V]]: ... - @overload - def collidedictall( - self, rect_dict: Dict[_K, _RectTypeCompatible_co], values: Literal[True] - ) -> List[Tuple[_K, _RectTypeCompatible_co]]: ... - -# Rect confirms to the Collection ABC, since it also confirms to -# Sized, Iterable and Container ABCs -class Rect(_GenericRect[int]): - ... - -class FRect(_GenericRect[float]): - ... - -RectType = Rect -FRectType = FRect diff --git a/src_c/_pygame.h b/src_c/_pygame.h index f4f2cec5df..4e8051e932 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -523,7 +523,6 @@ typedef enum { * Remember to keep these constants up to date. */ -//#define PYGAMEAPI_RECT_NUMSLOTS 10 #define PYGAMEAPI_JOYSTICK_NUMSLOTS 3 #define PYGAMEAPI_DISPLAY_NUMSLOTS 2 #define PYGAMEAPI_SURFACE_NUMSLOTS 4 diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index e3dd1bd154..32827dd2f6 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -192,6 +192,12 @@ typedef struct pg_bufferinfo_s { #define import_pygame_base() IMPORT_PYGAME_MODULE(base) #endif /* ~PYGAMEAPI_BASE_INTERNAL */ +#ifndef PYGAMEAPI_GEOMETRY_INTERNAL + +#define import_pygame_geometry() IMPORT_PYGAME_MODULE(geometry) + +#endif /* ~PYGAMEAPI_GEOMETRY_INTERNAL */ + typedef struct { PyObject_HEAD SDL_Rect r; PyObject *weakreflist; @@ -202,14 +208,16 @@ typedef struct { PyObject *weakreflist; } pgFRectObject; - #define pgRect_AsRect(x) (((pgRectObject *)x)->r) #define pgFRect_AsRect(x) (((pgFRectObject *)x)->r) + #ifndef PYGAMEAPI_RECT_INTERNAL + #define pgRect_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(geometry, 0)) #define pgRect_Check(x) ((x)->ob_type == &pgRect_Type) -#define pgRect_New (*(PyObject * (*)(SDL_Rect *)) PYGAMEAPI_GET_SLOT(geometry, 1)) +#define pgRect_New \ + (*(PyObject * (*)(SDL_Rect *)) PYGAMEAPI_GET_SLOT(geometry, 1)) #define pgRect_New4 \ (*(PyObject * (*)(int, int, int, int)) PYGAMEAPI_GET_SLOT(geometry, 2)) @@ -217,7 +225,8 @@ typedef struct { #define pgRect_FromObject \ (*(SDL_Rect * (*)(PyObject *, SDL_Rect *)) PYGAMEAPI_GET_SLOT(geometry, 3)) -#define pgRect_Normalize (*(void (*)(SDL_Rect *))PYGAMEAPI_GET_SLOT(geometry, 4)) +#define pgRect_Normalize \ + (*(void (*)(SDL_Rect *))PYGAMEAPI_GET_SLOT(geometry, 4)) #define pgFRect_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(geometry, 5)) @@ -225,13 +234,16 @@ typedef struct { #define pgFRect_New \ (*(PyObject * (*)(SDL_FRect *)) PYGAMEAPI_GET_SLOT(geometry, 6)) -#define pgFRect_New4 \ - (*(PyObject * (*)(float, float, float, float)) PYGAMEAPI_GET_SLOT(geometry, 7)) +#define pgFRect_New4 \ + (*(PyObject * (*)(float, float, float, float)) \ + PYGAMEAPI_GET_SLOT(geometry, 7)) -#define pgFRect_FromObject \ - (*(SDL_FRect * (*)(PyObject *, SDL_FRect *)) PYGAMEAPI_GET_SLOT(geometry, 8)) +#define pgFRect_FromObject \ + (*(SDL_FRect * (*)(PyObject *, SDL_FRect *)) \ + PYGAMEAPI_GET_SLOT(geometry, 8)) -#define pgFRect_Normalize (*(void (*)(SDL_FRect *))PYGAMEAPI_GET_SLOT(geometry, 9)) +#define pgFRect_Normalize \ + (*(void (*)(SDL_FRect *))PYGAMEAPI_GET_SLOT(geometry, 9)) #define import_pygame_rect() IMPORT_PYGAME_MODULE(geometry) #endif /* ~PYGAMEAPI_RECT_INTERNAL */ @@ -501,12 +513,6 @@ typedef struct pgColorObject pgColorObject; #define import_pygame_math() IMPORT_PYGAME_MODULE(math) #endif /* PYGAMEAPI_MATH_INTERNAL */ -#ifndef PYGAMEAPI_GEOMETRY_INTERNAL - -#define import_pygame_geometry() IMPORT_PYGAME_MODULE(geometry) - -#endif /* ~PYGAMEAPI_GEOMETRY_INTERNAL */ - /* * Window module */ @@ -532,7 +538,6 @@ typedef struct { */ #ifdef PYGAME_H PYGAMEAPI_DEFINE_SLOTS(base); -//PYGAMEAPI_DEFINE_SLOTS(rect); PYGAMEAPI_DEFINE_SLOTS(joystick); PYGAMEAPI_DEFINE_SLOTS(display); PYGAMEAPI_DEFINE_SLOTS(surface); @@ -546,7 +551,6 @@ PYGAMEAPI_DEFINE_SLOTS(window); PYGAMEAPI_DEFINE_SLOTS(geometry); #else /* ~PYGAME_H */ PYGAMEAPI_EXTERN_SLOTS(base); -//PYGAMEAPI_EXTERN_SLOTS(rect); PYGAMEAPI_EXTERN_SLOTS(joystick); PYGAMEAPI_EXTERN_SLOTS(display); PYGAMEAPI_EXTERN_SLOTS(surface); diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index 21135f65c1..4bc47725e3 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -491,7 +491,7 @@ RectExport_colliderect(RectObject *self, PyObject *const *args, Py_ssize_t nargs); static PyObject * RectExport_collidecircle(RectObject *self, PyObject *const *args, - Py_ssize_t nargs); + Py_ssize_t nargs); static PyObject * RectExport_collidelist(RectObject *self, PyObject *args); static PyObject * @@ -1347,7 +1347,8 @@ RectExport_colliderect(RectObject *self, PyObject *const *args, static PyObject * RectExport_collidecircle(RectObject *self, PyObject *const *args, - Py_ssize_t nargs) { + Py_ssize_t nargs) +{ pgCircleBase circle; InnerRect srect = self->r; diff --git a/src_c/static.c b/src_c/static.c index 5bd4a8033a..40fad13bc6 100644 --- a/src_c/static.c +++ b/src_c/static.c @@ -322,7 +322,6 @@ PyInit_pygame_static() #include "base.c" -#include "rect.c" #include "pgcompat_rect.c" #undef pgSurface_Lock diff --git a/src_py/rect.py b/src_py/rect.py index a1e72d40c0..2aa2f93181 100644 --- a/src_py/rect.py +++ b/src_py/rect.py @@ -1 +1 @@ -from pygame.geometry import Rect, FRect, RectType, FRectType \ No newline at end of file +from pygame.geometry import Rect, FRect, RectType, FRectType From c1280ad659831a48d5bd3d843d2d475fc0d28a64 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 17:15:55 +0200 Subject: [PATCH 03/13] Add docs and tests --- docs/reST/ref/rect.rst | 18 ++++++++++++ src_c/doc/rect_doc.h | 1 + src_c/rect.c | 4 +-- test/rect_test.py | 66 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 2 deletions(-) diff --git a/docs/reST/ref/rect.rst b/docs/reST/ref/rect.rst index 9066d045b1..b4f448e489 100644 --- a/docs/reST/ref/rect.rst +++ b/docs/reST/ref/rect.rst @@ -391,6 +391,24 @@ .. ## Rect.colliderect ## + .. method:: collidecircle + + | :sl:`checks if a circle intersects the rectangle` + | :sg:`collidecircle(Circle) -> bool` + | :sg:`collidecircle((x, y), r) -> bool` + | :sg:`collidecircle(x, y, r) -> bool` + + Returns `True` if any portion of the `Circle` overlaps with the rectangle, + `False` otherwise. + + .. note :: + For collision detection between a rect and a line the :meth:`clipline` + method can be used. + + .. versionadded:: 2.5.0 + + .. ## Rect.collidecircle ## + .. method:: collidelist | :sl:`test if one rectangle in a list intersects` diff --git a/src_c/doc/rect_doc.h b/src_c/doc/rect_doc.h index 934460fef6..463f86f819 100644 --- a/src_c/doc/rect_doc.h +++ b/src_c/doc/rect_doc.h @@ -22,6 +22,7 @@ #define DOC_RECT_CONTAINS "contains(rect, /) -> bool\ntest if one rectangle is inside another" #define DOC_RECT_COLLIDEPOINT "collidepoint(x, y, /) -> bool\ncollidepoint((x, y), /) -> bool\ntest if a point is inside a rectangle" #define DOC_RECT_COLLIDERECT "colliderect(rect, /) -> bool\ntest if two rectangles overlap" +#define DOC_RECT_COLLIDECIRCLE "collidecircle(Circle) -> bool\ncollidecircle((x, y), r) -> bool\ncollidecircle(x, y, r) -> bool\nchecks if a circle intersects the rectangle" #define DOC_RECT_COLLIDELIST "collidelist(list, /) -> index\ntest if one rectangle in a list intersects" #define DOC_RECT_COLLIDELISTALL "collidelistall(list, /) -> indices\ntest if all rectangles in a list intersect" #define DOC_RECT_COLLIDEOBJECTS "collideobjects(rect_list) -> object\ncollideobjects(obj_list, key=func) -> object\ntest if any object in a list intersects" diff --git a/src_c/rect.c b/src_c/rect.c index bd52d53605..78793b366f 100644 --- a/src_c/rect.c +++ b/src_c/rect.c @@ -492,7 +492,7 @@ static struct PyMethodDef pg_rect_methods[] = { {"colliderect", (PyCFunction)pg_rect_colliderect, METH_FASTCALL, DOC_RECT_COLLIDERECT}, {"collidecircle", (PyCFunction)pg_rect_collidecircle, METH_FASTCALL, - DOC_RECT_COLLIDERECT}, + DOC_RECT_COLLIDECIRCLE}, {"collidelist", (PyCFunction)pg_rect_collidelist, METH_O, DOC_RECT_COLLIDELIST}, {"collidelistall", (PyCFunction)pg_rect_collidelistall, METH_O, @@ -545,7 +545,7 @@ static struct PyMethodDef pg_frect_methods[] = { {"colliderect", (PyCFunction)pg_frect_colliderect, METH_FASTCALL, DOC_RECT_COLLIDERECT}, {"collidecircle", (PyCFunction)pg_frect_collidecircle, METH_FASTCALL, - DOC_RECT_COLLIDERECT}, + DOC_RECT_COLLIDECIRCLE}, {"collidelist", (PyCFunction)pg_frect_collidelist, METH_O, DOC_RECT_COLLIDELIST}, {"collidelistall", (PyCFunction)pg_frect_collidelistall, METH_O, diff --git a/test/rect_test.py b/test/rect_test.py index 307feb8b29..ff813880c1 100644 --- a/test/rect_test.py +++ b/test/rect_test.py @@ -3,6 +3,7 @@ from collections.abc import Collection, Sequence from pygame import Vector2, FRect, Rect as IRect +from pygame.geometry import Circle from pygame.tests import test_utils Rect = IRect @@ -1683,6 +1684,71 @@ def test_colliderect(self): "r1 collides with Rect(r1.right, r1.bottom, 1, 1)", ) + def test_collidecircle_argtype(self): + """tests if the function correctly handles incorrect types as parameters""" + invalid_types = (None, [], "1", (1,), Vector2(1, 1), 1) + + r = Rect(6, 6, 8, 8) + + for value in invalid_types: + with self.assertRaises(TypeError): + r.collidecircle(value) + + def test_collidecircle_argnum(self): + r = Rect(6, 6, 8, 8) + # no params + with self.assertRaises(TypeError): + r.collidecircle() + + with self.assertRaises(TypeError): + r.collidecircle(Circle(10, 10, 4), Circle(10, 10, 4)) + + def test_collidecircle(self): + r = Rect(-5, -5, 10, 10) + + c1 = Circle(10, 0, 5) + c2 = Circle(100, 100, 5) + c3 = Circle(10, 0, 4.999999999999) + c4 = Circle(0, 0, 2) + c5 = Circle(10, 0, 7) + c6 = Circle(0, 0, 5) + c7 = Circle(0, 0, 20) + + # touching + self.assertTrue( + r.collidecircle(c1), "Expected True, circle should collide here" + ) + + # partly colliding + self.assertTrue( + r.collidecircle(c5), "Expected True, circle should collide here" + ) + + # completely colliding + self.assertTrue( + r.collidecircle(c6), "Expected True, circle should collide here" + ) + + # not touching + self.assertFalse( + r.collidecircle(c2), "Expected False, circle should not collide here" + ) + + # barely not touching + self.assertFalse( + r.collidecircle(c3), "Expected False, circle should not collide here" + ) + + # small circle inside bigger rect + self.assertTrue( + r.collidecircle(c4), "Expected True, circle should collide here" + ) + + # big circle inside smaller rect + self.assertTrue( + r.collidecircle(c7), "Expected True, circle should collide here" + ) + def testEquals(self): """check to see how the rect uses __eq__""" r1 = Rect(1, 2, 3, 4) From 0d7fbd24d93fab6c926d2354b3ab3e29e4c2f91e Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 17:24:45 +0200 Subject: [PATCH 04/13] Add undef and remove comment --- src_c/rect.c | 83 ----------------------------------------------- src_c/rect_impl.h | 1 + 2 files changed, 1 insertion(+), 83 deletions(-) diff --git a/src_c/rect.c b/src_c/rect.c index 78793b366f..bb551ac6ff 100644 --- a/src_c/rect.c +++ b/src_c/rect.c @@ -767,86 +767,3 @@ static PyTypeObject pgFRect_Type = { .tp_iter = (getiterfunc)pg_frect_iterator, .tp_methods = pg_frect_methods, .tp_getset = pg_frect_getsets, .tp_init = (initproc)pg_frect_init, .tp_new = pg_frect_new}; - -/*static PyMethodDef _pg_module_methods[] = {{NULL, NULL, 0, NULL}}; - -static char _pg_module_doc[] = "Module for the rectangle object\n"; - -MODINIT_DEFINE(rect) -{ - PyObject *module, *apiobj; - static void *c_api[PYGAMEAPI_RECT_NUMSLOTS]; - - static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT, - "rect", - _pg_module_doc, - -1, - _pg_module_methods, - NULL, - NULL, - NULL, - NULL}; - - / import needed apis; Do this first so if there is an error - the module is not loaded. - / - import_pygame_base(); - if (PyErr_Occurred()) { - return NULL; - } - - / Create the module and add the functions / - if (PyType_Ready(&pgRect_Type) < 0 || PyType_Ready(&pgFRect_Type) < 0) { - return NULL; - } - - module = PyModule_Create(&_module); - if (module == NULL) { - return NULL; - } - - Py_INCREF(&pgRect_Type); - if (PyModule_AddObject(module, "RectType", (PyObject *)&pgRect_Type)) { - Py_DECREF(&pgRect_Type); - Py_DECREF(module); - return NULL; - } - Py_INCREF(&pgRect_Type); - if (PyModule_AddObject(module, "Rect", (PyObject *)&pgRect_Type)) { - Py_DECREF(&pgRect_Type); - Py_DECREF(module); - return NULL; - } - Py_INCREF(&pgFRect_Type); - if (PyModule_AddObject(module, "FRectType", (PyObject *)&pgFRect_Type)) { - Py_DECREF(&pgFRect_Type); - Py_DECREF(module); - return NULL; - } - Py_INCREF(&pgFRect_Type); - if (PyModule_AddObject(module, "FRect", (PyObject *)&pgFRect_Type)) { - Py_DECREF(&pgFRect_Type); - Py_DECREF(module); - return NULL; - } - - /* export the c api/ - c_api[0] = &pgRect_Type; - c_api[1] = pgRect_New; - c_api[2] = pgRect_New4; - c_api[3] = pgRect_FromObject; - c_api[4] = pgRect_Normalize; - c_api[5] = &pgFRect_Type; - c_api[6] = pgFRect_New; - c_api[7] = pgFRect_New4; - c_api[8] = pgFRect_FromObject; - c_api[9] = pgFRect_Normalize; - apiobj = encapsulate_api(c_api, "rect"); - if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) { - Py_XDECREF(apiobj); - Py_DECREF(module); - return NULL; - } - return module; -} -*/ \ No newline at end of file diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index 4bc47725e3..8b45ece781 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -2881,6 +2881,7 @@ RectExport_iterator(RectObject *self) #undef RectExport_unionallIp #undef RectExport_collidepoint #undef RectExport_colliderect +#undef RectExport_collidecircle #undef RectExport_collidelist #undef RectExport_collidelistall #undef RectExport_collidedict From d2bae76cf990a04fe621fc1c38085e6449f819d7 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 18:53:49 +0200 Subject: [PATCH 05/13] Fix meson build --- src_py/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_py/meson.build b/src_py/meson.build index 6f303ac645..c37b4c41de 100644 --- a/src_py/meson.build +++ b/src_py/meson.build @@ -19,7 +19,7 @@ python_sources = files( 'surfarray.py', 'sysfont.py', 'version.py', - 'rect.py`, + 'rect.py', ) py.install_sources(python_sources, subdir: pg) From d86cb276f729ab218f52233c656eef8441aa75f3 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 18:55:22 +0200 Subject: [PATCH 06/13] Try fix static.c --- src_c/static.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_c/static.c b/src_c/static.c index 40fad13bc6..aa52c34ee0 100644 --- a/src_c/static.c +++ b/src_c/static.c @@ -276,6 +276,7 @@ PyInit_pygame_static() SDL_SetHint("SDL_EMSCRIPTEN_KEYBOARD_ELEMENT", "1"); load_submodule("pygame", PyInit_base(), "base"); + load_submodule("pygame", PyInit_geometry(), "geometry"); load_submodule("pygame", PyInit_constants(), "constants"); load_submodule("pygame", PyInit_surflock(), "surflock"); load_submodule("pygame", PyInit_rwobject(), "rwobject"); @@ -285,7 +286,6 @@ PyInit_pygame_static() load_submodule("pygame", PyInit_system(), "system"); load_submodule("pygame", PyInit_key(), "key"); - load_submodule("pygame", PyInit_geometry(), "geometry"); load_submodule("pygame", PyInit_gfxdraw(), "gfxdraw"); load_submodule("pygame", PyInit_pg_time(), "time"); load_submodule("pygame", PyInit__freetype(), "_freetype"); @@ -323,6 +323,7 @@ PyInit_pygame_static() #include "base.c" #include "pgcompat_rect.c" +#include "geometry.c" #undef pgSurface_Lock #undef pgSurface_Unlock @@ -398,7 +399,6 @@ PyInit_pygame_static() #include "time.c" #include "system.c" -#include "geometry.c" #include "_freetype.c" #include "freetype/ft_wrap.c" From b137ddf8b684028aae6e0cb0457ea60cb13f03b2 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 18:58:55 +0200 Subject: [PATCH 07/13] Try fix static.c 2 --- src_c/static.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_c/static.c b/src_c/static.c index aa52c34ee0..e6b94a0ac0 100644 --- a/src_c/static.c +++ b/src_c/static.c @@ -322,8 +322,8 @@ PyInit_pygame_static() #include "base.c" -#include "pgcompat_rect.c" #include "geometry.c" +#include "pgcompat_rect.c" #undef pgSurface_Lock #undef pgSurface_Unlock From 98412a92df0b0d9d80354c52772fac5e40872be3 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 19:02:59 +0200 Subject: [PATCH 08/13] Try fix static.c 3 --- src_c/geometry.c | 1 + src_c/static.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src_c/geometry.c b/src_c/geometry.c index 4dd47c696a..f2674129c0 100644 --- a/src_c/geometry.c +++ b/src_c/geometry.c @@ -1,3 +1,4 @@ +#include "pgcompat_rect.c" #include "rect.c" #include "circle.c" #include "geometry_common.c" diff --git a/src_c/static.c b/src_c/static.c index e6b94a0ac0..6116428ad0 100644 --- a/src_c/static.c +++ b/src_c/static.c @@ -323,7 +323,6 @@ PyInit_pygame_static() #include "base.c" #include "geometry.c" -#include "pgcompat_rect.c" #undef pgSurface_Lock #undef pgSurface_Unlock From 6d1250a9c46dd0c31073aad48f1ac2af9a240354 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 19:07:06 +0200 Subject: [PATCH 09/13] Fix stubs --- buildconfig/stubs/pygame/geometry.pyi | 1 - 1 file changed, 1 deletion(-) diff --git a/buildconfig/stubs/pygame/geometry.pyi b/buildconfig/stubs/pygame/geometry.pyi index 53f58de9f7..7695cb2d3a 100644 --- a/buildconfig/stubs/pygame/geometry.pyi +++ b/buildconfig/stubs/pygame/geometry.pyi @@ -9,7 +9,6 @@ from typing import ( Protocol, Tuple, TypeVar, - Sequence, ) from ._common import Coordinate, Literal, RectValue, SupportsIndex, Sequence From 6534ffbdf491ce9a192212566972e6051875f2e9 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Wed, 29 May 2024 23:19:39 +0200 Subject: [PATCH 10/13] Move stubs back --- buildconfig/stubs/pygame/geometry.pyi | 297 ++------------------------ buildconfig/stubs/pygame/rect.pyi | 293 +++++++++++++++++++++++++ 2 files changed, 306 insertions(+), 284 deletions(-) create mode 100644 buildconfig/stubs/pygame/rect.pyi diff --git a/buildconfig/stubs/pygame/geometry.pyi b/buildconfig/stubs/pygame/geometry.pyi index 7695cb2d3a..34e5d5c132 100644 --- a/buildconfig/stubs/pygame/geometry.pyi +++ b/buildconfig/stubs/pygame/geometry.pyi @@ -1,35 +1,25 @@ -import sys + from typing import ( - Dict, - List, overload, Union, - Optional, Callable, Protocol, Tuple, - TypeVar, + Sequence, ) -from ._common import Coordinate, Literal, RectValue, SupportsIndex, Sequence +from ._common import Coordinate, RectValue +from .rect import Rect as Rect_, FRect as FRect_ from .math import Vector2 -if sys.version_info >= (3, 11): - from typing import Self -else: - from typing_extensions import Self - -if sys.version_info >= (3, 9): - from collections.abc import Collection, Iterator -else: - from typing import Collection, Iterator - -_N = TypeVar("_N", int, float) -_K = TypeVar("_K") -_V = TypeVar("_V") -_T = TypeVar("_T") - -_RectTypeCompatible_co = TypeVar("_RectTypeCompatible_co", bound=RectValue, covariant=True) +class Rect(Rect_): + ... + +class FRect(FRect_): + ... + +RectType = Rect +FRectType = FRect _CanBeCircle = Union[Circle, Tuple[Coordinate, float], Sequence[float]] @@ -41,268 +31,6 @@ class _HasCirclettribute(Protocol): _CircleValue = Union[_CanBeCircle, _HasCirclettribute] _CanBeCollided = Union[Circle, Rect, FRect, Coordinate, Vector2] -class _GenericRect(Collection[_N]): - @property - def x(self) -> _N: ... - @x.setter - def x(self, value: float) -> None: ... - @property - def y(self) -> _N: ... - @y.setter - def y(self, value: float) -> None: ... - @property - def top(self) -> _N: ... - @top.setter - def top(self, value: float) -> None: ... - @property - def left(self) -> _N: ... - @left.setter - def left(self, value: float) -> None: ... - @property - def bottom(self) -> _N: ... - @bottom.setter - def bottom(self, value: float) -> None: ... - @property - def right(self) -> _N: ... - @right.setter - def right(self, value: float) -> None: ... - @property - def topleft(self) -> Tuple[_N, _N]: ... - @topleft.setter - def topleft(self, value: Coordinate) -> None: ... - @property - def bottomleft(self) -> Tuple[_N, _N]: ... - @bottomleft.setter - def bottomleft(self, value: Coordinate) -> None: ... - @property - def topright(self) -> Tuple[_N, _N]: ... - @topright.setter - def topright(self, value: Coordinate) -> None: ... - @property - def bottomright(self) -> Tuple[_N, _N]: ... - @bottomright.setter - def bottomright(self, value: Coordinate) -> None: ... - @property - def midtop(self) -> Tuple[_N, _N]: ... - @midtop.setter - def midtop(self, value: Coordinate) -> None: ... - @property - def midleft(self) -> Tuple[_N, _N]: ... - @midleft.setter - def midleft(self, value: Coordinate) -> None: ... - @property - def midbottom(self) -> Tuple[_N, _N]: ... - @midbottom.setter - def midbottom(self, value: Coordinate) -> None: ... - @property - def midright(self) -> Tuple[_N, _N]: ... - @midright.setter - def midright(self, value: Coordinate) -> None: ... - @property - def center(self) -> Tuple[_N, _N]: ... - @center.setter - def center(self, value: Coordinate) -> None: ... - @property - def centerx(self) -> _N: ... - @centerx.setter - def centerx(self, value: float) -> None: ... - @property - def centery(self) -> _N: ... - @centery.setter - def centery(self, value: float) -> None: ... - @property - def size(self) -> Tuple[_N, _N]: ... - @size.setter - def size(self, value: Coordinate) -> None: ... - @property - def width(self) -> _N: ... - @width.setter - def width(self, value: float) -> None: ... - @property - def height(self) -> _N: ... - @height.setter - def height(self, value: float) -> None: ... - @property - def w(self) -> _N: ... - @w.setter - def w(self, value: float) -> None: ... - @property - def h(self) -> _N: ... - @h.setter - def h(self, value: float) -> None: ... - __hash__: None # type: ignore - __safe_for_unpickling__: Literal[True] - @overload - def __init__( - self, left: float, top: float, width: float, height: float - ) -> None: ... - @overload - def __init__(self, left_top: Coordinate, width_height: Coordinate) -> None: ... - @overload - def __init__(self, single_arg: RectValue) -> None: ... - @overload - def __init__(self) -> None: ... - def __len__(self) -> Literal[4]: ... - def __iter__(self) -> Iterator[_N]: ... - @overload - def __getitem__(self, i: SupportsIndex) -> _N: ... - @overload - def __getitem__(self, s: slice) -> List[_N]: ... - @overload - def __setitem__(self, key: int, value: float) -> None: ... - @overload - def __setitem__(self, key: slice, value: Union[float, RectValue]) -> None: ... - def __copy__(self) -> Self: ... - copy = __copy__ - @overload - def move(self, x: float, y: float, /) -> Self: ... - @overload - def move(self, move_by: Coordinate, /) -> Self: ... - @overload - def move_ip(self, x: float, y: float, /) -> None: ... - @overload - def move_ip(self, move_by: Coordinate, /) -> None: ... - def move_to(self, **kwargs: Union[float, Coordinate]) -> Self: ... - @overload - def inflate(self, x: float, y: float, /) -> Self: ... - @overload - def inflate(self, inflate_by: Coordinate, /) -> Self: ... - @overload - def inflate_ip(self, x: float, y: float, /) -> None: ... - @overload - def inflate_ip(self, inflate_by: Coordinate, /) -> None: ... - @overload - def scale_by(self, x: float, y: float = ...) -> Self: ... - @overload - def scale_by(self, scale_by: Coordinate) -> Self: ... - @overload - def scale_by_ip(self, x: float, y: float = ...) -> None: ... - @overload - def scale_by_ip(self, scale_by: Coordinate) -> None: ... - @overload - def update(self, left: float, top: float, width: float, height: float, /) -> None: ... - @overload - def update(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... - @overload - def update(self, single_arg: RectValue, /) -> None: ... - @overload - def clamp(self, rect: RectValue, /) -> Self: ... - @overload - def clamp(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... - @overload - def clamp(self, left: float, top: float, width: float, height: float, /) -> Self: ... - @overload - def clamp_ip(self, rect: RectValue, /) -> None: ... - @overload - def clamp_ip(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... - @overload - def clamp_ip( - self, left: float, top: float, width: float, height: float, / - ) -> None: ... - @overload - def clip(self, rect: RectValue, /) -> Self: ... - @overload - def clip(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... - @overload - def clip(self, left: float, top: float, width: float, height: float, /) -> Self: ... - @overload - def clipline( - self, x1: float, x2: float, x3: float, x4: float, / - ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... - @overload - def clipline( - self, first_coordinate: Coordinate, second_coordinate: Coordinate, / - ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... - @overload - def clipline( - self, rect_arg: RectValue, / - ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... - @overload - def union(self, rect: RectValue, /) -> Self: ... - @overload - def union(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... - @overload - def union(self, left: float, top: float, width: float, height: float, /) -> Self: ... - @overload - def union_ip(self, rect: RectValue, /) -> None: ... - @overload - def union_ip(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... - @overload - def union_ip( - self, left: float, top: float, width: float, height: float, / - ) -> None: ... - def unionall(self, rect: Sequence[_RectTypeCompatible_co], /) -> Self: ... - def unionall_ip(self, rect_sequence: Sequence[_RectTypeCompatible_co], /) -> None: ... - @overload - def fit(self, rect: RectValue, /) -> Self: ... - @overload - def fit(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... - @overload - def fit(self, left: float, top: float, width: float, height: float, /) -> Self: ... - def normalize(self) -> None: ... - def __contains__(self, rect: Union[RectValue, _N], /) -> bool: ... # type: ignore[override] - @overload - def contains(self, rect: RectValue, /) -> bool: ... - @overload - def contains(self, left_top: Coordinate, width_height: Coordinate, /) -> bool: ... - @overload - def contains( - self, left: float, top: float, width: float, height: float, / - ) -> bool: ... - @overload - def collidepoint(self, x: float, y: float, /) -> bool: ... - @overload - def collidepoint(self, x_y: Coordinate, /) -> bool: ... - @overload - def colliderect(self, rect: RectValue, /) -> bool: ... - @overload - def colliderect(self, left_top: Coordinate, width_height: Coordinate, /) -> bool: ... - @overload - def colliderect( - self, left: float, top: float, width: float, height: float, / - ) -> bool: ... - @overload - def collidecircle(self, circle: _CircleValue, /) -> bool: ... - @overload - def collidecircle(self, pos: Coordinate, r: float, /) -> bool: ... - @overload - def collidecircle(self, x: float, y: float, r: float, /) -> bool: ... - def collidelist(self, rect_list: Sequence[_RectTypeCompatible_co], /) -> int: ... - def collidelistall(self, rect_list: Sequence[_RectTypeCompatible_co], /) -> List[int]: ... - def collideobjectsall( - self, objects: Sequence[_T], key: Optional[Callable[[_T], RectValue]] = None - ) -> List[_T]: ... - def collideobjects( - self, objects: Sequence[_T], key: Optional[Callable[[_T], RectValue]] = None - ) -> Optional[_T]: ... - @overload - def collidedict( - self, rect_dict: Dict[_RectTypeCompatible_co, _V], values: Literal[False] = False - ) -> Optional[Tuple[_RectTypeCompatible_co, _V]]: ... - @overload - def collidedict( - self, rect_dict: Dict[_K, _RectTypeCompatible_co], values: Literal[True] - ) -> Optional[Tuple[_K, _RectTypeCompatible_co]]: ... - @overload - def collidedictall( - self, rect_dict: Dict[_RectTypeCompatible_co, _V], values: Literal[False] = False - ) -> List[Tuple[_RectTypeCompatible_co, _V]]: ... - @overload - def collidedictall( - self, rect_dict: Dict[_K, _RectTypeCompatible_co], values: Literal[True] - ) -> List[Tuple[_K, _RectTypeCompatible_co]]: ... - -# Rect confirms to the Collection ABC, since it also confirms to -# Sized, Iterable and Container ABCs -class Rect(_GenericRect[int]): - ... - -class FRect(_GenericRect[float]): - ... - -RectType = Rect -FRectType = FRect - class Circle: @property def x(self) -> float: ... @@ -394,3 +122,4 @@ class Circle: def as_frect(self) -> FRect: ... def __copy__(self) -> Circle: ... copy = __copy__ + \ No newline at end of file diff --git a/buildconfig/stubs/pygame/rect.pyi b/buildconfig/stubs/pygame/rect.pyi new file mode 100644 index 0000000000..4b15fd3d40 --- /dev/null +++ b/buildconfig/stubs/pygame/rect.pyi @@ -0,0 +1,293 @@ +import sys +from typing import ( + Dict, + List, + Tuple, + TypeVar, + Union, + overload, + Callable, + Optional, +) + +from ._common import Coordinate, Literal, RectValue, SupportsIndex, Sequence +from .geometry import _CircleValue + +if sys.version_info >= (3, 11): + from typing import Self +else: + from typing_extensions import Self + +if sys.version_info >= (3, 9): + from collections.abc import Collection, Iterator +else: + from typing import Collection, Iterator + +_N = TypeVar("_N", int, float) +_K = TypeVar("_K") +_V = TypeVar("_V") +_T = TypeVar("_T") + +_RectTypeCompatible_co = TypeVar("_RectTypeCompatible_co", bound=RectValue, covariant=True) + +class _GenericRect(Collection[_N]): + @property + def x(self) -> _N: ... + @x.setter + def x(self, value: float) -> None: ... + @property + def y(self) -> _N: ... + @y.setter + def y(self, value: float) -> None: ... + @property + def top(self) -> _N: ... + @top.setter + def top(self, value: float) -> None: ... + @property + def left(self) -> _N: ... + @left.setter + def left(self, value: float) -> None: ... + @property + def bottom(self) -> _N: ... + @bottom.setter + def bottom(self, value: float) -> None: ... + @property + def right(self) -> _N: ... + @right.setter + def right(self, value: float) -> None: ... + @property + def topleft(self) -> Tuple[_N, _N]: ... + @topleft.setter + def topleft(self, value: Coordinate) -> None: ... + @property + def bottomleft(self) -> Tuple[_N, _N]: ... + @bottomleft.setter + def bottomleft(self, value: Coordinate) -> None: ... + @property + def topright(self) -> Tuple[_N, _N]: ... + @topright.setter + def topright(self, value: Coordinate) -> None: ... + @property + def bottomright(self) -> Tuple[_N, _N]: ... + @bottomright.setter + def bottomright(self, value: Coordinate) -> None: ... + @property + def midtop(self) -> Tuple[_N, _N]: ... + @midtop.setter + def midtop(self, value: Coordinate) -> None: ... + @property + def midleft(self) -> Tuple[_N, _N]: ... + @midleft.setter + def midleft(self, value: Coordinate) -> None: ... + @property + def midbottom(self) -> Tuple[_N, _N]: ... + @midbottom.setter + def midbottom(self, value: Coordinate) -> None: ... + @property + def midright(self) -> Tuple[_N, _N]: ... + @midright.setter + def midright(self, value: Coordinate) -> None: ... + @property + def center(self) -> Tuple[_N, _N]: ... + @center.setter + def center(self, value: Coordinate) -> None: ... + @property + def centerx(self) -> _N: ... + @centerx.setter + def centerx(self, value: float) -> None: ... + @property + def centery(self) -> _N: ... + @centery.setter + def centery(self, value: float) -> None: ... + @property + def size(self) -> Tuple[_N, _N]: ... + @size.setter + def size(self, value: Coordinate) -> None: ... + @property + def width(self) -> _N: ... + @width.setter + def width(self, value: float) -> None: ... + @property + def height(self) -> _N: ... + @height.setter + def height(self, value: float) -> None: ... + @property + def w(self) -> _N: ... + @w.setter + def w(self, value: float) -> None: ... + @property + def h(self) -> _N: ... + @h.setter + def h(self, value: float) -> None: ... + __hash__: None # type: ignore + __safe_for_unpickling__: Literal[True] + @overload + def __init__( + self, left: float, top: float, width: float, height: float + ) -> None: ... + @overload + def __init__(self, left_top: Coordinate, width_height: Coordinate) -> None: ... + @overload + def __init__(self, single_arg: RectValue) -> None: ... + @overload + def __init__(self) -> None: ... + def __len__(self) -> Literal[4]: ... + def __iter__(self) -> Iterator[_N]: ... + @overload + def __getitem__(self, i: SupportsIndex) -> _N: ... + @overload + def __getitem__(self, s: slice) -> List[_N]: ... + @overload + def __setitem__(self, key: int, value: float) -> None: ... + @overload + def __setitem__(self, key: slice, value: Union[float, RectValue]) -> None: ... + def __copy__(self) -> Self: ... + copy = __copy__ + @overload + def move(self, x: float, y: float, /) -> Self: ... + @overload + def move(self, move_by: Coordinate, /) -> Self: ... + @overload + def move_ip(self, x: float, y: float, /) -> None: ... + @overload + def move_ip(self, move_by: Coordinate, /) -> None: ... + def move_to(self, **kwargs: Union[float, Coordinate]) -> Self: ... + @overload + def inflate(self, x: float, y: float, /) -> Self: ... + @overload + def inflate(self, inflate_by: Coordinate, /) -> Self: ... + @overload + def inflate_ip(self, x: float, y: float, /) -> None: ... + @overload + def inflate_ip(self, inflate_by: Coordinate, /) -> None: ... + @overload + def scale_by(self, x: float, y: float = ...) -> Self: ... + @overload + def scale_by(self, scale_by: Coordinate) -> Self: ... + @overload + def scale_by_ip(self, x: float, y: float = ...) -> None: ... + @overload + def scale_by_ip(self, scale_by: Coordinate) -> None: ... + @overload + def update(self, left: float, top: float, width: float, height: float, /) -> None: ... + @overload + def update(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... + @overload + def update(self, single_arg: RectValue, /) -> None: ... + @overload + def clamp(self, rect: RectValue, /) -> Self: ... + @overload + def clamp(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... + @overload + def clamp(self, left: float, top: float, width: float, height: float, /) -> Self: ... + @overload + def clamp_ip(self, rect: RectValue, /) -> None: ... + @overload + def clamp_ip(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... + @overload + def clamp_ip( + self, left: float, top: float, width: float, height: float, / + ) -> None: ... + @overload + def clip(self, rect: RectValue, /) -> Self: ... + @overload + def clip(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... + @overload + def clip(self, left: float, top: float, width: float, height: float, /) -> Self: ... + @overload + def clipline( + self, x1: float, x2: float, x3: float, x4: float, / + ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... + @overload + def clipline( + self, first_coordinate: Coordinate, second_coordinate: Coordinate, / + ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... + @overload + def clipline( + self, rect_arg: RectValue, / + ) -> Union[Tuple[Tuple[_N, _N], Tuple[_N, _N]], Tuple[()]]: ... + @overload + def union(self, rect: RectValue, /) -> Self: ... + @overload + def union(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... + @overload + def union(self, left: float, top: float, width: float, height: float, /) -> Self: ... + @overload + def union_ip(self, rect: RectValue, /) -> None: ... + @overload + def union_ip(self, left_top: Coordinate, width_height: Coordinate, /) -> None: ... + @overload + def union_ip( + self, left: float, top: float, width: float, height: float, / + ) -> None: ... + def unionall(self, rect: Sequence[_RectTypeCompatible_co], /) -> Self: ... + def unionall_ip(self, rect_sequence: Sequence[_RectTypeCompatible_co], /) -> None: ... + @overload + def fit(self, rect: RectValue, /) -> Self: ... + @overload + def fit(self, left_top: Coordinate, width_height: Coordinate, /) -> Self: ... + @overload + def fit(self, left: float, top: float, width: float, height: float, /) -> Self: ... + def normalize(self) -> None: ... + def __contains__(self, rect: Union[RectValue, _N], /) -> bool: ... # type: ignore[override] + @overload + def contains(self, rect: RectValue, /) -> bool: ... + @overload + def contains(self, left_top: Coordinate, width_height: Coordinate, /) -> bool: ... + @overload + def contains( + self, left: float, top: float, width: float, height: float, / + ) -> bool: ... + @overload + def collidepoint(self, x: float, y: float, /) -> bool: ... + @overload + def collidepoint(self, x_y: Coordinate, /) -> bool: ... + @overload + def colliderect(self, rect: RectValue, /) -> bool: ... + @overload + def colliderect(self, left_top: Coordinate, width_height: Coordinate, /) -> bool: ... + @overload + def colliderect( + self, left: float, top: float, width: float, height: float, / + ) -> bool: ... + @overload + def collidecircle(self, circle: _CircleValue, /) -> bool: ... + @overload + def collidecircle(self, pos: Coordinate, r: float, /) -> bool: ... + @overload + def collidecircle(self, x: float, y: float, r: float, /) -> bool: ... + def collidelist(self, rect_list: Sequence[_RectTypeCompatible_co], /) -> int: ... + def collidelistall(self, rect_list: Sequence[_RectTypeCompatible_co], /) -> List[int]: ... + def collideobjectsall( + self, objects: Sequence[_T], key: Optional[Callable[[_T], RectValue]] = None + ) -> List[_T]: ... + def collideobjects( + self, objects: Sequence[_T], key: Optional[Callable[[_T], RectValue]] = None + ) -> Optional[_T]: ... + @overload + def collidedict( + self, rect_dict: Dict[_RectTypeCompatible_co, _V], values: Literal[False] = False + ) -> Optional[Tuple[_RectTypeCompatible_co, _V]]: ... + @overload + def collidedict( + self, rect_dict: Dict[_K, _RectTypeCompatible_co], values: Literal[True] + ) -> Optional[Tuple[_K, _RectTypeCompatible_co]]: ... + @overload + def collidedictall( + self, rect_dict: Dict[_RectTypeCompatible_co, _V], values: Literal[False] = False + ) -> List[Tuple[_RectTypeCompatible_co, _V]]: ... + @overload + def collidedictall( + self, rect_dict: Dict[_K, _RectTypeCompatible_co], values: Literal[True] + ) -> List[Tuple[_K, _RectTypeCompatible_co]]: ... + +# Rect confirms to the Collection ABC, since it also confirms to +# Sized, Iterable and Container ABCs +class Rect(_GenericRect[int]): + ... + +class FRect(_GenericRect[float]): + ... + +RectType = Rect +FRectType = FRect From 5b8ef8d5224e220fb1743d4ce3e462d10ea01739 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Thu, 30 May 2024 18:37:36 +0200 Subject: [PATCH 11/13] Add double cast --- src_c/rect_impl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index 8b45ece781..1f56c15304 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -1357,7 +1357,8 @@ RectExport_collidecircle(RectObject *self, PyObject *const *args, } return PyBool_FromLong( - pgCollision_RectCircle(srect.x, srect.y, srect.w, srect.h, &circle)); + pgCollision_RectCircle((double)srect.x, (double)srect.y, + (double)srect.w, (double)srect.h, &circle)); } #ifndef OPTIMIZED_COLLIDERECT_SETUP From 87fab924f787ed607bfeb0b26f68fe47c427b423 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Sun, 2 Jun 2024 11:01:12 +0200 Subject: [PATCH 12/13] Add missing newline --- buildconfig/stubs/pygame/geometry.pyi | 1 - 1 file changed, 1 deletion(-) diff --git a/buildconfig/stubs/pygame/geometry.pyi b/buildconfig/stubs/pygame/geometry.pyi index 34e5d5c132..853e559e21 100644 --- a/buildconfig/stubs/pygame/geometry.pyi +++ b/buildconfig/stubs/pygame/geometry.pyi @@ -122,4 +122,3 @@ class Circle: def as_frect(self) -> FRect: ... def __copy__(self) -> Circle: ... copy = __copy__ - \ No newline at end of file From d27deb03cf81ffd800e75f44a95de463d37c4174 Mon Sep 17 00:00:00 2001 From: Damus666 Date: Mon, 10 Jun 2024 12:11:43 +0200 Subject: [PATCH 13/13] Update docs and versionadded --- docs/reST/ref/rect.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/reST/ref/rect.rst b/docs/reST/ref/rect.rst index 867d6ce29a..d16aedc8ec 100644 --- a/docs/reST/ref/rect.rst +++ b/docs/reST/ref/rect.rst @@ -401,11 +401,7 @@ Returns `True` if any portion of the `Circle` overlaps with the rectangle, `False` otherwise. - .. note :: - For collision detection between a rect and a line the :meth:`clipline` - method can be used. - - .. versionadded:: 2.5.0 + .. versionadded:: 2.5.1 .. ## Rect.collidecircle ##