Skip to content

Commit 6df9334

Browse files
committed
Fix mouse tile regressions and improve integer coordinate handling
Refactor Point to be generic to better track what uses int and float types Fix wrong C type in get_mouse_state, added function to samples Added separate integer attributes to mouse events
1 parent 1ab50f7 commit 6df9334

File tree

4 files changed

+125
-81
lines changed

4 files changed

+125
-81
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,30 @@ This project adheres to [Semantic Versioning](https://semver.org/) since version
99
### Added
1010

1111
- `tcod.sdl.video.Window` now accepts an SDL WindowID.
12+
- `MouseState.integer_position` and `MouseMotion.integer_motion` to handle cases where integer values are preferred.
1213

1314
### Changed
1415

1516
- Event classes are now more strict with attribute types
1617
- Event class initializers are keyword-only and no longer take a type parameter, with exceptions.
1718
Generally event class initialization is an internal process.
1819
- `MouseButtonEvent` no longer a subclass of `MouseState`.
20+
- `tcod.event.Point` is now a generic type containing `int` or `float` values depending on the context.
21+
- When converting mouse events to tiles:
22+
`MouseState.position` and `MouseMotion.motion` refers to sub-tile coordinates.
23+
`MouseState.integer_position` and `MouseMotion.integer_motion` refers to integer tile coordinates.
1924

2025
### Deprecated
2126

2227
- `Event.type` is deprecated except for special cases such as `ControllerDevice`, `WindowEvent`, etc.
2328
- `MouseButtonEvent.state` is deprecated, replaced by the existing `.button` attribute.
2429

30+
### Fixed
31+
32+
- Fixed incorrect C FFI types inside `tcod.event.get_mouse_state`.
33+
- Fixed regression in mouse event tile coordinates being `float` instead of `int`.
34+
`convert_coordinates_from_window` can be used if sub-tile coordinates were desired.
35+
2536
## [20.1.0] - 2026-02-25
2637

2738
### Added

examples/samples_tcod.py

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,6 @@ class MouseSample(Sample):
10111011

10121012
def __init__(self) -> None:
10131013
self.motion = tcod.event.MouseMotion()
1014-
self.mouse_left = self.mouse_middle = self.mouse_right = 0
10151014
self.log: list[str] = []
10161015

10171016
def on_enter(self) -> None:
@@ -1022,15 +1021,18 @@ def on_enter(self) -> None:
10221021

10231022
def on_draw(self) -> None:
10241023
sample_console.clear(bg=GREY)
1024+
mouse_state = tcod.event.get_mouse_state()
10251025
sample_console.print(
10261026
1,
10271027
1,
1028-
f"Pixel position : {self.motion.position.x:4.0f}x{self.motion.position.y:4.0f}\n"
1029-
f"Tile position : {self.motion.tile.x:4.0f}x{self.motion.tile.y:4.0f}\n"
1030-
f"Tile movement : {self.motion.tile_motion.x:4.0f}x{self.motion.tile_motion.y:4.0f}\n"
1031-
f"Left button : {'ON' if self.mouse_left else 'OFF'}\n"
1032-
f"Right button : {'ON' if self.mouse_right else 'OFF'}\n"
1033-
f"Middle button : {'ON' if self.mouse_middle else 'OFF'}\n",
1028+
f"Pixel position : {mouse_state.position.x:4.0f}x{mouse_state.position.y:4.0f}\n"
1029+
f"Tile position : {self.motion.tile.x:4d}x{self.motion.tile.y:4d}\n"
1030+
f"Tile movement : {self.motion.tile_motion.x:4d}x{self.motion.tile_motion.y:4d}\n"
1031+
f"Left button : {'ON' if mouse_state.state & tcod.event.MouseButtonMask.LEFT else 'OFF'}\n"
1032+
f"Middle button : {'ON' if mouse_state.state & tcod.event.MouseButtonMask.MIDDLE else 'OFF'}\n"
1033+
f"Right button : {'ON' if mouse_state.state & tcod.event.MouseButtonMask.RIGHT else 'OFF'}\n"
1034+
f"X1 button : {'ON' if mouse_state.state & tcod.event.MouseButtonMask.X1 else 'OFF'}\n"
1035+
f"X2 button : {'ON' if mouse_state.state & tcod.event.MouseButtonMask.X2 else 'OFF'}\n",
10341036
fg=LIGHT_YELLOW,
10351037
bg=None,
10361038
)
@@ -1046,18 +1048,6 @@ def on_event(self, event: tcod.event.Event) -> None:
10461048
match event:
10471049
case tcod.event.MouseMotion():
10481050
self.motion = event
1049-
case tcod.event.MouseButtonDown(button=tcod.event.MouseButton.LEFT):
1050-
self.mouse_left = True
1051-
case tcod.event.MouseButtonDown(button=tcod.event.MouseButton.MIDDLE):
1052-
self.mouse_middle = True
1053-
case tcod.event.MouseButtonDown(button=tcod.event.MouseButton.RIGHT):
1054-
self.mouse_right = True
1055-
case tcod.event.MouseButtonUp(button=tcod.event.MouseButton.LEFT):
1056-
self.mouse_left = False
1057-
case tcod.event.MouseButtonUp(button=tcod.event.MouseButton.MIDDLE):
1058-
self.mouse_middle = False
1059-
case tcod.event.MouseButtonUp(button=tcod.event.MouseButton.RIGHT):
1060-
self.mouse_right = False
10611051
case tcod.event.KeyDown(sym=KeySym.N1):
10621052
tcod.sdl.mouse.show(visible=False)
10631053
case tcod.event.KeyDown(sym=KeySym.N2):
@@ -1422,8 +1412,8 @@ def handle_events() -> None:
14221412
tile_event = tcod.event.convert_coordinates_from_window(event, context, root_console)
14231413
SAMPLES[cur_sample].on_event(tile_event)
14241414
match tile_event:
1425-
case tcod.event.MouseMotion(position=(x, y)):
1426-
mouse_tile_xy = int(x), int(y)
1415+
case tcod.event.MouseMotion(integer_position=(x, y)):
1416+
mouse_tile_xy = x, y
14271417
case tcod.event.WindowEvent(type="WindowLeave"):
14281418
mouse_tile_xy = -1, -1
14291419

tcod/context.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import pickle
3030
import sys
3131
import warnings
32+
from math import floor
3233
from pathlib import Path
3334
from typing import TYPE_CHECKING, Any, Literal, NoReturn, TypeVar
3435

@@ -256,16 +257,22 @@ def convert_event(self, event: _Event) -> _Event:
256257
event_copy = copy.copy(event)
257258
if isinstance(event, (tcod.event.MouseState, tcod.event.MouseMotion)):
258259
assert isinstance(event_copy, (tcod.event.MouseState, tcod.event.MouseMotion))
259-
event_copy.position = event._tile = tcod.event.Point(*self.pixel_to_tile(*event.position))
260+
event_copy.position = tcod.event.Point(*self.pixel_to_tile(event.position[0], event.position[1]))
261+
event._tile = tcod.event.Point(floor(event_copy.position[0]), floor(event_copy.position[1]))
260262
if isinstance(event, tcod.event.MouseMotion):
261263
assert isinstance(event_copy, tcod.event.MouseMotion)
262264
assert event._tile is not None
263265
prev_tile = self.pixel_to_tile(
264266
event.position[0] - event.motion[0],
265267
event.position[1] - event.motion[1],
266268
)
267-
event_copy.motion = event._tile_motion = tcod.event.Point(
268-
int(event._tile[0]) - int(prev_tile[0]), int(event._tile[1]) - int(prev_tile[1])
269+
event_copy.motion = tcod.event.Point(
270+
event_copy.position[0] - prev_tile[0],
271+
event_copy.position[1] - prev_tile[1],
272+
)
273+
event._tile_motion = tcod.event.Point(
274+
event._tile[0] - floor(prev_tile[0]),
275+
event._tile[1] - floor(prev_tile[1]),
269276
)
270277
return event_copy
271278

0 commit comments

Comments
 (0)