34 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 2d2c333cd7 |
Refactor UIEntity::grid to shared_ptr<GridData>; add entity.texture; closes #313
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> |
|||
| 16adc92995 |
Add public API-surface snapshot regression test; lock #314 freeze decisions
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> |
|||
| 70434fd1ee |
Fix outdated CLAUDE.md WASM audio entry; update triage notes
CLAUDE.md had Audio as Stubbed for the SDL2/WASM build, but SDL2_mixer is fully wired up via -sUSE_SDL_MIXER=2. Update table to reflect current state (discovered during blog draft review). Also commits previously-staged triage completion notes in docs/ISSUE_TRIAGE_2026-04.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
|||
| 98d2b36739 |
Regenerate docs and stubs after API freeze pass
Picks up the five 1.0 freeze commits (groups A-D + Grid follow-up): * mcrfpy.Animation removed from module exports * parent= kwarg on Frame/Caption/Sprite/Line/Circle/Arc/Grid * grid= kwarg on ColorLayer/TileLayer * Constructor positional reorders (Circle, Caption, Layers) * __getitem__/__setitem__ on ColorLayer/TileLayer/Grid PyMethodDef/PyGetSetDef compliance baseline (per tools/audit_pymethoddef.py): PyGetSetDef: 190/410 MACRO (46.3%) PyMethodDef: 150/345 MACRO (43.5%) 413 raw-string docstring entries remain to migrate to MCRF_METHOD/ MCRF_PROPERTY in a separate sweep. |
|||
| 2086d25581 |
Phase 5.3: documentation regeneration + introspection-based stub generator
Regenerate HTML/Markdown API reference, man page, and type stubs against current committed HEAD (post API-freeze pass #304-#308, #252 overhaul, and Phase 3/4/5.1/5.2 changes). The previous tools/generate_stubs_v2.py hand-maintained hardcoded strings, which drifted badly: stubs still contained removed module functions (setScale, findAll, getMetrics, setDevConsole), lacked new types (GridView, Behavior, Trigger, DiscreteMap, Viewport3D, Entity3D, Model3D, Billboard, NoiseSource, WangSet, LdtkProject, HeightMap, DijkstraMap, AStarPath, ColorLayer, TileLayer, etc.), and missed post-overhaul properties (tile_width/tile_height, sprite_grid, perspective_map, cell_pos, labels, turn_order, move_speed, etc.). Rewrite the generator as a runtime-introspection script mirroring generate_dynamic_docs.py's approach: - classify mcrfpy members (classes, enums, functions, constants, submodules) - parse signatures from docstring first line with proper paren-depth tracking - translate multi-form signatures (foo(x,y) or foo(pos)) to *args/**kwargs - sanitize docstring '...' placeholder params into '**kwargs' - emit IntEnum blocks for int-subclass types with uppercase members - discover delegated methods via instance probing (Grid/GridView -> _GridData) - conservative property type inference (only accept recognized primitives and CapitalCase class names in parenthesized hints) Resulting stubs/mcrfpy.pyi (2069 lines) parses as valid Python. Markdown/HTML/man-page regeneration is otherwise timestamp-only since the introspection path was already current -- the stubs were the stale artifact. |
|||
| f797120d53 |
Replace UIEntity gridstate with DiscreteMap perspective_map; closes #294
Per-entity FOV memory moves from std::vector<UIGridPointState> (two-bool visible/discovered pairs) to a 3-state DiscreteMap (0=UNKNOWN, 1=DISCOVERED, 2=VISIBLE), exposed as entity.perspective_map. The invariant visible-subset-of-discovered becomes structural (single value per cell), and the map is a live, serializable, first-class object rather than an implicit internal array. Changes: - New DiscreteMap C++ class with shared ownership; PyDiscreteMapObject now holds shared_ptr<DiscreteMap>. UIEntity holds the same shared_ptr. - New mcrfpy.Perspective IntEnum (UNKNOWN/DISCOVERED/VISIBLE), modelled on PyInputState. - entity.perspective_map: lazy-allocated on first access with a grid; setter validates size against grid and raises ValueError on mismatch; None clears (next access lazy-reallocates fresh). - updateVisibility() now demotes 2->1 then promotes visible cells to 2. - entity.at(x, y) returns grid.at(x, y) when VISIBLE, else None. - Fog-of-war rendering in UIGridView and UIGrid reads the 3-state map. - Removed: UIEntity::gridstate, ensureGridstate(), entity.gridstate getter, UIGridPointState struct + PyUIGridPointStateType. - Obsolete tests deleted (test_gridpointstate_point, issue_265_gridpointstate_dangle); 4 new tests cover lazy allocation, identity, serialization round-trip, size validation, and the visible-subset-of-discovered invariant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| edd0028270 |
Add WASM developer troubleshooting guide, closes #240
Covers build issues, runtime debugging, browser dev tools, deployment sizing, embedding, and known limitations for Emscripten/WebAssembly builds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
|||
| c332772324 |
Add issue triage document for all 46 open issues
Categorize open issues #53–#304 into 14 system-related groups, prioritized by impact. Recommends tackling dirty-flag bugs (#288-#291) and dangling-pointer bugs (#270, #271, #277) first. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
|||
| 1805b985bd |
Update all 13 tutorial scripts to current enum-based API, refs #167
All tutorial parts (1-13) used the old string-based key/action
comparison API removed in
|
|||
| 4a3854dac1 |
Fix audit type count (44->46) and add regression test for Color __eq__, refs #307
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> |
|||
| 71ab1dcf2e |
Add API consistency audit document for 1.0 freeze preparation
Comprehensive catalog of the full Python API surface area: - 44 exported types, 14 internal types, 10 enums - 13 module functions, 7 module properties, 5 singletons - 15 findings across naming, functionality, deprecations, docs Key findings: camelCase module functions (#304), deprecated sprite_number (#305), legacy enum string comparisons (#306), Color missing __eq__ (#307), redundant Grid.position (#308). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
|||
| 07fd12373d |
First successful Emscripten/WASM build for #158
Build produces mcrogueface.wasm (8.9MB) + mcrogueface.js (126KB): - All 68 C++ source files compile with emcc - Links Python 3.14 (wasm32-emscripten target) - Links libtcod-headless (built for Emscripten) - Uses Emscripten ports: zlib, bzip2, sqlite3 - Includes HACL crypto, expat, mpdec, ffi dependencies CMakeLists.txt updates: - Add HACL .o files (not included in libpython3.14.a) - Add expat, mpdec, ffi static libraries from Python build - Add libtcod WASM build with lodepng and utf8proc - Add Emscripten port link options libtcod-headless submodule updated with Emscripten build. Next: Bundle Python stdlib into WASM filesystem. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| 5081a37c25 |
Document first Emscripten build attempt results
First emcc build confirms Python headers are the blocker: - HeadlessTypes.h stubs compile fine with Emscripten - Game engine code compiles fine - Python C API headers fail: LONG_BIT check, 48-bit shifts on 32-bit WASM Options identified: 1. Pyodide - pre-built Python WASM (recommended) 2. CPython WASM - build ourselves (complex) 3. No-Python mode - test build without scripting (simplest for now) Contributes to #158 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| 8b6eb1e7ae |
Extract GameEngine::doFrame() for Emscripten callback support
Refactors the main game loop to support both: - Desktop: traditional blocking while(running) loop - Browser: emscripten_set_main_loop_arg() callback (build-time conditional) Changes: - Add doFrame() method containing single-frame update logic - Add isRunning() accessor for Emscripten callback - run() now conditionally uses #ifdef __EMSCRIPTEN__ for loop selection - Add emscriptenMainLoopCallback() static function This is a prerequisite for Emscripten builds - browsers require cooperative multitasking with callback-based frame updates. Both normal and headless builds verified working. Contributes to #158 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| 4c70aee020 |
Add proper CMake MCRF_HEADLESS option for headless builds
- Add option(MCRF_HEADLESS) to CMakeLists.txt for official headless support - Conditional compilation: skip ImGui sources when headless - Conditional linking: no SFML/OpenGL libraries in headless mode - Auto-define MCRF_HEADLESS preprocessor flag Verified: - Zero SFML/OpenGL dynamic dependencies (ldd confirms) - Python interpreter fully functional in headless mode - Core mcrfpy types work: Vector, Color, Scene, Frame, Grid - Binary size: 1.6 MB headless vs 2.5 MB normal (36% reduction) Build with: cmake .. -DMCRF_HEADLESS=ON Contributes to #158 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| 7621ae35bb |
Add MCRF_HEADLESS compile-time build option for #158
This commit enables McRogueFace to compile without SFML dependencies when built with -DMCRF_HEADLESS, a prerequisite for Emscripten/WebAssembly support. Changes: - Add src/platform/HeadlessTypes.h (~900 lines of SFML type stubs) - Consolidate all SFML includes through src/Common.h (15 files fixed) - Wrap ImGui-SFML with #ifndef MCRF_HEADLESS guards - Disable debug console/explorer in headless builds - Add comprehensive research document: docs/EMSCRIPTEN_RESEARCH.md The headless build compiles successfully but uses stub implementations that return failure/no-op. This proves the abstraction boundary is clean and enables future work on alternative backends (VRSFML, Emscripten). What still works in headless mode: - Python interpreter and script execution - libtcod integrations (pathfinding, FOV, noise, BSP, heightmaps) - Timer system and scene management - All game logic and data structures Build commands: Normal: make Headless: cmake .. -DCMAKE_CXX_FLAGS="-DMCRF_HEADLESS" && make Addresses #158 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| 5a1948699e |
Update documentation for API changes #229, #230, #184
CLAUDE.md updates: - Fix Python version 3.12 -> 3.14 - Update keypressScene -> scene.on_key pattern - Add API examples for new callback signatures - Document animation callbacks (target, prop, value) - Document hover callbacks (position-only) - Document enum types (Key, MouseButton, InputState) stubs/mcrfpy.pyi updates: - Add Key, MouseButton, InputState, Easing enum classes - Fix Drawable hover callback signatures per #230 - Fix Grid cell callback signatures per #230 - Fix Scene.on_key signature to use enums per #184 - Update Animation class with correct callback signature per #229 - Add deprecation notes to keypressScene, setTimer, delTimer Regenerated docs: - API_REFERENCE_DYNAMIC.md - api_reference_dynamic.html - mcrfpy.3 man page Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| a3a0618524 | rebuild docs | |||
| 4be2502a10 |
Fix #161: Update Grid, GridPoint, GridPointState stubs to match current API
- Grid: Update constructor (pos, size, grid_size, texture, ...) and add all current properties (zoom, center, layers, FOV, cell events, etc.) - Grid: Add all methods (find_path, compute_fov, add_layer, entities_in_radius, etc.) - GridPoint: Replace incorrect properties (texture_index, solid, color) with actual API (walkable, transparent, entities, grid_pos) - GridPointState: Replace incorrect properties with actual API (visible, discovered, point) - Add missing types: ColorLayer, TileLayer, FOV, AStarPath, DijkstraMap, HeightMap, NoiseSource, BSP Closes #161 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| 73230989ad | Cookbook: draft docs | |||
| c095be4b73 |
HeightMap: core class with scalar operations (closes #193)
Implement the foundational HeightMap class for procedural generation: - HeightMap(size, fill=0.0) constructor with libtcod backend - Immutable size property after construction - Scalar operations returning self for method chaining: - fill(value), clear() - add_constant(value), scale(factor) - clamp(min=0.0, max=1.0), normalize(min=0.0, max=1.0) Includes procedural generation spec document and unit tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| 48359b5a48 | draft tutorial revisions | |||
| 05f28ef7cd |
Add 14-part tutorial Python files (extracted, tested)
Tutorial scripts extracted from documentation, with fixes: - Asset filename: kenney_roguelike.png → kenney_tinydungeon.png - Entity keyword: pos= → grid_pos= (tile coordinates) - Frame.size property → Frame.resize() method - Removed sprite_color (deferred to shader support) All 14 parts pass smoke testing (import + 2-frame run). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| e64c5c147f |
docs: Fix property extraction and add Scene documentation
Doc generator fixes (tools/generate_dynamic_docs.py): - Add types.GetSetDescriptorType detection for C++ extension properties - All 22 classes with properties now have documented Properties sections - Read-only detection via "read-only" docstring convention Scene class documentation (src/PySceneObject.h): - Expanded tp_doc with constructor, properties, lifecycle callbacks - Documents key advantage: on_key works on ANY scene - Includes usage examples for basic and subclass patterns CLAUDE.md additions: - New section "Adding Documentation for New Python Types" - Step-by-step guide for tp_doc, PyMethodDef, PyGetSetDef - Documentation extraction details and troubleshooting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
|||
| 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> |
|||
| d761b53d48 |
docs: Update grid demo and regenerate API docs
- grid_demo.py: Updated for new layer-based rendering - Screenshots: Refreshed demo screenshots - API docs: Regenerated with latest method signatures 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| 4e94291cfb |
docs: Complete Phase 7 documentation system with parser fixes and man pages
Fixed critical documentation generation bugs and added complete multi-format output support. All documentation now generates cleanly from MCRF_* macros. ## Parser Fixes (tools/generate_dynamic_docs.py) Fixed parse_docstring() function: - Added "Raises:" section support (was missing entirely) - Fixed function name duplication in headings - Was: `createSoundBuffercreateSoundBuffer(...)` - Now: `createSoundBuffer(filename: str) -> int` - Proper section separation between Returns and Raises - Handles MCRF_* macro format correctly Changes: - Rewrote parse_docstring() to parse by section markers - Fixed markdown generation (lines 514-539) - Fixed HTML generation (lines 385-413, 446-473) - Added "raises" field to parsed output dict ## Man Page Generation New files: - tools/generate_man_page.sh - Pandoc wrapper for man page generation - docs/mcrfpy.3 - Unix man page (section 3 for library functions) Uses pandoc with metadata: - Section 3 (library functions) - Git version tag in footer - Current date in header ## Master Orchestration Script New file: tools/generate_all_docs.sh Single command generates all documentation formats: - HTML API reference (docs/api_reference_dynamic.html) - Markdown API reference (docs/API_REFERENCE_DYNAMIC.md) - Unix man page (docs/mcrfpy.3) - Type stubs (stubs/mcrfpy.pyi via generate_stubs_v2.py) Includes error checking (set -e) and helpful output messages. ## Documentation Updates (CLAUDE.md) Updated "Regenerating Documentation" section: - Documents new ./tools/generate_all_docs.sh master script - Lists all output files with descriptions - Notes pandoc as system requirement - Clarifies generate_stubs_v2.py is preferred (has @overload support) ## Type Stub Decision Assessed generate_stubs.py vs generate_stubs_v2.py: - generate_stubs.py has critical bugs (missing commas in method signatures) - generate_stubs_v2.py produces high-quality manually-maintained stubs - Decision: Keep v2, use it in master script ## Files Modified Modified: - CLAUDE.md (25 lines changed) - tools/generate_dynamic_docs.py (121 lines changed) - docs/api_reference_dynamic.html (359 lines changed) Created: - tools/generate_all_docs.sh (28 lines) - tools/generate_man_page.sh (12 lines) - docs/mcrfpy.3 (1070 lines) - stubs/mcrfpy.pyi (532 lines) - stubs/mcrfpy/__init__.pyi (213 lines) - stubs/mcrfpy/automation.pyi (24 lines) - stubs/py.typed (0 bytes) Total: 2159 insertions, 225 deletions ## Testing Verified: - Man page viewable with `man docs/mcrfpy.3` - No function name duplication in docs/API_REFERENCE_DYNAMIC.md - Raises sections properly separated from Returns - Master script successfully generates all formats ## Related Issues Addresses requirements from Phase 7 documentation issues. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| 67aba5ef1f |
docs: convert Phase 1 classes to documentation macros (Color, Font, Texture, Timer)
Converted 4 files to use MCRF_* documentation macros: - PyColor.cpp: 3 methods + 4 properties - PyFont.cpp: 2 properties (read-only) - PyTexture.cpp: 6 properties (read-only) - PyTimer.cpp: 4 methods + 7 properties All conversions verified with test_phase1_docs.py - 0 placeholders. Documentation regenerated with enhanced descriptions. Progress: 11/12 class files complete (92%) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| 4c61bee512 |
docs: update CLAUDE.md with MCRF_* macro documentation system
Updated documentation guidelines to reflect the new macro-based system: - Documented MCRF_METHOD and MCRF_PROPERTY usage - Listed all available macros (MCRF_SIG, MCRF_DESC, MCRF_ARG, etc.) - Added prose guidelines (concise C++, verbose external docs) - Updated regeneration workflow (removed references to deleted scripts) - Emphasized single source of truth and zero-drift architecture Removed references to obsolete hardcoded documentation scripts that were deleted in previous commits. Related: #92 (Inline C++ documentation system) |
|||
| 7f253da581 |
fix: escape HTML in descriptions before link transformation
Fixes HTML injection vulnerability in generate_dynamic_docs.py where description text was not HTML-escaped before being inserted into HTML output. Special characters like <, >, & could be interpreted as HTML. Changes: - Modified transform_doc_links() to escape all non-link text when format='html' or format='web' - Link text and hrefs are also properly escaped - Non-HTML formats (markdown, python) remain unchanged - Added proper handling for descriptions with mixed plain text and links The fix splits docstrings into link and non-link segments, escapes non-link segments, and properly escapes content within link patterns. Tested with comprehensive test suite covering: - Basic HTML special characters - Special chars with links - Special chars in link text - Multiple links with special chars 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| 8b7ea544dd |
docs: Add complete API reference documentation
Add comprehensive HTML API reference documentation covering all McRogueFace Python API components, methods, and properties. This documentation was generated from the C++ inline docstrings and provides complete reference material for engine users. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> |
|||
| f4343e1e82 |
Squashed commit of the following: [alpha_presentable]
Author: John McCardle <mccardle.john@gmail.com>
Co-Authored-By: Claude <noreply@anthropic.com>
commit dc47f2474c7b2642d368f9772894aed857527807
the UIEntity rant
commit 673ca8e1b089ea670257fc04ae1a676ed95a40ed
I forget when these tests were written, but I want them in the squash merge
commit 70c71565c684fa96e222179271ecb13a156d80ad
Fix UI object segfault by switching from managed to manual weakref management
The UI types (Frame, Caption, Sprite, Grid, Entity) were using
Py_TPFLAGS_MANAGED_WEAKREF while also trying to manually create weakrefs
for the PythonObjectCache. This is fundamentally incompatible - when
Python manages weakrefs internally, PyWeakref_NewRef() cannot access the
weakref list properly, causing segfaults.
Changed all UI types to use manual weakref management (like PyTimer):
- Restored weakreflist field in all UI type structures
- Removed Py_TPFLAGS_MANAGED_WEAKREF from all UI type flags
- Added tp_weaklistoffset for all UI types in module initialization
- Initialize weakreflist=NULL in tp_new and init methods
- Call PyObject_ClearWeakRefs() in dealloc functions
This allows the PythonObjectCache to continue working correctly,
maintaining Python object identity for C++ objects across the boundary.
Fixes segfault when creating UI objects (e.g., Caption, Grid) that was
preventing tutorial scripts from running.
This is the bulk of the required behavior for Issue #126.
that issure isn't ready for closure yet; several other sub-issues left.
closes #110
mention issue #109 - resolves some __init__ related nuisances
commit 3dce3ec539ae99e32d869007bf3f49d03e4e2f89
Refactor timer system for cleaner architecture and enhanced functionality
Major improvements to the timer system:
- Unified all timer logic in the Timer class (C++)
- Removed PyTimerCallable subclass, now using PyCallable directly
- Timer objects are now passed to callbacks as first argument
- Added 'once' parameter for one-shot timers that auto-stop
- Implemented proper PythonObjectCache integration with weakref support
API enhancements:
- New callback signature: callback(timer, runtime) instead of just (runtime)
- Timer objects expose: name, interval, remaining, paused, active, once properties
- Methods: pause(), resume(), cancel(), restart()
- Comprehensive documentation with examples
- Enhanced repr showing timer state (active/paused/once/remaining time)
This cleanup follows the UIEntity/PyUIEntity pattern and makes the timer
system more Pythonic while maintaining backward compatibility through
the legacy setTimer/delTimer API.
closes #121
commit 145834cfc31b8dabc4cb3591b9cb4ed99fc8b964
Implement Python object cache to preserve derived types in collections
Add a global cache system that maintains weak references to Python objects,
ensuring that derived Python classes maintain their identity when stored in
and retrieved from C++ collections.
Key changes:
- Add PythonObjectCache singleton with serial number system
- Each cacheable object (UIDrawable, UIEntity, Timer, Animation) gets unique ID
- Cache stores weak references to prevent circular reference memory leaks
- Update all UI type definitions to support weak references (Py_TPFLAGS_MANAGED_WEAKREF)
- Enable subclassing for all UI types (Py_TPFLAGS_BASETYPE)
- Collections check cache before creating new Python wrappers
- Register objects in cache during __init__ methods
- Clean up cache entries in C++ destructors
This ensures that Python code like:
```python
class MyFrame(mcrfpy.Frame):
def __init__(self):
super().__init__()
self.custom_data = "preserved"
frame = MyFrame()
scene.ui.append(frame)
retrieved = scene.ui[0] # Same MyFrame instance with custom_data intact
```
Works correctly, with retrieved maintaining the derived type and custom attributes.
Closes #112
commit
|
|||
| 96857a41c6 | hotfix: windows build, fresh docs | |||
| d11f76ac43 |
Squashed commit of 53 Commits: [alpha_streamline_2]
* Field of View, Pathing courtesy of libtcod
* python-tcod emulation at `mcrfpy.libtcod` - partial implementation
* documentation, tutorial drafts: in middling to good shape
┌────────────┬────────────────────┬───────────┬────────────┬───────────────┬────────────────┬────────────────┬─────────────┐
│ Date │ Models │ Input │ Output │ Cache Create │ Cache Read │ Total Tokens │ Cost (USD) │
├────────────┼────────────────────┼───────────┼────────────┼───────────────┼────────────────┼────────────────┼─────────────┤
│ 2025-07-05 │ - opus-4 │ 13,630 │ 159,500 │ 3,854,900 │ 84,185,034 │ 88,213,064 │ $210.72 │
├────────────┼────────────────────┼───────────┼────────────┼───────────────┼────────────────┼────────────────┼─────────────┤
│ 2025-07-06 │ - opus-4 │ 5,814 │ 113,190 │ 4,242,407 │ 150,191,183 │ 154,552,594 │ $313.41 │
├────────────┼────────────────────┼───────────┼────────────┼───────────────┼────────────────┼────────────────┼─────────────┤
│ 2025-07-07 │ - opus-4 │ 7,244 │ 104,599 │ 3,894,453 │ 81,781,179 │ 85,787,475 │ $184.46 │
│ │ - sonnet-4 │ │ │ │ │ │ │
├────────────┼────────────────────┼───────────┼────────────┼───────────────┼────────────────┼────────────────┼─────────────┤
│ 2025-07-08 │ - opus-4 │ 50,312 │ 158,599 │ 5,021,189 │ 60,028,561 │ 65,258,661 │ $167.05 │
│ │ - sonnet-4 │ │ │ │ │ │ │
├────────────┼────────────────────┼───────────┼────────────┼───────────────┼────────────────┼────────────────┼─────────────┤
│ 2025-07-09 │ - opus-4 │ 6,311 │ 109,653 │ 4,171,140 │ 80,092,875 │ 84,379,979 │ $193.09 │
│ │ - sonnet-4 │ │ │ │ │ │ │
└────────────┴────────────────────┴───────────┴────────────┴───────────────┴────────────────┴────────────────┴─────────────┘
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Author: John McCardle <mccardle.john@gmail.com>
Draft tutorials
Author: John McCardle <mccardle.john@gmail.com>
docs: update ROADMAP with FOV, A* pathfinding, and GUI text widget completions
- Mark TCOD Integration Sprint as complete
- Document FOV system with perspective rendering implementation
- Update UIEntity pathfinding status to complete with A* and caching
- Add comprehensive achievement entry for July 10 work
- Reflect current engine capabilities accurately
The engine now has all core roguelike mechanics:
- Field of View with per-entity visibility
- Pathfinding (both Dijkstra and A*)
- Text input for in-game consoles
- Performance optimizations throughout
Author: John McCardle <mccardle.john@gmail.com>
feat(engine): implement perspective FOV, pathfinding, and GUI text widgets
Major Engine Enhancements:
- Complete FOV (Field of View) system with perspective rendering
- UIGrid.perspective property for entity-based visibility
- Three-layer overlay colors (unexplored, explored, visible)
- Per-entity visibility state tracking
- Perfect knowledge updates only for explored areas
- Advanced Pathfinding Integration
- A* pathfinding implementation in UIGrid
- Entity.path_to() method for direct pathfinding
- Dijkstra maps for multi-target pathfinding
- Path caching for performance optimization
- GUI Text Input Widgets
- TextInputWidget class with cursor, selection, scrolling
- Improved widget with proper text rendering and input handling
- Example showcase of multiple text input fields
- Foundation for in-game console and chat systems
- Performance & Architecture Improvements
- PyTexture copy operations optimized
- GameEngine update cycle refined
- UIEntity property handling enhanced
- UITestScene modernized
Test Suite:
- Interactive visibility demos showing FOV in action
- Pathfinding comparison (A* vs Dijkstra)
- Debug utilities for visibility and empty path handling
- Sizzle reel demo combining pathfinding and vision
- Multiple text input test scenarios
This commit brings McRogueFace closer to a complete roguelike engine
with essential features like line-of-sight, intelligent pathfinding,
and interactive text input capabilities.
Author: John McCardle <mccardle.john@gmail.com>
feat(demos): enhance interactive pathfinding demos with entity.path_to()
- dijkstra_interactive_enhanced.py: Animation along paths with smooth movement
- M key to start movement animation
- P to pause/resume
- R to reset positions
- Visual path gradient for better clarity
- pathfinding_showcase.py: Advanced multi-entity behaviors
- Chase mode: enemies pursue player
- Flee mode: enemies avoid player
- Patrol mode: entities follow waypoints
- WASD player movement
- Dijkstra distance field visualization (D key)
- Larger dungeon map with multiple rooms
- Both demos use new entity.path_to() method
- Smooth interpolated movement animations
- Real-time pathfinding recalculation
- Comprehensive test coverage
These demos showcase the power of integrated pathfinding for game AI.
Author: John McCardle <mccardle.john@gmail.com>
feat(entity): implement path_to() method for entity pathfinding
- Add path_to(target_x, target_y) method to UIEntity class
- Uses existing Dijkstra pathfinding implementation from UIGrid
- Returns list of (x, y) coordinate tuples for complete path
- Supports both positional and keyword argument formats
- Proper error handling for out-of-bounds and no-grid scenarios
- Comprehensive test suite covering normal and edge cases
Part of TCOD integration sprint - gives entities immediate pathfinding capabilities.
Author: John McCardle <mccardle.john@gmail.com>
docs: update roadmap with Dijkstra pathfinding progress
- Mark UIGrid TCOD Integration as completed
- Document critical PyArg bug fix achievement
- Update UIEntity Pathfinding to 50% complete
- Add detailed progress notes for July 9 sprint work
Author: John McCardle <mccardle.john@gmail.com>
feat(tcod): complete Dijkstra pathfinding implementation with critical PyArg fix
- Add complete Dijkstra pathfinding to UIGrid class
- compute_dijkstra(), get_dijkstra_distance(), get_dijkstra_path()
- Full TCODMap and TCODDijkstra integration
- Proper memory management in constructors/destructors
- Create mcrfpy.libtcod submodule with Python bindings
- dijkstra_compute(), dijkstra_get_distance(), dijkstra_get_path()
- line() function for drawing corridors
- Foundation for future FOV and pathfinding algorithms
- Fix critical PyArg bug in UIGridPoint color setter
- PyObject_to_sfColor() now handles both Color objects and tuples
- Prevents "SystemError: new style getargs format but argument is not a tuple"
- Proper error handling and exception propagation
- Add comprehensive test suite
- test_dijkstra_simple.py validates all pathfinding operations
- dijkstra_test.py for headless testing with screenshots
- dijkstra_interactive.py for full user interaction demos
- Consolidate and clean up test files
- Removed 6 duplicate/broken demo attempts
- Two clean versions: headless test + interactive demo
Part of TCOD integration sprint for RoguelikeDev Tutorial Event.
Author: John McCardle <mccardle.john@gmail.com>
Roguelike Tutorial Planning + Prep
Author: John McCardle <mccardle.john@gmail.com>
feat(docs): complete markdown API documentation export
- Created comprehensive markdown documentation matching HTML completeness
- Documented all 75 functions, 20 classes, 56 methods, and 20 automation methods
- Zero ellipsis instances - complete coverage with no missing documentation
- Added proper markdown formatting with code blocks and navigation
- Included full parameter documentation, return values, and examples
Key features:
- 23KB GitHub-compatible markdown documentation
- 47 argument sections with detailed parameters
- 35 return value specifications
- 23 code examples with syntax highlighting
- 38 explanatory notes and 10 exception specifications
- Full table of contents with anchor links
- Professional markdown formatting
Both export formats now available:
- HTML: docs/api_reference_complete.html (54KB, rich styling)
- Markdown: docs/API_REFERENCE_COMPLETE.md (23KB, GitHub-compatible)
Author: John McCardle <mccardle.john@gmail.com>
feat(docs): complete API documentation with zero missing methods
- Eliminated ALL ellipsis instances (0 remaining)
- Documented 40 functions with complete signatures and examples
- Documented 21 classes with full method and property documentation
- Added 56 method descriptions with detailed parameters and return values
- Included 15 complete property specifications
- Added 24 code examples and 38 explanatory notes
- Comprehensive coverage of all collection methods, system classes, and functions
Key highlights:
- EntityCollection/UICollection: Complete method docs (append, remove, extend, count, index)
- Animation: Full property and method documentation with examples
- Color: All manipulation methods (from_hex, to_hex, lerp) with examples
- Vector: Complete mathematical operations (magnitude, normalize, dot, distance_to, angle, copy)
- Scene: All management methods including register_keyboard
- Timer: Complete control methods (pause, resume, cancel, restart)
- Window: All management methods (get, center, screenshot)
- System functions: Complete audio, scene, UI, and system function documentation
Author: John McCardle <mccardle.john@gmail.com>
feat(docs): create professional HTML API documentation
- Fixed all formatting issues from original HTML output
- Added comprehensive constructor documentation for all classes
- Enhanced visual design with modern styling and typography
- Fixed literal newline display and markdown link conversion
- Added proper semantic HTML structure and navigation
- Includes detailed documentation for Entity, collections, and system types
Author: John McCardle <mccardle.john@gmail.com>
feat: complete API reference generator and finish Phase 7 documentation
Implemented comprehensive API documentation generator that:
- Introspects live mcrfpy module for accurate documentation
- Generates organized Markdown reference (docs/API_REFERENCE.md)
- Categorizes classes and functions by type
- Includes full automation module documentation
- Provides summary statistics
Results:
- 20 classes documented
- 19 module functions documented
- 20 automation methods documented
- 100% coverage of public API
- Clean, readable Markdown output
Phase 7 Summary:
- Completed 4/5 tasks (1 cancelled as architecturally inappropriate)
- All documentation tasks successful
- Type stubs, docstrings, and API reference all complete
Author: John McCardle <mccardle.john@gmail.com>
docs: cancel PyPI wheel task and add future vision for Python extension architecture
Task #70 Analysis:
- Discovered fundamental incompatibility with PyPI distribution
- McRogueFace embeds CPython rather than being loaded by it
- Traditional wheels expect to extend existing Python interpreter
- Current architecture is application-with-embedded-Python
Decisions:
- Cancelled PyPI wheel preparation as out of scope for Alpha
- Cleaned up attempted packaging files (pyproject.toml, setup.py, etc.)
- Identified better distribution methods (installers, package managers)
Added Future Vision:
- Comprehensive plan for pure Python extension architecture
- Would allow true "pip install mcrogueface" experience
- Requires major refactoring to invert control flow
- Python would drive main loop with C++ performance extensions
- Unscheduled but documented as long-term possibility
This clarifies the architectural boundaries and sets realistic
expectations for distribution methods while preserving the vision
of what McRogueFace could become with significant rework.
Author: John McCardle <mccardle.john@gmail.com>
feat: generate comprehensive .pyi type stubs for IDE support (#108)
Created complete type stub files for the mcrfpy module to enable:
- Full IntelliSense/autocomplete in IDEs
- Static type checking with mypy/pyright
- Better documentation tooltips
- Parameter hints and return types
Implementation details:
- Manually crafted stubs for accuracy (15KB, 533 lines)
- Complete coverage: 19 classes, 112 functions/methods
- Proper type annotations using typing module
- @overload decorators for multiple signatures
- Type aliases for common patterns (UIElement union)
- Preserved all docstrings for IDE help
- Automation module fully typed
- PEP 561 compliant with py.typed marker
Testing:
- Validated Python syntax with ast.parse()
- Verified all expected classes and functions
- Confirmed type annotations are well-formed
- Checked docstring preservation (80 docstrings)
Usage:
- VS Code: Add stubs/ to python.analysis.extraPaths
- PyCharm: Mark stubs/ directory as Sources Root
- Other IDEs will auto-detect .pyi files
This significantly improves the developer experience when using
McRogueFace as a Python game engine.
Author: John McCardle <mccardle.john@gmail.com>
docs: add comprehensive parameter documentation to all API methods (#86)
Enhanced documentation for the mcrfpy module with:
- Detailed docstrings for all API methods
- Type hints in documentation (name: type format)
- Return type specifications
- Exception documentation where applicable
- Usage examples for complex methods
- Module-level documentation with overview and example code
Specific improvements:
- Audio API: Added parameter types and return values
- Scene API: Documented transition types and error conditions
- Timer API: Clarified handler signature and runtime parameter
- UI Search: Added wildcard pattern examples for findAll()
- Metrics API: Documented all dictionary keys returned
Also fixed method signatures:
- Changed METH_VARARGS to METH_NOARGS for parameterless methods
- Ensures proper Python calling conventions
Test coverage included - all documentation is accessible via Python's
__doc__ attributes and shows correctly formatted information.
Author: John McCardle <mccardle.john@gmail.com>
docs: mark issue #85 as completed in Phase 7
Author: John McCardle <mccardle.john@gmail.com>
docs: replace all 'docstring' placeholders with comprehensive documentation (#85)
Added proper Python docstrings for all UI component classes:
UIFrame:
- Container element that can hold child drawables
- Documents position, size, colors, outline, and clip_children
- Includes constructor signature with all parameters
UICaption:
- Text display element with font and styling
- Documents text content, position, font, colors, outline
- Notes that w/h are computed from text content
UISprite:
- Texture/sprite display element
- Documents position, texture, sprite_index, scale
- Notes that w/h are computed from texture and scale
UIGrid:
- Tile-based grid for game worlds
- Documents grid dimensions, tile size, texture atlas
- Includes entities collection and background_color
All docstrings follow consistent format:
- Constructor signature with defaults
- Brief description
- Args section with types and defaults
- Attributes section with all properties
This completes Phase 7 task #85 for documentation improvements.
Author: John McCardle <mccardle.john@gmail.com>
docs: update ROADMAP with PyArgHelpers infrastructure completion
Author: John McCardle <mccardle.john@gmail.com>
refactor: implement PyArgHelpers for standardized Python argument parsing
This major refactoring standardizes how position, size, and other arguments
are parsed across all UI components. PyArgHelpers provides consistent handling
for various argument patterns:
- Position as (x, y) tuple or separate x, y args
- Size as (w, h) tuple or separate width, height args
- Grid position and size with proper validation
- Color parsing with PyColorObject support
Changes across UI components:
- UICaption: Migrated to PyArgHelpers, improved resize() for future multiline support
- UIFrame: Uses standardized position parsing
- UISprite: Consistent position handling
- UIGrid: Grid-specific position/size helpers
- UIEntity: Unified argument parsing
Also includes:
- Improved error messages for type mismatches (int or float accepted)
- Reduced code duplication across constructors
- Better handling of keyword/positional argument conflicts
- Maintains backward compatibility with existing API
This addresses the inconsistent argument handling patterns discovered during
the inheritance hierarchy work and prepares for Phase 7 documentation.
Author: John McCardle <mccardle.john@gmail.com>
feat(Python): establish proper inheritance hierarchy for UI types
All UIDrawable-derived Python types now properly inherit from the Drawable
base class in Python, matching the C++ inheritance structure.
Changes:
- Add Py_TPFLAGS_BASETYPE to PyDrawableType to allow inheritance
- Set tp_base = &mcrfpydef::PyDrawableType for all UI types
- Add PyDrawable.h include to UI type headers
- Rename _Drawable to Drawable and update error message
This enables proper Python inheritance: Frame, Caption, Sprite, Grid,
and Entity all inherit from Drawable, allowing shared functionality
and isinstance() checks.
Author: John McCardle <mccardle.john@gmail.com>
refactor: move position property to UIDrawable base class (UISprite)
- Update UISprite to use base class position instead of sprite position
- Synchronize sprite position with base class position for rendering
- Implement onPositionChanged() for position synchronization
- Update all UISprite methods to use base position consistently
- Add comprehensive test coverage for UISprite position handling
This is part 3 of moving position to the base class. UIGrid is the final
class that needs to be updated.
Author: John McCardle <mccardle.john@gmail.com>
refactor: move position property to UIDrawable base class (UICaption)
- Update UICaption to use base class position instead of text position
- Synchronize text position with base class position for rendering
- Add onPositionChanged() virtual method for position synchronization
- Update all UICaption methods to use base position consistently
- Add comprehensive test coverage for UICaption position handling
This is part 2 of moving position to the base class. UISprite and UIGrid
will be updated in subsequent commits.
Author: John McCardle <mccardle.john@gmail.com>
refactor: move position property to UIDrawable base class (UIFrame)
- Add position member to UIDrawable base class
- Add common position getters/setters (x, y, pos) to base class
- Update UIFrame to use base class position instead of box position
- Synchronize box position with base class position for rendering
- Update all UIFrame methods to use base position consistently
- Add comprehensive test coverage for UIFrame position handling
This is part 1 of moving position to the base class. Other derived classes
(UICaption, UISprite, UIGrid) will be updated in subsequent commits.
Author: John McCardle <mccardle.john@gmail.com>
refactor: remove UIEntity collision_pos field
- Remove redundant collision_pos field from UIEntity
- Update position getters/setters to use integer-cast position when needed
- Remove all collision_pos synchronization code
- Simplify entity position handling to use single float position field
- Add comprehensive test coverage proving functionality is preserved
This removes technical debt and simplifies the codebase without changing API behavior.
Author: John McCardle <mccardle.john@gmail.com>
feat: add PyArgHelpers infrastructure for standardized argument parsing
- Create PyArgHelpers.h with parsing functions for position, size, grid coordinates, and color
- Support tuple-based vector arguments with conflict detection
- Provide consistent error messages and validation
- Add comprehensive test coverage for infrastructure
This sets the foundation for standardizing all Python API constructors.
Author: John McCardle <mccardle.john@gmail.com>
docs: mark Phase 6 (Rendering Revolution) as complete
Phase 6 is now complete with all core rendering features implemented:
Completed Features:
- Grid background colors (#50) - customizable backgrounds with animation
- RenderTexture overhaul (#6) - UIFrame clipping with opt-in architecture
- Viewport-based rendering (#8) - three scaling modes with coordinate transform
Strategic Decisions:
- UIGrid already has optimal RenderTexture implementation for its viewport needs
- UICaption/UISprite clipping deemed unnecessary (no children to clip)
- Effects/Shader/Particle systems deferred to post-Phase 7 for focused delivery
The rendering foundation is now solid and ready for Phase 7: Documentation & Distribution.
Author: John McCardle <mccardle.john@gmail.com>
feat(viewport): complete viewport-based rendering system (#8)
Implements a comprehensive viewport system that allows fixed game resolution
with flexible window scaling, addressing the primary wishes for issues #34, #49, and #8.
Key Features:
- Fixed game resolution independent of window size (window.game_resolution property)
- Three scaling modes accessible via window.scaling_mode:
- "center": 1:1 pixels, viewport centered in window
- "stretch": viewport fills window, ignores aspect ratio
- "fit": maintains aspect ratio with black bars
- Automatic window-to-game coordinate transformation for mouse input
- Full Python API integration with PyWindow properties
Technical Implementation:
- GameEngine::ViewportMode enum with Center, Stretch, Fit modes
- SFML View system for efficient GPU-based viewport scaling
- updateViewport() recalculates on window resize or mode change
- windowToGameCoords() transforms mouse coordinates correctly
- PyScene mouse input automatically uses transformed coordinates
Tests:
- test_viewport_simple.py: Basic API functionality
- test_viewport_visual.py: Visual verification with screenshots
- test_viewport_scaling.py: Interactive mode switching and resizing
This completes the viewport-based rendering task and provides the foundation
for resolution-independent game development as requested for Crypt of Sokoban.
Author: John McCardle <mccardle.john@gmail.com>
docs: update ROADMAP for Phase 6 progress
- Marked Phase 6 as IN PROGRESS
- Updated RenderTexture overhaul (#6) as PARTIALLY COMPLETE
- Marked Grid background colors (#50) as COMPLETED
- Added technical notes from implementation experience
- Identified viewport rendering (#8) as next priority
Author: John McCardle <mccardle.john@gmail.com>
feat(rendering): implement RenderTexture base infrastructure and UIFrame clipping (#6)
- Added RenderTexture support to UIDrawable base class
- std::unique_ptr<sf::RenderTexture> for opt-in rendering
- Dirty flag system for optimization
- enableRenderTexture() and markDirty() methods
- Implemented clip_children property for UIFrame
- Python-accessible boolean property
- Automatic RenderTexture creation when enabled
- Proper coordinate transformation for nested frames
- Updated UIFrame::render() for clipping support
- Renders to RenderTexture when clip_children=true
- Handles nested clipping correctly
- Only re-renders when dirty flag is set
- Added comprehensive dirty flag propagation
- All property setters mark frame as dirty
- Size changes recreate RenderTexture
- Animation system integration
- Created tests for clipping functionality
- Basic clipping test with visual verification
- Advanced nested clipping test
- Dynamic resize handling test
This is Phase 1 of the RenderTexture overhaul, providing the foundation
for advanced rendering effects like blur, glow, and viewport rendering.
Author: John McCardle <mccardle.john@gmail.com>
docs: create RenderTexture overhaul design document
- Comprehensive design for Issue #6 implementation
- Opt-in architecture to maintain backward compatibility
- Phased implementation plan with clear milestones
- Performance considerations and risk mitigation
- API design for clipping and future effects
Also includes Grid background color test
Author: John McCardle <mccardle.john@gmail.com>
feat(Grid): add customizable background_color property (#50)
- Added sf::Color background_color member with default dark gray
- Python property getter/setter for background_color
- Animation support for individual color components (r/g/b/a)
- Replaces hardcoded clear color in render method
- Test demonstrates color changes and property access
Closes #50
Author: John McCardle <mccardle.john@gmail.com>
docs: update roadmap for Phase 6 preparation
- Mark Phase 5 (Window/Scene Architecture) as complete
- Update issue statuses (#34, #61, #1, #105 completed)
- Add Phase 6 implementation strategy for RenderTexture overhaul
- Archive Phase 5 test files to .archive/
- Identify quick wins and technical approach for rendering work
Author: John McCardle <mccardle.john@gmail.com>
feat(Phase 5): Complete Window/Scene Architecture
- Window singleton with properties (resolution, fullscreen, vsync, title)
- OOP Scene support with lifecycle methods (on_enter, on_exit, on_keypress, update)
- Window resize events trigger scene.on_resize callbacks
- Scene transitions (fade, slide_left/right/up/down) with smooth animations
- Full integration of Python Scene objects with C++ engine
All Phase 5 tasks (#34, #1, #61, #105) completed successfully.
Author: John McCardle <mccardle.john@gmail.com>
research: SFML 3.0 migration analysis
- Analyzed SFML 3.0 breaking changes (event system, scoped enums, C++17)
- Assessed migration impact on McRogueFace (40+ files affected)
- Evaluated timing relative to mcrfpy.sfml module plans
- Recommended deferring migration until after mcrfpy.sfml implementation
- Created SFML_3_MIGRATION_RESEARCH.md with comprehensive strategy
Author: John McCardle <mccardle.john@gmail.com>
research: SFML exposure options analysis (#14)
- Analyzed current SFML 2.6.1 usage throughout codebase
- Evaluated python-sfml (abandoned, only supports SFML 2.3.2)
- Recommended direct integration as mcrfpy.sfml module
- Created comprehensive SFML_EXPOSURE_RESEARCH.md with implementation plan
- Identified opportunity to provide modern SFML 2.6+ Python bindings
Author: John McCardle <mccardle.john@gmail.com>
feat: add basic profiling/metrics system (#104)
- Add ProfilingMetrics struct to track performance data
- Track frame time (current and 60-frame rolling average)
- Calculate FPS from average frame time
- Count draw calls, UI elements, and visible elements per frame
- Track total runtime and current frame number
- PyScene counts elements during render
- Expose metrics via mcrfpy.getMetrics() returning dict
This provides basic performance monitoring capabilities for
identifying bottlenecks and optimizing rendering performance.
Author: John McCardle <mccardle.john@gmail.com>
fix: improve click handling with proper z-order and coordinate transforms
- UIFrame: Fix coordinate transformation (subtract parent pos, not add)
- UIFrame: Check children in reverse order (highest z-index first)
- UIFrame: Skip invisible elements entirely
- PyScene: Sort elements by z-index before checking clicks
- PyScene: Stop at first element that handles the click
- UIGrid: Implement entity click detection with grid coordinate transform
- UIGrid: Check entities in reverse order, return sprite as target
Click events now correctly respect z-order (top elements get priority),
handle coordinate transforms for nested frames, and support clicking
on grid entities. Elements without click handlers are transparent to
clicks, allowing elements below to receive them.
Note: Click testing requires non-headless mode due to PyScene limitation.
feat: implement name system for finding UI elements (#39/40/41)
- Add 'name' property to UIDrawable base class
- All UI elements (Frame, Caption, Sprite, Grid, Entity) support .name
- Entity delegates name to its sprite member
- Add find(name, scene=None) function for exact match search
- Add findAll(pattern, scene=None) with wildcard support (* matches any sequence)
- Both functions search recursively through Frame children and Grid entities
- Comprehensive test coverage for all functionality
This provides a simple way to find UI elements by name in Python scripts,
supporting both exact matches and wildcard patterns.
Author: John McCardle <mccardle.john@gmail.com>
fix: prevent segfault when closing window via X button
- Add cleanup() method to GameEngine to clear Python references before destruction
- Clear timers and McRFPy_API references in proper order
- Call cleanup() at end of run loop and in destructor
- Ensure cleanup is only called once per GameEngine instance
Also includes:
- Fix audio ::stop() calls (already in place, OpenAL warning is benign)
- Add Caption support for x, y keywords (e.g. Caption("text", x=5, y=10))
- Refactor UIDrawable_methods.h into UIBase.h for better organization
- Move UIEntity-specific implementations to UIEntityPyMethods.h
Author: John McCardle <mccardle.john@gmail.com>
feat: stabilize test suite and add UIDrawable methods
- Add visible, opacity properties to all UI classes (#87, #88)
- Add get_bounds(), move(), resize() methods to UIDrawable (#89, #98)
- Create UIDrawable_methods.h with template implementations
- Fix test termination issues - all tests now exit properly
- Fix test_sprite_texture_swap.py click handler signature
- Fix test_drawable_base.py segfault in headless mode
- Convert audio objects to pointers for cleanup (OpenAL warning persists)
- Remove debug print statements from UICaption
- Special handling for UIEntity to delegate drawable methods to sprite
All test files are now "airtight" - they complete successfully,
terminate on their own, and handle edge cases properly.
Author: John McCardle <mccardle.john@gmail.com>
docs: add Phase 1-3 completion summary
- Document all completed tasks across three phases
- Show before/after API improvements
- Highlight technical achievements
- Outline next steps for Phase 4-7
Author: John McCardle <mccardle.john@gmail.com>
feat: implement mcrfpy.Timer object with pause/resume/cancel capabilities closes #103
- Created PyTimer.h/cpp with object-oriented timer interface
- Enhanced PyTimerCallable with pause/resume state tracking
- Added timer control methods: pause(), resume(), cancel(), restart()
- Added timer properties: interval, remaining, paused, active, callback
- Fixed timing logic to prevent rapid catch-up after resume
- Timer objects automatically register with game engine
- Added comprehensive test demonstrating all functionality
Author: John McCardle <mccardle.john@gmail.com>
feat(Color): add helper methods from_hex, to_hex, lerp closes #94
- Add Color.from_hex(hex_string) class method for creating colors from hex
- Support formats: #RRGGBB, RRGGBB, #RRGGBBAA, RRGGBBAA
- Add color.to_hex() to convert Color to hex string
- Add color.lerp(other, t) for smooth color interpolation
- Comprehensive test coverage for all methods
Author: John McCardle <mccardle.john@gmail.com>
fix: properly configure UTF-8 encoding for Python stdio
- Use PyConfig to set stdio_encoding="UTF-8" during initialization
- Set stdio_errors="surrogateescape" for robust handling
- Configure in both init_python() and init_python_with_config()
- Cleaner solution than wrapping streams after initialization
- Fixes UnicodeEncodeError when printing unicode characters
Author: John McCardle <mccardle.john@gmail.com>
feat(Vector): implement arithmetic operations closes #93
- Add PyNumberMethods with add, subtract, multiply, divide, negate, absolute
- Add rich comparison for equality/inequality checks
- Add boolean check (zero vector is False)
- Implement vector methods: magnitude(), normalize(), dot(), distance_to(), angle(), copy()
- Fix UIDrawable::get_click() segfault when click_callable is null
- Comprehensive test coverage for all arithmetic operations
Author: John McCardle <mccardle.john@gmail.com>
feat: Complete position argument standardization for all UI classes
- Frame and Sprite now support pos keyword override
- Entity now accepts x,y arguments (was pos-only before)
- All UI classes now consistently support:
- (x, y) positional
- ((x, y)) tuple
- x=x, y=y keywords
- pos=(x,y) keyword
- pos=Vector keyword
- Improves API consistency and flexibility
Author: John McCardle <mccardle.john@gmail.com>
feat: Standardize position arguments across all UI classes
- Create PyPositionHelper for consistent position parsing
- Grid.at() now accepts (x,y), ((x,y)), x=x, y=y, pos=(x,y)
- Caption now accepts x,y args in addition to pos
- Grid init fully supports keyword arguments
- Maintain backward compatibility for all formats
- Consistent error messages across classes
Author: John McCardle <mccardle.john@gmail.com>
feat: Add Entity.die() method for lifecycle management closes #30
- Remove entity from its grid's entity list
- Clear grid reference after removal
- Safe to call multiple times (no-op if not on grid)
- Works with shared_ptr entity management
Author: John McCardle <mccardle.john@gmail.com>
perf: Skip out-of-bounds entities during Grid rendering closes #52
- Add visibility bounds check in entity render loop
- Skip entities outside view with 1 cell margin
- Improves performance for large grids with many entities
- Bounds check considers zoom and pan settings
Author: John McCardle <mccardle.john@gmail.com>
verify: Sprite texture swapping functionality closes #19
- Texture property getter/setter already implemented
- Position/scale preservation during swap confirmed
- Type validation for texture assignment working
- Tests verify functionality is complete
Author: John McCardle <mccardle.john@gmail.com>
feat: Grid size tuple support closes #90
- Add grid_size keyword parameter to Grid.__init__
- Accept tuple or list of two integers
- Override grid_x/grid_y if grid_size provided
- Maintain backward compatibility
- Add comprehensive test coverage
Author: John McCardle <mccardle.john@gmail.com>
feat: Phase 1 - safe constructors and _Drawable foundation
Closes #7 - Make all UI class constructors safe:
- Added safe default constructors for UISprite, UIGrid, UIEntity, UICaption
- Initialize all members to predictable values
- Made Python init functions accept no arguments
- Added x,y properties to UIEntity
Closes #71 - Create _Drawable Python base class:
- Created PyDrawable.h/cpp with base type (not yet inherited by UI types)
- Registered in module initialization
Closes #87 - Add visible property:
- Added bool visible=true to UIDrawable base class
- All render methods check visibility before drawing
Closes #88 - Add opacity property:
- Added float opacity=1.0 to UIDrawable base class
- UICaption and UISprite apply opacity to alpha channel
Closes #89 - Add get_bounds() method:
- Virtual method returns sf::FloatRect(x,y,w,h)
- Implemented in Frame, Caption, Sprite, Grid
Closes #98 - Add move() and resize() methods:
- move(dx,dy) for relative movement
- resize(w,h) for absolute sizing
- Caption resize is no-op (size controlled by font)
Author: John McCardle <mccardle.john@gmail.com>
docs: comprehensive alpha_streamline_2 plan and strategic vision
- Add 7-phase development plan for alpha_streamline_2 branch
- Define architectural dependencies and critical path
- Identify new issues needed (Timer objects, event system, etc.)
- Add strategic vision document with 3 transformative directions
- Timeline: 10-12 weeks to solid Beta foundation
Author: John McCardle <mccardle.john@gmail.com>
feat(Grid): flexible at() method arguments
- Support tuple argument: grid.at((x, y))
- Support keyword arguments: grid.at(x=5, y=3)
- Support pos keyword: grid.at(pos=(2, 8))
- Maintain backward compatibility with grid.at(x, y)
- Add comprehensive error handling for invalid arguments
Improves API ergonomics and Python-like flexibility
|