Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions buildconfig/stubs/pygame/_render.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ class Renderer:
def fill_rect(self, rect: RectLike) -> None: ...
def fill_triangle(self, p1: Point, p2: Point, p3: Point) -> None: ...
def get_viewport(self) -> Rect: ...
def logical_to_window(
self, logical_x: float, logical_y: float
) -> tuple[int, int]: ...
def window_to_logical(
self, window_x: int, window_y: int
) -> tuple[float, float]: ...
def present(self) -> None: ...
def set_viewport(self, area: Optional[RectLike]) -> None: ...
def to_surface(
Expand Down
16 changes: 16 additions & 0 deletions docs/reST/ref/sdl2_video.rst
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,22 @@
drawing area on the target, or ``None`` to use the
entire area of the current rendering target.

.. method:: logical_to_window

| :sl:`Translates logical coordinates to window coordinates`
| :sg:`logical_to_window(logical_x, logical_y) -> (int, int)`

:param logical_x: The x coordinate in logical space
:param logical_y: The y coordinate in logical space

.. method:: window_to_logical

| :sl:`Translates window coordinates to logical coordinates`
| :sg:`window_to_logical(window_x, window_y) -> (float, float)`

:param window_x: The x coordinate in window space
:param window_y: The y coordinate in window space

.. method:: blit

| :sl:`Draw textures using a Surface-like API`
Expand Down
2 changes: 2 additions & 0 deletions src_c/doc/sdl2_video_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#define DOC_SDL2_VIDEO_RENDERER_PRESENT "present() -> None\nUpdate the screen with any rendering performed since the previous call"
#define DOC_SDL2_VIDEO_RENDERER_GETVIEWPORT "get_viewport() -> Rect\nGet the drawing area on the rendering target"
#define DOC_SDL2_VIDEO_RENDERER_SETVIEWPORT "set_viewport(area) -> None\nSet the drawing area on the rendering target"
#define DOC_SDL2_VIDEO_RENDERER_LOGICALTOWINDOW "logical_to_window(logical_x, logical_y) -> (int, int)\nTranslates logical coordinates to window coordinates"
#define DOC_SDL2_VIDEO_RENDERER_WINDOWTOLOGICAL "window_to_logical(window_x, window_y) -> (float, float)\nTranslates window coordinates to logical coordinates"
#define DOC_SDL2_VIDEO_RENDERER_BLIT "blit(source, dest, area=None, special_flags=0)-> Rect\nDraw textures using a Surface-like API"
#define DOC_SDL2_VIDEO_RENDERER_DRAWLINE "draw_line(p1, p2) -> None\nDraw a line"
#define DOC_SDL2_VIDEO_RENDERER_DRAWPOINT "draw_point(point) -> None\nDraw a point"
Expand Down
74 changes: 74 additions & 0 deletions src_c/render.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,76 @@ renderer_set_logical_size(pgRendererObject *self, PyObject *arg, void *closure)
return 0;
}

static PyObject *
renderer_logical_to_window(pgRendererObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
int x, y;

if (nargs != 2) {
PyErr_SetString(
PyExc_TypeError,
"logical_to_window requires exactly 2 numeric arguments");
return NULL;
}

PyObject *logical_x = args[0];
PyObject *logical_y = args[1];

double lx = PyFloat_AsDouble(logical_x);
if (PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"The argument logical_x must be a number");
return NULL;
}

double ly = PyFloat_AsDouble(logical_y);
if (PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"The argument logical_y must be a number");
return NULL;
}

SDL_RenderLogicalToWindow(self->renderer, (float)lx, (float)ly, &x, &y);

return pg_tuple_couple_from_values_int(x, y);
}

static PyObject *
renderer_window_to_logical(pgRendererObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
float x, y;

if (nargs != 2) {
PyErr_SetString(
PyExc_TypeError,
"window_to_logical requires exactly 2 numeric arguments");
return NULL;
}

PyObject *window_x = args[0];
PyObject *window_y = args[1];

int wx = (int)PyFloat_AsDouble(window_x);
if (PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"The argument window_x must be a number");
return NULL;
}

int wy = (int)PyFloat_AsDouble(window_y);
if (PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"The argument window_y must be a number");
return NULL;
}

SDL_RenderWindowToLogical(self->renderer, wx, wy, &x, &y);

return pg_tuple_couple_from_values_double(x, y);
}

static PyObject *
renderer_get_scale(pgRendererObject *self, void *closure)
{
Expand Down Expand Up @@ -582,6 +652,10 @@ static PyMethodDef renderer_methods[] = {
METH_VARARGS | METH_KEYWORDS, DOC_SDL2_VIDEO_RENDERER_SETVIEWPORT},
{"get_viewport", (PyCFunction)renderer_get_viewport, METH_NOARGS,
DOC_SDL2_VIDEO_RENDERER_GETVIEWPORT},
{"logical_to_window", (PyCFunction)renderer_logical_to_window,
METH_FASTCALL, DOC_SDL2_VIDEO_RENDERER_LOGICALTOWINDOW},
{"window_to_logical", (PyCFunction)renderer_window_to_logical,
METH_FASTCALL, DOC_SDL2_VIDEO_RENDERER_WINDOWTOLOGICAL},
{"compose_custom_blend_mode",
(PyCFunction)renderer_compose_custom_blend_mode,
METH_VARARGS | METH_KEYWORDS | METH_CLASS,
Expand Down
2 changes: 2 additions & 0 deletions test/render_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ def test_logical_size(self):
self.assertEqual(self.renderer.logical_size, (0, 0))
self.renderer.logical_size = (10, 10)
self.assertEqual(self.renderer.logical_size, (10, 10))
self.assertEqual(self.renderer.logical_to_window(10, 10), (100, 100))
self.assertEqual(self.renderer.window_to_logical(100, 100), (10, 10))

def test_scale(self):
self.assertEqual(self.renderer.scale, (1.0, 1.0))
Expand Down
Loading