Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
13 changes: 13 additions & 0 deletions arcade/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,19 @@ def default_camera(self) -> DefaultProjector:
"""
return self._ctx._default_camera

@property
def camera(self) -> DefaultProjector:
"""
Alias for :py:attr:`default_camera`.

pyglet looks up ``Window.camera`` (rather than ``default_camera``)
as the fallback camera for batch draws with no camera explicitly
set, so this needs to resolve to the same :py:class:`DefaultProjector`
to keep pyglet's internal drawing (e.g. :py:class:`~pyglet.text.Label`)
going through arcade's projection/scissor handling.
"""
return self._ctx._default_camera

@property
def current_camera(self) -> Projector:
"""
Expand Down
22 changes: 11 additions & 11 deletions arcade/camera/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,14 @@ def activate(self) -> Generator[Self, None, None]:
self._ctx.view_matrix = previous_view
self._ctx.current_camera = previous_projector

# --- pyglet dev6 batch-draw compatibility shim ---
# --- pyglet batch-draw compatibility shim ---
#
# pyglet's own Batch.draw() (used e.g. by pyglet.text.Label.draw(), which
# arcade.Text delegates to) falls back to `window.default_camera` when no
# explicit camera is given. Since Arcade overrides `default_camera` to
# return this class instead of pyglet's own Camera2D, pyglet's batch
# pipeline needs DefaultProjector to satisfy its internal
# CameraScopeProtocol (`.view.scissor`, `.begin()`,
# arcade.Text delegates to) falls back to `window.camera` (`.default_camera`
# pre-dev7) when no explicit camera is given. Since Arcade overrides
# `camera`/`default_camera` to return this class instead of pyglet's own
# Camera2D, pyglet's batch pipeline needs DefaultProjector to satisfy its
# internal CameraScopeProtocol (`.view.scissor`, `.begin()`,
# `.get_group_scissor_area()`) or it raises AttributeError.
@property
def view(self) -> Self:
Expand All @@ -182,13 +182,13 @@ def get_group_scissor_area(self) -> CameraScissor:
# anything beyond what's already visible.
return CameraScissor(*(self._scissor or self.get_current_viewport()))

# pyglet's base Window.projection/.view properties (dev6+) delegate to
# `self.default_camera.projection` / `.view_matrix` respectively
# (`pyglet/window/__init__.py`). Any code that reads/writes
# pyglet's base Window.projection/.view properties delegate to
# `self.camera.projection` / `.view_matrix` respectively (`.default_camera`
# pre-dev7; see `pyglet/window/__init__.py`). Any code that reads/writes
# `window.projection`/`window.view` — pyglet's own internals, test
# infrastructure, or downstream user code — routes through here once
# Arcade's `default_camera` override is in the MRO, so these need to
# exist and behave sensibly rather than raise AttributeError.
# Arcade's `camera`/`default_camera` override is in the MRO, so these need
# to exist and behave sensibly rather than raise AttributeError.
@property
def projection(self) -> Mat4:
if self._matrix is None:
Expand Down
6 changes: 3 additions & 3 deletions arcade/future/background/background_texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(
self.texture = texture

self._scale = scale
self._scale_transform = Mat3().scale(scale, scale)
self._scale_transform = Mat3().scale(1.0 / scale, 1.0 / scale)

self._angle = angle
self._angle_transform = Mat3().rotate(angle)
Expand All @@ -56,7 +56,7 @@ def scale(self) -> float:
@scale.setter
def scale(self, value: float):
self._scale = value
self._scale_transform = Mat3().scale(value, value)
self._scale_transform = Mat3().scale(1.0 / value, 1.0 / value)

@property
def angle(self) -> float:
Expand All @@ -82,7 +82,7 @@ def offset(self) -> tuple[float, float]:
@offset.setter
def offset(self, value: tuple[float, float]):
self._offset = value
self._offset_transform = Mat3().translate(-value[0], value[1])
self._offset_transform = Mat3().translate(value[0], value[1])

@property
def wrap_x(self) -> int:
Expand Down
1 change: 1 addition & 0 deletions arcade/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"rand_vec_magnitude",
"get_distance",
"rotate_point",
"rotate_around_point",
"get_angle_degrees",
"get_angle_radians",
"quaternion_rotation",
Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ classifiers = [
dependencies = [
"pillow>=11.3.0",
"pytiled-parser~=2.2.9",
"pyglet==3.0.dev6",
"pyglet==3.0.dev7",
]
dynamic = ["version"]

Expand Down Expand Up @@ -61,8 +61,7 @@ dev = [
"ruff",
"mypy",
"pyright==1.1.387",
"click==8.1.7", # Temp fix until we bump typer
"typer==0.12.5", # Needed for make.py
"typer==0.27.1", # Needed for make.py; older typer incompatible with security-patched click
"wheel",
"bottle", # Used for web testing playground
{include-group = "extras"},
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_example_docstrings.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def check_single_example_docstring(path: Path, name: str) -> None:
"""

# Read the file & extract the docstring
code = ast.parse(path.read_text())
code = ast.parse(path.read_text(encoding="utf-8"))
docstring = ast.get_docstring(code)

# print(f"Checking if example {name} has a run instruction..")
Expand Down
45 changes: 26 additions & 19 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.