Follow-up to the macro conversion: an adversarial verify pass (one agent per
file vs. the C++ implementation + stubs) found 62 content issues; the real
ones are fixed here.
Callbacks (centralized):
- on_click: receives (pos, MouseButton, InputState), not str (8 files).
- on_enter/on_exit/on_move (UIBase.h): hover passes only (pos) -- removed the
fictional button/action args.
- bounds/global_bounds (UIBase.h): mark (tuple, read-only).
Signatures / types:
- Grid.find_path: document heuristic + weight; get_dijkstra_map: document roots;
compute_fov: FOV | int = FOV.BASIC (not the C constant FOV_BASIC) + Returns;
at/is_in_fov: document (pos) and (x, y) call forms.
- get_metrics: document all 16 returned dict keys (was 8); bresenham: drop the
bogus '*' keyword-only separator.
- Nullable defaults typed correctly: BSP seed/size, ColorLayer draw_fov/
apply_perspective Color|None, Entity.visible_entities radius int=-1 (None is
rejected by the 'i' parser -> see #319).
- Type-token fixes: GridView.center -> Vector; GridView.texture -> (None,
read-only) (unimplemented, #318); GridPoint.grid_pos -> (tuple, read-only);
EntityCollection.find -> Entity | list[Entity] | None; extend RuntimeError;
UniformCollection.values -> list[float | tuple | None].
- automation: onScreen (x, y) form documented; scroll notes x is ignored (#317).
Also: correct stale AStarPath/DijkstraMap signatures in docs/api-audit-2026-04.md
(the bindings were right, the audit table was outdated). Rebaseline the API
snapshot golden and regenerate docs/stubs.
Code-level bugs surfaced by the pass are filed as #317, #318, #319.
Refs #314, #317, #318, #319
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
UIEntity now depends on the grid DATA layer only:
- GridData gains cell_width_px/cell_height_px (mirrored from the grid
texture in UIGrid's 5-arg ctor; texture is write-once) so entity
tile<->pixel math no longer reaches into rendering (getTexture()).
- GridData gains markDirty()/markCompositeDirty(): set the flag on the
UIGrid subobject AND notify owning_view, covering both render paths.
UIGrid disambiguates via 'using UIDrawable::markDirty' so all
pre-existing UIGrid-receiver calls resolve exactly as before.
- The three Python wrappers that still need the full UIGrid (GridPoint
from entity.at(), the _GridData fallback in get_grid, find_path's temp
wrapper) reconstruct it via a single aliasing-downcast helper
(grid_as_uigrid) that documents the never-independently-allocated
GridData invariant; init/set_grid simplify (share grid_data directly).
Removing the casts is deferred to #252.
entity.texture (new, frozen surface +1): thin get/set over the entity's
own UISprite. Entities render with their OWN texture (default_texture
fallback at construction); the grid's texture only determines cell size.
Setter preserves sprite_index; rejects non-Texture (TypeError),
null-data Texture wrappers (ValueError), and deletion.
Adversarial review fixes folded in:
- set_texture/get_texture guard uninitialized Entity wrappers
(RuntimeError), isinstance errors, and null-data Textures.
- PyUIGridViewType tp_dealloc no longer unconditionally severs
GridData::owning_view: gated on last-owner (#251 use_count pattern)
plus owning-view identity. Previously ANY Grid wrapper GC while the
view lived (e.g. scene.children.append(mcrfpy.Grid(...))) silently
broke entity.grid -> Grid identity and data-layer dirty notification.
Tests: tests/regression/issue_313_entity_grid_data_test.py (texture
semantics, grid-cell-size invariance, entity.grid identity, #251 gate
survival, GridPoint outliving teardown, review-fix guards, owning_view
survival) + tests/unit/entity_texture_test.py. API snapshot golden
re-baselined: exactly +1 surface line (Entity.texture) + writability
probe flip. Docs/stubs regenerated. Native + Emscripten builds verified.
Known edges recorded in docs/api-audit-2026-04.md: texture read-back is
a fresh wrapper each get (no Texture __eq__); sprite_index not
re-validated against a new atlas. Multi-view markDirty broadcast and
pure-GridData wrappers remain deferred to #252. Addresses #314.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 1 of the #314/#313 plan (docs/plan-313-314.md): commit a deterministic
full-public-API-surface snapshot as the regression net BEFORE the #313
UIEntity::grid -> GridData refactor, so that refactor reduces to a reviewable diff.
tests/unit/api_surface_snapshot_test.py enumerates the complete public mcrfpy
surface (exported types' methods/properties with docstring-derived type + ro/rw,
12 enums with int values, module functions, singletons, the automation submodule)
and diffs it against tests/snapshots/api_surface.golden.txt. Re-baseline with
MCRF_UPDATE_API_SNAPSHOT=1.
Key design points (verified against source + live introspection):
- mcrfpy.Grid IS mcrfpy.GridView and delegates its real API to an internal
_GridData via tp_getattro -- invisible to dir(). The test walks grid.grid_data
AND probes delegation integrity on a live instance (69/69 members resolve).
- Behavioral writability probes compensate for docstring-derived ro/rw inference.
- Every exported class is classified FROZEN vs EXPERIMENTAL; the snapshot captures
the classification so future additions force a deliberate freeze decision.
Freeze decisions recorded in docs/api-audit-2026-04.md:
- F3: grid_pos is the canonical cell-position name (matches the constructor kwarg);
cell_pos/cell_x/cell_y documented as aliases. Docstrings aligned in UIEntity.cpp.
- F12: deprecated set_scale KEPT in the 1.0 surface (removal would be a new break).
- automation camelCase EXEMPT from the snake_case rule.
- EXPERIMENTAL (exempt): 3D/Voxel, Tiled/LDtk import, Shader, binding helpers.
- FROZEN: core UI/Grid/Entity/value types, enums, procgen (BSP/HeightMap/
NoiseSource/DijkstraMap/AStarPath), Drawable (root).
Doc/stub regeneration and the entity.texture addition are deferred to Phase 2
(the #313 refactor). Addresses #314.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review of session 1b14b941 found two issues:
- Exported type count was 44 in audit doc but array has 46 entries
(EntityCollection3DIterType and one other were not counted)
- No regression test existed for the Color.__eq__/__ne__ fix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>