Compare commits

...

2 commits

Author SHA1 Message Date
da6f4a3e62 docs: Add Line/Circle/Arc to stubs and fix click→on_click
- Add Line, Circle, Arc class definitions to type stubs
- Update UIElement type alias to include new drawable types
- Rename click kwarg to on_click throughout stubs (matches #126 change)
- Update UICollection docstring to list all drawable types

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 14:36:54 -05:00
c9c7375827 refactor: Rename click kwarg to on_click for API consistency (closes #126)
BREAKING CHANGE: Constructor keyword argument renamed from `click` to
`on_click` for all UIDrawable types (Frame, Caption, Sprite, Grid, Line,
Circle, Arc).

Before: Frame(pos=(0,0), size=(100,100), click=handler)
After:  Frame(pos=(0,0), size=(100,100), on_click=handler)

The property name was already `on_click` - this makes the constructor
kwarg match, completing the callback naming standardization from #139.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 14:31:22 -05:00
15 changed files with 2076 additions and 236 deletions

File diff suppressed because it is too large Load diff

View file

@ -108,7 +108,7 @@
<body>
<div class="container">
<h1>McRogueFace API Reference</h1>
<p><em>Generated on 2025-11-29 10:12:05</em></p>
<p><em>Generated on 2025-12-28 14:29:42</em></p>
<p><em>This documentation was dynamically generated from the compiled module.</em></p>
<div class="toc">
@ -126,6 +126,7 @@
<li><a href="#Drawable">Drawable</a></li>
<li><a href="#Entity">Entity</a></li>
<li><a href="#EntityCollection">EntityCollection</a></li>
<li><a href="#FOV">FOV</a></li>
<li><a href="#Font">Font</a></li>
<li><a href="#Frame">Frame</a></li>
<li><a href="#Grid">Grid</a></li>
@ -392,6 +393,18 @@ Note:</p>
<p><span class='raises'>Raises:</span> RuntimeError: If a benchmark is already running Benchmark filename is auto-generated from PID and timestamp. Use end_benchmark() to stop and get filename.</p>
</div>
<div class="method-section">
<h3><code class="function-signature">step(dt: float = None) -> float</code></h3>
<p>Advance simulation time (headless mode only).
Note:</p>
<h4>Arguments:</h4>
<ul>
<li><span class='arg-name'>dt</span>: Time to advance in seconds. If None, advances to the next scheduled event (timer/animation).</li>
</ul>
<p><span class='returns'>Returns:</span> float: Actual time advanced in seconds. Returns 0.0 in windowed mode. In windowed mode, this is a no-op and returns 0.0. Use this for deterministic simulation control in headless/testing scenarios.</p>
</div>
<h2 id='classes'>Classes</h2>
<div class="method-section">
@ -424,14 +437,16 @@ Note:</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">start(target: UIDrawable) -> None</code></h5>
<h5><code class="method-name">start(target: UIDrawable, conflict_mode: str = 'replace') -> None</code></h5>
<p>Start the animation on a target UI element.
Note:</p>
<div style='margin-left: 20px;'>
<div><span class='arg-name'>target</span>: The UI element to animate (Frame, Caption, Sprite, Grid, or Entity)</div>
<div><span class='arg-name'>conflict_mode</span>: How to handle conflicts if property is already animating: &#x27;replace&#x27; (default) - complete existing animation and start new one; &#x27;queue&#x27; - wait for existing animation to complete; &#x27;error&#x27; - raise RuntimeError if property is busy</div>
</div>
<p style='margin-left: 20px;'><span class='returns'>Returns:</span> None The animation will automatically stop if the target is destroyed. Call AnimationManager.update(delta_time) each frame to progress animations.</p>
<p style='margin-left: 20px;'><span class='returns'>Returns:</span> None</p>
<p style='margin-left: 20px;'><span class='raises'>Raises:</span> RuntimeError: When conflict_mode=&#x27;error&#x27; and property is already animating The animation will automatically stop if the target is destroyed.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
@ -462,7 +477,7 @@ Args:
thickness (float, optional): Line thickness. Default: 1.0
Keyword Args:
click (callable): Click handler. Default: None
on_click (callable): Click handler. Default: None
visible (bool): Visibility state. Default: True
opacity (float): Opacity (0.0-1.0). Default: 1.0
z_index (int): Rendering order. Default: 0
@ -600,7 +615,7 @@ Args:
outline (float, optional): Outline thickness. Default: 0 (no outline)
Keyword Args:
click (callable): Click handler. Default: None
on_click (callable): Click handler. Default: None
visible (bool): Visibility state. Default: True
opacity (float): Opacity (0.0-1.0). Default: 1.0
z_index (int): Rendering order. Default: 0
@ -709,20 +724,51 @@ Methods:
fill(color): Fill entire layer with color</p>
<h4>Methods:</h4>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">apply_perspective(entity, visible=None, discovered=None, unknown=None)</code></h5>
<p>Bind this layer to an entity for automatic FOV updates.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">at(x, y) -> Color</code></h5>
<p>Get the color at cell position (x, y).</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">clear_perspective()</code></h5>
<p>Remove the perspective binding from this layer.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">draw_fov(source, radius=None, fov=None, visible=None, discovered=None, unknown=None)</code></h5>
<p>Paint cells based on field-of-view visibility from source position.
Note: Layer must be attached to a grid for FOV calculation.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">fill(color)</code></h5>
<p>Fill the entire layer with the specified color.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">fill_rect(pos, size, color)</code></h5>
<p>Fill a rectangular region with a color.</p>
<div style='margin-left: 20px;'>
<div><span class='arg-name'>color</span>: Color object or (r, g, b[, a]) tuple</div>
</div>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">set(x, y, color)</code></h5>
<p>Set the color at cell position (x, y).</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">update_perspective()</code></h5>
<p>Redraw FOV based on the bound entity&#x27;s current position.
Call this after the entity moves to update the visibility layer.</p>
</div>
</div>
<div class="method-section">
@ -852,6 +898,12 @@ Recomputes which cells are visible from the entity&#x27;s position and updates
the entity&#x27;s gridstate to track explored areas. This is called automatically
when the entity moves if it has a grid with perspective set.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">visible_entities(fov=None, radius=None) -> list[Entity]</code></h5>
<p>Get list of other entities visible from this entity&#x27;s position.</p>
<p style='margin-left: 20px;'><span class='returns'>Returns:</span> List of Entity objects that are within field of view. Computes FOV from this entity&#x27;s position and returns all other entities whose positions fall within the visible area.</p>
</div>
</div>
<div class="method-section">
@ -901,6 +953,90 @@ when the entity moves if it has a grid with perspective set.</p>
</div>
</div>
<div class="method-section">
<h3 id="FOV"><span class="class-name">FOV</span></h3>
<p><em>Inherits from: IntEnum</em></p>
<h4>Methods:</h4>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">as_integer_ratio(...)</code></h5>
<p>Return a pair of integers, whose ratio is equal to the original int.
The ratio is in lowest terms and has a positive denominator.
&gt;&gt;&gt; (10).as_integer_ratio()
(10, 1)
&gt;&gt;&gt; (-10).as_integer_ratio()
(-10, 1)
&gt;&gt;&gt; (0).as_integer_ratio()
(0, 1)</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">bit_count(...)</code></h5>
<p>Number of ones in the binary representation of the absolute value of self.
Also known as the population count.
&gt;&gt;&gt; bin(13)
&#x27;0b1101&#x27;
&gt;&gt;&gt; (13).bit_count()
3</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">bit_length(...)</code></h5>
<p>Number of bits necessary to represent self in binary.
&gt;&gt;&gt; bin(37)
&#x27;0b100101&#x27;
&gt;&gt;&gt; (37).bit_length()
6</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">conjugate(...)</code></h5>
<p>Returns self, the complex conjugate of any int.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">from_bytes(...)</code></h5>
<p>Return the integer represented by the given array of bytes.
bytes
Holds the array of bytes to convert. The argument must either
support the buffer protocol or be an iterable object producing bytes.
Bytes and bytearray are examples of built-in objects that support the
buffer protocol.
byteorder
The byte order used to represent the integer. If byteorder is &#x27;big&#x27;,
the most significant byte is at the beginning of the byte array. If
byteorder is &#x27;little&#x27;, the most significant byte is at the end of the
byte array. To request the native byte order of the host system, use
sys.byteorder as the byte order value. Default is to use &#x27;big&#x27;.
signed
Indicates whether two&#x27;s complement is used to represent the integer.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">is_integer(...)</code></h5>
<p>Returns True. Exists for duck type compatibility with float.is_integer.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">to_bytes(...)</code></h5>
<p>Return an array of bytes representing an integer.
length
Length of bytes object to use. An OverflowError is raised if the
integer is not representable with the given number of bytes. Default
is length 1.
byteorder
The byte order used to represent the integer. If byteorder is &#x27;big&#x27;,
the most significant byte is at the beginning of the byte array. If
byteorder is &#x27;little&#x27;, the most significant byte is at the end of the
byte array. To request the native byte order of the host system, use
sys.byteorder as the byte order value. Default is to use &#x27;big&#x27;.
signed
Determines whether two&#x27;s complement is used to represent the integer.
If signed is False and a negative integer is given, an OverflowError
is raised.</p>
</div>
</div>
<div class="method-section">
<h3 id="Font"><span class="class-name">Font</span></h3>
<p>SFML Font Object</p>
@ -1084,6 +1220,17 @@ Attributes:
</div>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">entities_in_radius(x: float, y: float, radius: float) -> list[Entity]</code></h5>
<p>Query entities within radius using spatial hash (O(k) where k = nearby entities).</p>
<div style='margin-left: 20px;'>
<div><span class='arg-name'>x</span>: Center X coordinate</div>
<div><span class='arg-name'>y</span>: Center Y coordinate</div>
<div><span class='arg-name'>radius</span>: Search radius</div>
</div>
<p style='margin-left: 20px;'><span class='returns'>Returns:</span> List of Entity objects within the radius.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">find_path(x1: int, y1: int, x2: int, y2: int, diagonal_cost: float = 1.41) -> List[Tuple[int, int]]</code></h5>
<p>Find A* path between two points.</p>
@ -1201,7 +1348,7 @@ Args:
color (Color, optional): Line color. Default: White
Keyword Args:
click (callable): Click handler. Default: None
on_click (callable): Click handler. Default: None
visible (bool): Visibility state. Default: True
opacity (float): Opacity (0.0-1.0). Default: 1.0
z_index (int): Rendering order. Default: 0
@ -1263,14 +1410,6 @@ Note:</p>
<p style='margin-left: 20px;'><span class='returns'>Returns:</span> None Deactivates the current scene and activates this one. Scene transitions and lifecycle callbacks are triggered.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">get_ui() -> UICollection</code></h5>
<p>Get the UI element collection for this scene.
Note:</p>
<p style='margin-left: 20px;'><span class='returns'>Returns:</span> UICollection: Collection of UI elements (Frames, Captions, Sprites, Grids) in this scene Use to add, remove, or iterate over UI elements. Changes are reflected immediately.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">register_keyboard(callback: callable) -> None</code></h5>
<p>Register a keyboard event handler function.
@ -1279,7 +1418,7 @@ Note:</p>
<div style='margin-left: 20px;'>
<div><span class='arg-name'>callback</span>: Function that receives (key: str, pressed: bool) when keyboard events occur</div>
</div>
<p style='margin-left: 20px;'><span class='returns'>Returns:</span> None Alternative to overriding on_keypress() method. Handler is called for both key press and release events.</p>
<p style='margin-left: 20px;'><span class='returns'>Returns:</span> None Alternative to setting on_key property. Handler is called for both key press and release events.</p>
</div>
</div>
@ -1392,6 +1531,11 @@ Methods:
<p>Fill the entire layer with the specified tile index.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">fill_rect(pos, size, index)</code></h5>
<p>Fill a rectangular region with a tile index.</p>
</div>
<div style="margin-left: 20px; margin-bottom: 15px;">
<h5><code class="method-name">set(x, y, index)</code></h5>
<p>Set the tile index at cell position (x, y). Use -1 for no tile.</p>
@ -1635,19 +1779,6 @@ Note:</p>
<h2 id='constants'>Constants</h2>
<ul>
<li><code>FOV_BASIC</code> (int): 0</li>
<li><code>FOV_DIAMOND</code> (int): 1</li>
<li><code>FOV_PERMISSIVE_0</code> (int): 3</li>
<li><code>FOV_PERMISSIVE_1</code> (int): 4</li>
<li><code>FOV_PERMISSIVE_2</code> (int): 5</li>
<li><code>FOV_PERMISSIVE_3</code> (int): 6</li>
<li><code>FOV_PERMISSIVE_4</code> (int): 7</li>
<li><code>FOV_PERMISSIVE_5</code> (int): 8</li>
<li><code>FOV_PERMISSIVE_6</code> (int): 9</li>
<li><code>FOV_PERMISSIVE_7</code> (int): 10</li>
<li><code>FOV_PERMISSIVE_8</code> (int): 11</li>
<li><code>FOV_RESTRICTIVE</code> (int): 12</li>
<li><code>FOV_SHADOW</code> (int): 2</li>
</ul>
</div>

View file

@ -14,11 +14,11 @@
. ftr VB CB
. ftr VBI CBI
.\}
.TH "MCRFPY" "3" "2025-11-29" "McRogueFace dev" ""
.TH "MCRFPY" "3" "2025-12-28" "McRogueFace dev" ""
.hy
.SH McRogueFace API Reference
.PP
\f[I]Generated on 2025-11-29 10:12:05\f[R]
\f[I]Generated on 2025-12-28 14:29:42\f[R]
.PP
\f[I]This documentation was dynamically generated from the compiled
module.\f[R]
@ -47,6 +47,8 @@ Entity
.IP \[bu] 2
EntityCollection
.IP \[bu] 2
FOV
.IP \[bu] 2
Font
.IP \[bu] 2
Frame
@ -312,6 +314,20 @@ Note:
\f[B]Raises:\f[R] RuntimeError: If a benchmark is already running
Benchmark filename is auto-generated from PID and timestamp.
Use end_benchmark() to stop and get filename.
.SS \f[V]step(dt: float = None) -> float\f[R]
.PP
Advance simulation time (headless mode only).
.PP
Note:
.PP
\f[B]Arguments:\f[R] - \f[V]dt\f[R]: Time to advance in seconds.
If None, advances to the next scheduled event (timer/animation).
.PP
\f[B]Returns:\f[R] float: Actual time advanced in seconds.
Returns 0.0 in windowed mode.
In windowed mode, this is a no-op and returns 0.0.
Use this for deterministic simulation control in headless/testing
scenarios.
.SS Classes
.SS Animation
.PP
@ -348,19 +364,24 @@ Note:
was destroyed Animations automatically clean up when targets are
destroyed.
Use this to check if manual cleanup is needed.
.SS \f[V]start(target: UIDrawable) -> None\f[R]
.SS \f[V]start(target: UIDrawable, conflict_mode: str = \[aq]replace\[aq]) -> None\f[R]
.PP
Start the animation on a target UI element.
.PP
Note:
.PP
\f[B]Arguments:\f[R] - \f[V]target\f[R]: The UI element to animate
(Frame, Caption, Sprite, Grid, or Entity)
(Frame, Caption, Sprite, Grid, or Entity) - \f[V]conflict_mode\f[R]: How
to handle conflicts if property is already animating: `replace'
(default) - complete existing animation and start new one; `queue' -
wait for existing animation to complete; `error' - raise RuntimeError if
property is busy
.PP
\f[B]Returns:\f[R] None The animation will automatically stop if the
target is destroyed.
Call AnimationManager.update(delta_time) each frame to progress
animations.
\f[B]Returns:\f[R] None
.PP
\f[B]Raises:\f[R] RuntimeError: When conflict_mode=`error' and property
is already animating The animation will automatically stop if the target
is destroyed.
.SS \f[V]update(delta_time: float) -> bool\f[R]
.PP
Update the animation by the given time delta.
@ -390,7 +411,7 @@ Default: 90 color (Color, optional): Arc color.
Default: White thickness (float, optional): Line thickness.
Default: 1.0
.PP
Keyword Args: click (callable): Click handler.
Keyword Args: on_click (callable): Click handler.
Default: None visible (bool): Visibility state.
Default: True opacity (float): Opacity (0.0-1.0).
Default: 1.0 z_index (int): Rendering order.
@ -507,7 +528,7 @@ Default: White outline_color (Color, optional): Outline color.
Default: Transparent outline (float, optional): Outline thickness.
Default: 0 (no outline)
.PP
Keyword Args: click (callable): Click handler.
Keyword Args: on_click (callable): Click handler.
Default: None visible (bool): Visibility state.
Default: True opacity (float): Opacity (0.0-1.0).
Default: 1.0 z_index (int): Rendering order.
@ -606,15 +627,36 @@ Methods: at(x, y): Get color at cell position set(x, y, color): Set
color at cell position fill(color): Fill entire layer with color
.PP
\f[B]Methods:\f[R]
.SS \f[V]apply_perspective(entity, visible=None, discovered=None, unknown=None)\f[R]
.PP
Bind this layer to an entity for automatic FOV updates.
.SS \f[V]at(x, y) -> Color\f[R]
.PP
Get the color at cell position (x, y).
.SS \f[V]clear_perspective()\f[R]
.PP
Remove the perspective binding from this layer.
.SS \f[V]draw_fov(source, radius=None, fov=None, visible=None, discovered=None, unknown=None)\f[R]
.PP
Paint cells based on field-of-view visibility from source position.
.PP
Note: Layer must be attached to a grid for FOV calculation.
.SS \f[V]fill(color)\f[R]
.PP
Fill the entire layer with the specified color.
.SS \f[V]fill_rect(pos, size, color)\f[R]
.PP
Fill a rectangular region with a color.
.PP
\f[B]Arguments:\f[R] - \f[V]color\f[R]: Color object or (r, g, b[, a])
tuple
.SS \f[V]set(x, y, color)\f[R]
.PP
Set the color at cell position (x, y).
.SS \f[V]update_perspective()\f[R]
.PP
Redraw FOV based on the bound entity\[cq]s current position.
Call this after the entity moves to update the visibility layer.
.SS Drawable
.PP
Base class for all drawable UI elements
@ -722,6 +764,13 @@ Recomputes which cells are visible from the entity\[cq]s position and
updates the entity\[cq]s gridstate to track explored areas.
This is called automatically when the entity moves if it has a grid with
perspective set.
.SS \f[V]visible_entities(fov=None, radius=None) -> list[Entity]\f[R]
.PP
Get list of other entities visible from this entity\[cq]s position.
.PP
\f[B]Returns:\f[R] List of Entity objects that are within field of view.
Computes FOV from this entity\[cq]s position and returns all other
entities whose positions fall within the visible area.
.SS EntityCollection
.PP
Iterable, indexable collection of Entities
@ -757,6 +806,71 @@ Remove and return entity at index (default: last entity).
.PP
Remove first occurrence of entity.
Raises ValueError if not found.
.SS FOV
.PP
\f[I]Inherits from: IntEnum\f[R]
.PP
\f[B]Methods:\f[R]
.SS \f[V]as_integer_ratio(...)\f[R]
.PP
Return a pair of integers, whose ratio is equal to the original int.
The ratio is in lowest terms and has a positive denominator.
>>> (10).as_integer_ratio() (10, 1) >>> (-10).as_integer_ratio() (-10,
1) >>> (0).as_integer_ratio() (0, 1)
.SS \f[V]bit_count(...)\f[R]
.PP
Number of ones in the binary representation of the absolute value of
self.
Also known as the population count.
>>> bin(13) `0b1101' >>> (13).bit_count() 3
.SS \f[V]bit_length(...)\f[R]
.PP
Number of bits necessary to represent self in binary.
>>> bin(37) `0b100101' >>> (37).bit_length() 6
.SS \f[V]conjugate(...)\f[R]
.PP
Returns self, the complex conjugate of any int.
.SS \f[V]from_bytes(...)\f[R]
.PP
Return the integer represented by the given array of bytes.
bytes Holds the array of bytes to convert.
The argument must either support the buffer protocol or be an iterable
object producing bytes.
Bytes and bytearray are examples of built-in objects that support the
buffer protocol.
byteorder The byte order used to represent the integer.
If byteorder is `big', the most significant byte is at the beginning of
the byte array.
If byteorder is `little', the most significant byte is at the end of the
byte array.
To request the native byte order of the host system, use sys.byteorder
as the byte order value.
Default is to use `big'.
signed Indicates whether two\[cq]s complement is used to represent the
integer.
.SS \f[V]is_integer(...)\f[R]
.PP
Returns True.
Exists for duck type compatibility with float.is_integer.
.SS \f[V]to_bytes(...)\f[R]
.PP
Return an array of bytes representing an integer.
length Length of bytes object to use.
An OverflowError is raised if the integer is not representable with the
given number of bytes.
Default is length 1.
byteorder The byte order used to represent the integer.
If byteorder is `big', the most significant byte is at the beginning of
the byte array.
If byteorder is `little', the most significant byte is at the end of the
byte array.
To request the native byte order of the host system, use sys.byteorder
as the byte order value.
Default is to use `big'.
signed Determines whether two\[cq]s complement is used to represent the
integer.
If signed is False and a negative integer is given, an OverflowError is
raised.
.SS Font
.PP
SFML Font Object
@ -916,6 +1030,15 @@ Compute field of view from a position.
distance (0 = unlimited) - \f[V]light_walls\f[R]: Whether walls are lit
when visible - \f[V]algorithm\f[R]: FOV algorithm to use (FOV_BASIC,
FOV_DIAMOND, FOV_SHADOW, FOV_PERMISSIVE_0-8)
.SS \f[V]entities_in_radius(x: float, y: float, radius: float) -> list[Entity]\f[R]
.PP
Query entities within radius using spatial hash (O(k) where k = nearby
entities).
.PP
\f[B]Arguments:\f[R] - \f[V]x\f[R]: Center X coordinate - \f[V]y\f[R]:
Center Y coordinate - \f[V]radius\f[R]: Search radius
.PP
\f[B]Returns:\f[R] List of Entity objects within the radius.
.SS \f[V]find_path(x1: int, y1: int, x2: int, y2: int, diagonal_cost: float = 1.41) -> List[Tuple[int, int]]\f[R]
.PP
Find A* path between two points.
@ -1019,7 +1142,7 @@ Default: (0, 0) thickness (float, optional): Line thickness in pixels.
Default: 1.0 color (Color, optional): Line color.
Default: White
.PP
Keyword Args: click (callable): Click handler.
Keyword Args: on_click (callable): Click handler.
Default: None visible (bool): Visibility state.
Default: True opacity (float): Opacity (0.0-1.0).
Default: 1.0 z_index (int): Rendering order.
@ -1071,16 +1194,6 @@ Note:
\f[B]Returns:\f[R] None Deactivates the current scene and activates this
one.
Scene transitions and lifecycle callbacks are triggered.
.SS \f[V]get_ui() -> UICollection\f[R]
.PP
Get the UI element collection for this scene.
.PP
Note:
.PP
\f[B]Returns:\f[R] UICollection: Collection of UI elements (Frames,
Captions, Sprites, Grids) in this scene Use to add, remove, or iterate
over UI elements.
Changes are reflected immediately.
.SS \f[V]register_keyboard(callback: callable) -> None\f[R]
.PP
Register a keyboard event handler function.
@ -1090,7 +1203,7 @@ Note:
\f[B]Arguments:\f[R] - \f[V]callback\f[R]: Function that receives (key:
str, pressed: bool) when keyboard events occur
.PP
\f[B]Returns:\f[R] None Alternative to overriding on_keypress() method.
\f[B]Returns:\f[R] None Alternative to setting on_key property.
Handler is called for both key press and release events.
.SS Sprite
.PP
@ -1187,6 +1300,9 @@ Returns -1 if no tile.
.SS \f[V]fill(index)\f[R]
.PP
Fill the entire layer with the specified tile index.
.SS \f[V]fill_rect(pos, size, index)\f[R]
.PP
Fill a rectangular region with a tile index.
.SS \f[V]set(x, y, index)\f[R]
.PP
Set the tile index at cell position (x, y).
@ -1410,29 +1526,3 @@ given, otherwise None after saving Screenshot is taken at the actual
window resolution.
Use after render loop update for current frame.
.SS Constants
.IP \[bu] 2
\f[V]FOV_BASIC\f[R] (int): 0
.IP \[bu] 2
\f[V]FOV_DIAMOND\f[R] (int): 1
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_0\f[R] (int): 3
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_1\f[R] (int): 4
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_2\f[R] (int): 5
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_3\f[R] (int): 6
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_4\f[R] (int): 7
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_5\f[R] (int): 8
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_6\f[R] (int): 9
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_7\f[R] (int): 10
.IP \[bu] 2
\f[V]FOV_PERMISSIVE_8\f[R] (int): 11
.IP \[bu] 2
\f[V]FOV_RESTRICTIVE\f[R] (int): 12
.IP \[bu] 2
\f[V]FOV_SHADOW\f[R] (int): 2

View file

@ -463,7 +463,7 @@ int UIArc::init(PyUIArcObject* self, PyObject* args, PyObject* kwds) {
static const char* kwlist[] = {
"center", "radius", "start_angle", "end_angle", "color", "thickness",
"click", "visible", "opacity", "z_index", "name",
"on_click", "visible", "opacity", "z_index", "name",
nullptr
};
@ -511,7 +511,7 @@ int UIArc::init(PyUIArcObject* self, PyObject* args, PyObject* kwds) {
// Handle common UIDrawable properties
if (click_handler && click_handler != Py_None) {
if (!PyCallable_Check(click_handler)) {
PyErr_SetString(PyExc_TypeError, "click must be callable");
PyErr_SetString(PyExc_TypeError, "on_click must be callable");
return -1;
}
self->data->click_register(click_handler);

View file

@ -134,7 +134,7 @@ namespace mcrfpydef {
" color (Color, optional): Arc color. Default: White\n"
" thickness (float, optional): Line thickness. Default: 1.0\n\n"
"Keyword Args:\n"
" click (callable): Click handler. Default: None\n"
" on_click (callable): Click handler. Default: None\n"
" visible (bool): Visibility state. Default: True\n"
" opacity (float): Opacity (0.0-1.0). Default: 1.0\n"
" z_index (int): Rendering order. Default: 0\n"

View file

@ -331,7 +331,7 @@ int UICaption::init(PyUICaptionObject* self, PyObject* args, PyObject* kwds)
static const char* kwlist[] = {
"pos", "font", "text", // Positional args (as per spec)
// Keyword-only args
"fill_color", "outline_color", "outline", "font_size", "click",
"fill_color", "outline_color", "outline", "font_size", "on_click",
"visible", "opacity", "z_index", "name", "x", "y",
nullptr
};

View file

@ -400,7 +400,7 @@ PyObject* UICircle::repr(PyUICircleObject* self) {
int UICircle::init(PyUICircleObject* self, PyObject* args, PyObject* kwds) {
static const char* kwlist[] = {
"radius", "center", "fill_color", "outline_color", "outline",
"click", "visible", "opacity", "z_index", "name", NULL
"on_click", "visible", "opacity", "z_index", "name", NULL
};
float radius = 10.0f;
@ -480,7 +480,7 @@ int UICircle::init(PyUICircleObject* self, PyObject* args, PyObject* kwds) {
// Handle common UIDrawable properties
if (click_obj && click_obj != Py_None) {
if (!PyCallable_Check(click_obj)) {
PyErr_SetString(PyExc_TypeError, "click must be callable");
PyErr_SetString(PyExc_TypeError, "on_click must be callable");
return -1;
}
self->data->click_register(click_obj);

View file

@ -123,7 +123,7 @@ namespace mcrfpydef {
" outline_color (Color, optional): Outline color. Default: Transparent\n"
" outline (float, optional): Outline thickness. Default: 0 (no outline)\n\n"
"Keyword Args:\n"
" click (callable): Click handler. Default: None\n"
" on_click (callable): Click handler. Default: None\n"
" visible (bool): Visibility state. Default: True\n"
" opacity (float): Opacity (0.0-1.0). Default: 1.0\n"
" z_index (int): Rendering order. Default: 0\n"

View file

@ -504,7 +504,7 @@ int UIFrame::init(PyUIFrameObject* self, PyObject* args, PyObject* kwds)
static const char* kwlist[] = {
"pos", "size", // Positional args (as per spec)
// Keyword-only args
"fill_color", "outline_color", "outline", "children", "click",
"fill_color", "outline_color", "outline", "children", "on_click",
"visible", "opacity", "z_index", "name", "x", "y", "w", "h", "clip_children", "cache_subtree",
nullptr
};

View file

@ -749,7 +749,7 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) {
static const char* kwlist[] = {
"pos", "size", "grid_size", "texture", // Positional args (as per spec)
// Keyword-only args
"fill_color", "click", "center_x", "center_y", "zoom",
"fill_color", "on_click", "center_x", "center_y", "zoom",
"visible", "opacity", "z_index", "name", "x", "y", "w", "h", "grid_x", "grid_y",
"layers", // #150 - layers dict parameter
nullptr

View file

@ -481,7 +481,7 @@ int UILine::init(PyUILineObject* self, PyObject* args, PyObject* kwds) {
static const char* kwlist[] = {
"start", "end", "thickness", "color",
"click", "visible", "opacity", "z_index", "name",
"on_click", "visible", "opacity", "z_index", "name",
nullptr
};
@ -549,7 +549,7 @@ int UILine::init(PyUILineObject* self, PyObject* args, PyObject* kwds) {
// Handle click handler
if (click_handler && click_handler != Py_None) {
if (!PyCallable_Check(click_handler)) {
PyErr_SetString(PyExc_TypeError, "click must be callable");
PyErr_SetString(PyExc_TypeError, "on_click must be callable");
return -1;
}
self->data->click_register(click_handler);

View file

@ -119,7 +119,7 @@ namespace mcrfpydef {
" thickness (float, optional): Line thickness in pixels. Default: 1.0\n"
" color (Color, optional): Line color. Default: White\n\n"
"Keyword Args:\n"
" click (callable): Click handler. Default: None\n"
" on_click (callable): Click handler. Default: None\n"
" visible (bool): Visibility state. Default: True\n"
" opacity (float): Opacity (0.0-1.0). Default: 1.0\n"
" z_index (int): Rendering order. Default: 0\n"

View file

@ -392,7 +392,7 @@ int UISprite::init(PyUISpriteObject* self, PyObject* args, PyObject* kwds)
static const char* kwlist[] = {
"pos", "texture", "sprite_index", // Positional args (as per spec)
// Keyword-only args
"scale", "scale_x", "scale_y", "click",
"scale", "scale_x", "scale_y", "on_click",
"visible", "opacity", "z_index", "name", "x", "y", "snapshot",
nullptr
};

View file

@ -3,12 +3,11 @@
Core game engine interface for creating roguelike games with Python.
"""
from typing import Any, List, Dict, Tuple, Optional, Callable, Union, overload, Literal
from typing import Any, List, Dict, Tuple, Optional, Callable, Union, overload
# Type aliases
UIElement = Union['Frame', 'Caption', 'Sprite', 'Grid']
UIElement = Union['Frame', 'Caption', 'Sprite', 'Grid', 'Line', 'Circle', 'Arc']
Transition = Union[str, None]
ConflictMode = Literal['replace', 'queue', 'error']
# Classes
@ -116,9 +115,6 @@ class Frame(Drawable):
outline_color: Color
outline: float
on_click: Optional[Callable[[float, float, int], None]]
on_enter: Optional[Callable[[], None]]
on_exit: Optional[Callable[[], None]]
on_move: Optional[Callable[[float, float], None]]
children: 'UICollection'
clip_children: bool
@ -142,9 +138,6 @@ class Caption(Drawable):
outline_color: Color
outline: float
on_click: Optional[Callable[[float, float, int], None]]
on_enter: Optional[Callable[[], None]]
on_exit: Optional[Callable[[], None]]
on_move: Optional[Callable[[float, float], None]]
w: float # Read-only, computed from text
h: float # Read-only, computed from text
@ -165,90 +158,97 @@ class Sprite(Drawable):
sprite_index: int
scale: float
on_click: Optional[Callable[[float, float, int], None]]
on_enter: Optional[Callable[[], None]]
on_exit: Optional[Callable[[], None]]
on_move: Optional[Callable[[float, float], None]]
w: float # Read-only, computed from texture
h: float # Read-only, computed from texture
class Grid(Drawable):
"""Grid(pos=None, size=None, grid_size=(20, 20), texture=None, on_click=None, layers=None)
"""Grid(x=0, y=0, grid_size=(20, 20), texture=None, tile_width=16, tile_height=16, scale=1.0, on_click=None)
A grid-based tilemap UI element for rendering tile-based levels and game worlds.
Supports multiple rendering layers (ColorLayer, TileLayer) and entity management.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, pos: Optional[Tuple[float, float]] = None,
size: Optional[Tuple[float, float]] = None,
grid_size: Tuple[int, int] = (20, 20),
texture: Optional[Texture] = None,
on_click: Optional[Callable] = None,
layers: Optional[Dict[str, str]] = None) -> None: ...
def __init__(self, x: float = 0, y: float = 0, grid_size: Tuple[int, int] = (20, 20),
texture: Optional[Texture] = None, tile_width: int = 16, tile_height: int = 16,
scale: float = 1.0, on_click: Optional[Callable] = None) -> None: ...
grid_size: Tuple[int, int]
grid_x: int # Read-only grid width
grid_y: int # Read-only grid height
tile_width: int
tile_height: int
texture: Texture
zoom: float
center: Tuple[float, float]
center_x: float
center_y: float
fill_color: Color
scale: float
points: List[List['GridPoint']]
entities: 'EntityCollection'
children: 'UICollection'
layers: List[Union['ColorLayer', 'TileLayer']]
hovered_cell: Optional[Tuple[int, int]]
# Mouse event handlers
on_click: Optional[Callable[[float, float, int], None]]
on_enter: Optional[Callable[[], None]]
on_exit: Optional[Callable[[], None]]
on_move: Optional[Callable[[float, float], None]]
# Grid cell event handlers
on_cell_click: Optional[Callable[[int, int], None]]
on_cell_enter: Optional[Callable[[int, int], None]]
on_cell_exit: Optional[Callable[[int, int], None]]
background_color: Color
on_click: Optional[Callable[[int, int, int], None]]
def at(self, x: int, y: int) -> 'GridPoint':
"""Get grid point at tile coordinates."""
...
def add_layer(self, type: str, z_index: int = -1,
texture: Optional[Texture] = None) -> Union['ColorLayer', 'TileLayer']:
"""Add a rendering layer. type='color' or 'tile'. z_index<0 = below entities."""
...
class Line(Drawable):
"""Line(start=None, end=None, thickness=1.0, color=None, on_click=None, **kwargs)
def remove_layer(self, layer: Union['ColorLayer', 'TileLayer']) -> None:
"""Remove a layer from the grid."""
...
A line UI element for drawing straight lines between two points.
"""
def compute_fov(self, x: int, y: int, radius: int) -> None:
"""Compute field of view from a position."""
...
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, start: Optional[Tuple[float, float]] = None,
end: Optional[Tuple[float, float]] = None,
thickness: float = 1.0, color: Optional[Color] = None,
on_click: Optional[Callable] = None) -> None: ...
def is_in_fov(self, x: int, y: int) -> bool:
"""Check if a cell is visible in the current FOV."""
...
start: Vector
end: Vector
thickness: float
color: Color
on_click: Optional[Callable[[float, float, int], None]]
def compute_dijkstra(self, sources: List[Tuple[int, int]], max_cost: float = -1) -> None:
"""Compute Dijkstra distance map from source points."""
...
class Circle(Drawable):
"""Circle(radius=0, center=None, fill_color=None, outline_color=None, outline=0, on_click=None, **kwargs)
def get_dijkstra_distance(self, x: int, y: int) -> float:
"""Get distance to nearest source for a cell."""
...
A circle UI element for drawing filled or outlined circles.
"""
def get_dijkstra_path(self, x: int, y: int) -> List[Tuple[int, int]]:
"""Get path from cell to nearest source."""
...
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, radius: float = 0, center: Optional[Tuple[float, float]] = None,
fill_color: Optional[Color] = None, outline_color: Optional[Color] = None,
outline: float = 0, on_click: Optional[Callable] = None) -> None: ...
def find_path(self, x1: int, y1: int, x2: int, y2: int) -> List[Tuple[int, int]]:
"""Find A* path between two cells."""
...
radius: float
center: Vector
fill_color: Color
outline_color: Color
outline: float
on_click: Optional[Callable[[float, float, int], None]]
class Arc(Drawable):
"""Arc(center=None, radius=0, start_angle=0, end_angle=90, color=None, thickness=1, on_click=None, **kwargs)
An arc UI element for drawing curved line segments.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, center: Optional[Tuple[float, float]] = None, radius: float = 0,
start_angle: float = 0, end_angle: float = 90,
color: Optional[Color] = None, thickness: float = 1.0,
on_click: Optional[Callable] = None) -> None: ...
center: Vector
radius: float
start_angle: float
end_angle: float
color: Color
thickness: float
on_click: Optional[Callable[[float, float, int], None]]
class GridPoint:
"""Grid point representing a single tile."""
@ -259,49 +259,10 @@ class GridPoint:
class GridPointState:
"""State information for a grid point."""
texture_index: int
color: Color
class ColorLayer:
"""Grid layer that renders solid colors per cell."""
z_index: int
visible: bool
grid_size: Tuple[int, int]
def fill(self, color: Color) -> None:
"""Fill all cells with a color."""
...
def set(self, x: int, y: int, color: Color) -> None:
"""Set color at a specific cell."""
...
def at(self, x: int, y: int) -> Color:
"""Get color at a specific cell."""
...
class TileLayer:
"""Grid layer that renders texture tiles per cell."""
z_index: int
visible: bool
texture: Texture
grid_size: Tuple[int, int]
def fill(self, sprite_index: int) -> None:
"""Fill all cells with a sprite index."""
...
def set(self, x: int, y: int, sprite_index: int) -> None:
"""Set tile sprite at a specific cell."""
...
def at(self, x: int, y: int) -> int:
"""Get tile sprite index at a specific cell."""
...
class Entity(Drawable):
"""Entity(grid_x=0, grid_y=0, texture=None, sprite_index=0, name='')
@ -333,7 +294,7 @@ class Entity(Drawable):
...
class UICollection:
"""Collection of UI drawable elements (Frame, Caption, Sprite, Grid)."""
"""Collection of UI drawable elements (Frame, Caption, Sprite, Grid, Line, Circle, Arc)."""
def __len__(self) -> int: ...
def __getitem__(self, index: int) -> UIElement: ...
@ -462,19 +423,8 @@ class Animation:
duration: float, easing: str = 'linear', loop: bool = False,
on_complete: Optional[Callable] = None) -> None: ...
def start(self, target: Any, conflict_mode: ConflictMode = 'replace') -> None:
"""Start the animation on a target UI element.
Args:
target: The UI element to animate (Frame, Caption, Sprite, Grid, or Entity)
conflict_mode: How to handle conflicts if property is already animating:
- 'replace' (default): Complete existing animation and start new one
- 'queue': Wait for existing animation to complete
- 'error': Raise RuntimeError if property is busy
Raises:
RuntimeError: When conflict_mode='error' and property is already animating
"""
def start(self) -> None:
"""Start the animation."""
...
def update(self, dt: float) -> bool:

View file

@ -18,7 +18,7 @@ Core game engine interface for creating roguelike games with Python.
from typing import Any, List, Dict, Tuple, Optional, Callable, Union, overload
# Type aliases
UIElement = Union['Frame', 'Caption', 'Sprite', 'Grid']
UIElement = Union['Frame', 'Caption', 'Sprite', 'Grid', 'Line', 'Circle', 'Arc']
Transition = Union[str, None]
# Classes
@ -108,84 +108,84 @@ class Drawable:
...
class Frame(Drawable):
"""Frame(x=0, y=0, w=0, h=0, fill_color=None, outline_color=None, outline=0, click=None, children=None)
"""Frame(x=0, y=0, w=0, h=0, fill_color=None, outline_color=None, outline=0, on_click=None, children=None)
A rectangular frame UI element that can contain other drawable elements.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, x: float = 0, y: float = 0, w: float = 0, h: float = 0,
fill_color: Optional[Color] = None, outline_color: Optional[Color] = None,
outline: float = 0, click: Optional[Callable] = None,
outline: float = 0, on_click: Optional[Callable] = None,
children: Optional[List[UIElement]] = None) -> None: ...
w: float
h: float
fill_color: Color
outline_color: Color
outline: float
click: Optional[Callable[[float, float, int], None]]
on_click: Optional[Callable[[float, float, int], None]]
children: 'UICollection'
clip_children: bool
class Caption(Drawable):
"""Caption(text='', x=0, y=0, font=None, fill_color=None, outline_color=None, outline=0, click=None)
"""Caption(text='', x=0, y=0, font=None, fill_color=None, outline_color=None, outline=0, on_click=None)
A text display UI element with customizable font and styling.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, text: str = '', x: float = 0, y: float = 0,
font: Optional[Font] = None, fill_color: Optional[Color] = None,
outline_color: Optional[Color] = None, outline: float = 0,
click: Optional[Callable] = None) -> None: ...
on_click: Optional[Callable] = None) -> None: ...
text: str
font: Font
fill_color: Color
outline_color: Color
outline: float
click: Optional[Callable[[float, float, int], None]]
on_click: Optional[Callable[[float, float, int], None]]
w: float # Read-only, computed from text
h: float # Read-only, computed from text
class Sprite(Drawable):
"""Sprite(x=0, y=0, texture=None, sprite_index=0, scale=1.0, click=None)
"""Sprite(x=0, y=0, texture=None, sprite_index=0, scale=1.0, on_click=None)
A sprite UI element that displays a texture or portion of a texture atlas.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, x: float = 0, y: float = 0, texture: Optional[Texture] = None,
sprite_index: int = 0, scale: float = 1.0,
click: Optional[Callable] = None) -> None: ...
on_click: Optional[Callable] = None) -> None: ...
texture: Texture
sprite_index: int
scale: float
click: Optional[Callable[[float, float, int], None]]
on_click: Optional[Callable[[float, float, int], None]]
w: float # Read-only, computed from texture
h: float # Read-only, computed from texture
class Grid(Drawable):
"""Grid(x=0, y=0, grid_size=(20, 20), texture=None, tile_width=16, tile_height=16, scale=1.0, click=None)
"""Grid(x=0, y=0, grid_size=(20, 20), texture=None, tile_width=16, tile_height=16, scale=1.0, on_click=None)
A grid-based tilemap UI element for rendering tile-based levels and game worlds.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, x: float = 0, y: float = 0, grid_size: Tuple[int, int] = (20, 20),
texture: Optional[Texture] = None, tile_width: int = 16, tile_height: int = 16,
scale: float = 1.0, click: Optional[Callable] = None) -> None: ...
scale: float = 1.0, on_click: Optional[Callable] = None) -> None: ...
grid_size: Tuple[int, int]
tile_width: int
tile_height: int
@ -194,12 +194,74 @@ class Grid(Drawable):
points: List[List['GridPoint']]
entities: 'EntityCollection'
background_color: Color
click: Optional[Callable[[int, int, int], None]]
on_click: Optional[Callable[[int, int, int], None]]
def at(self, x: int, y: int) -> 'GridPoint':
"""Get grid point at tile coordinates."""
...
class Line(Drawable):
"""Line(start=None, end=None, thickness=1.0, color=None, on_click=None, **kwargs)
A line UI element for drawing straight lines between two points.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, start: Optional[Tuple[float, float]] = None,
end: Optional[Tuple[float, float]] = None,
thickness: float = 1.0, color: Optional[Color] = None,
on_click: Optional[Callable] = None) -> None: ...
start: Vector
end: Vector
thickness: float
color: Color
on_click: Optional[Callable[[float, float, int], None]]
class Circle(Drawable):
"""Circle(radius=0, center=None, fill_color=None, outline_color=None, outline=0, on_click=None, **kwargs)
A circle UI element for drawing filled or outlined circles.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, radius: float = 0, center: Optional[Tuple[float, float]] = None,
fill_color: Optional[Color] = None, outline_color: Optional[Color] = None,
outline: float = 0, on_click: Optional[Callable] = None) -> None: ...
radius: float
center: Vector
fill_color: Color
outline_color: Color
outline: float
on_click: Optional[Callable[[float, float, int], None]]
class Arc(Drawable):
"""Arc(center=None, radius=0, start_angle=0, end_angle=90, color=None, thickness=1, on_click=None, **kwargs)
An arc UI element for drawing curved line segments.
"""
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, center: Optional[Tuple[float, float]] = None, radius: float = 0,
start_angle: float = 0, end_angle: float = 90,
color: Optional[Color] = None, thickness: float = 1.0,
on_click: Optional[Callable] = None) -> None: ...
center: Vector
radius: float
start_angle: float
end_angle: float
color: Color
thickness: float
on_click: Optional[Callable[[float, float, int], None]]
class GridPoint:
"""Grid point representing a single tile."""
@ -244,7 +306,7 @@ class Entity(Drawable):
...
class UICollection:
"""Collection of UI drawable elements (Frame, Caption, Sprite, Grid)."""
"""Collection of UI drawable elements (Frame, Caption, Sprite, Grid, Line, Circle, Arc)."""
def __len__(self) -> int: ...
def __getitem__(self, index: int) -> UIElement: ...