McRogueFace/src/PyAnimation.cpp

273 lines
9.7 KiB
C++
Raw Normal View History

Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
#include "PyAnimation.h"
#include "McRFPy_API.h"
#include "UIDrawable.h"
#include "UIFrame.h"
#include "UICaption.h"
#include "UISprite.h"
#include "UIGrid.h"
#include "UIEntity.h"
#include "UI.h" // For the PyTypeObject definitions
#include <cstring>
PyObject* PyAnimation::create(PyTypeObject* type, PyObject* args, PyObject* kwds) {
PyAnimationObject* self = (PyAnimationObject*)type->tp_alloc(type, 0);
if (self != NULL) {
// Will be initialized in init
}
return (PyObject*)self;
}
int PyAnimation::init(PyAnimationObject* self, PyObject* args, PyObject* kwds) {
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
static const char* keywords[] = {"property", "target", "duration", "easing", "delta", "callback", nullptr};
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
const char* property_name;
PyObject* target_value;
float duration;
const char* easing_name = "linear";
int delta = 0;
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
PyObject* callback = nullptr;
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
if (!PyArg_ParseTupleAndKeywords(args, kwds, "sOf|spO", const_cast<char**>(keywords),
&property_name, &target_value, &duration, &easing_name, &delta, &callback)) {
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
return -1;
}
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
// Validate callback is callable if provided
if (callback && callback != Py_None && !PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "callback must be callable");
return -1;
}
// Convert None to nullptr for C++
if (callback == Py_None) {
callback = nullptr;
}
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
// Convert Python target value to AnimationValue
AnimationValue animValue;
if (PyFloat_Check(target_value)) {
animValue = static_cast<float>(PyFloat_AsDouble(target_value));
}
else if (PyLong_Check(target_value)) {
animValue = static_cast<int>(PyLong_AsLong(target_value));
}
else if (PyList_Check(target_value)) {
// List of integers for sprite animation
std::vector<int> indices;
Py_ssize_t size = PyList_Size(target_value);
for (Py_ssize_t i = 0; i < size; i++) {
PyObject* item = PyList_GetItem(target_value, i);
if (PyLong_Check(item)) {
indices.push_back(PyLong_AsLong(item));
} else {
PyErr_SetString(PyExc_TypeError, "Sprite animation list must contain only integers");
return -1;
}
}
animValue = indices;
}
else if (PyTuple_Check(target_value)) {
Py_ssize_t size = PyTuple_Size(target_value);
if (size == 2) {
// Vector2f
float x = PyFloat_AsDouble(PyTuple_GetItem(target_value, 0));
float y = PyFloat_AsDouble(PyTuple_GetItem(target_value, 1));
animValue = sf::Vector2f(x, y);
}
else if (size == 3 || size == 4) {
// Color (RGB or RGBA)
int r = PyLong_AsLong(PyTuple_GetItem(target_value, 0));
int g = PyLong_AsLong(PyTuple_GetItem(target_value, 1));
int b = PyLong_AsLong(PyTuple_GetItem(target_value, 2));
int a = size == 4 ? PyLong_AsLong(PyTuple_GetItem(target_value, 3)) : 255;
animValue = sf::Color(r, g, b, a);
}
else {
PyErr_SetString(PyExc_ValueError, "Tuple must have 2 elements (vector) or 3-4 elements (color)");
return -1;
}
}
else if (PyUnicode_Check(target_value)) {
// String for text animation
const char* str = PyUnicode_AsUTF8(target_value);
animValue = std::string(str);
}
else {
PyErr_SetString(PyExc_TypeError, "Target value must be float, int, list, tuple, or string");
return -1;
}
// Get easing function
EasingFunction easingFunc = EasingFunctions::getByName(easing_name);
// Create the Animation
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
self->data = std::make_shared<Animation>(property_name, animValue, duration, easingFunc, delta != 0, callback);
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
return 0;
}
void PyAnimation::dealloc(PyAnimationObject* self) {
self->data.reset();
Py_TYPE(self)->tp_free((PyObject*)self);
}
PyObject* PyAnimation::get_property(PyAnimationObject* self, void* closure) {
return PyUnicode_FromString(self->data->getTargetProperty().c_str());
}
PyObject* PyAnimation::get_duration(PyAnimationObject* self, void* closure) {
return PyFloat_FromDouble(self->data->getDuration());
}
PyObject* PyAnimation::get_elapsed(PyAnimationObject* self, void* closure) {
return PyFloat_FromDouble(self->data->getElapsed());
}
PyObject* PyAnimation::get_is_complete(PyAnimationObject* self, void* closure) {
return PyBool_FromLong(self->data->isComplete());
}
PyObject* PyAnimation::get_is_delta(PyAnimationObject* self, void* closure) {
return PyBool_FromLong(self->data->isDelta());
}
PyObject* PyAnimation::start(PyAnimationObject* self, PyObject* args) {
PyObject* target_obj;
if (!PyArg_ParseTuple(args, "O", &target_obj)) {
return NULL;
}
// Check type by comparing type names
const char* type_name = Py_TYPE(target_obj)->tp_name;
if (strcmp(type_name, "mcrfpy.Frame") == 0) {
PyUIFrameObject* frame = (PyUIFrameObject*)target_obj;
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
if (frame->data) {
self->data->start(frame->data);
AnimationManager::getInstance().addAnimation(self->data);
}
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
}
else if (strcmp(type_name, "mcrfpy.Caption") == 0) {
PyUICaptionObject* caption = (PyUICaptionObject*)target_obj;
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
if (caption->data) {
self->data->start(caption->data);
AnimationManager::getInstance().addAnimation(self->data);
}
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
}
else if (strcmp(type_name, "mcrfpy.Sprite") == 0) {
PyUISpriteObject* sprite = (PyUISpriteObject*)target_obj;
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
if (sprite->data) {
self->data->start(sprite->data);
AnimationManager::getInstance().addAnimation(self->data);
}
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
}
else if (strcmp(type_name, "mcrfpy.Grid") == 0) {
PyUIGridObject* grid = (PyUIGridObject*)target_obj;
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
if (grid->data) {
self->data->start(grid->data);
AnimationManager::getInstance().addAnimation(self->data);
}
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
}
else if (strcmp(type_name, "mcrfpy.Entity") == 0) {
// Special handling for Entity since it doesn't inherit from UIDrawable
PyUIEntityObject* entity = (PyUIEntityObject*)target_obj;
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
if (entity->data) {
self->data->startEntity(entity->data);
AnimationManager::getInstance().addAnimation(self->data);
}
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
}
else {
PyErr_SetString(PyExc_TypeError, "Target must be a Frame, Caption, Sprite, Grid, or Entity");
return NULL;
}
Py_RETURN_NONE;
}
PyObject* PyAnimation::update(PyAnimationObject* self, PyObject* args) {
float deltaTime;
if (!PyArg_ParseTuple(args, "f", &deltaTime)) {
return NULL;
}
bool still_running = self->data->update(deltaTime);
return PyBool_FromLong(still_running);
}
PyObject* PyAnimation::get_current_value(PyAnimationObject* self, PyObject* args) {
AnimationValue value = self->data->getCurrentValue();
// Convert AnimationValue back to Python
return std::visit([](const auto& val) -> PyObject* {
using T = std::decay_t<decltype(val)>;
if constexpr (std::is_same_v<T, float>) {
return PyFloat_FromDouble(val);
}
else if constexpr (std::is_same_v<T, int>) {
return PyLong_FromLong(val);
}
else if constexpr (std::is_same_v<T, std::vector<int>>) {
// This shouldn't happen as we interpolate to int
return PyLong_FromLong(0);
}
else if constexpr (std::is_same_v<T, sf::Color>) {
return Py_BuildValue("(iiii)", val.r, val.g, val.b, val.a);
}
else if constexpr (std::is_same_v<T, sf::Vector2f>) {
return Py_BuildValue("(ff)", val.x, val.y);
}
else if constexpr (std::is_same_v<T, std::string>) {
return PyUnicode_FromString(val.c_str());
}
Py_RETURN_NONE;
}, value);
}
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
PyObject* PyAnimation::complete(PyAnimationObject* self, PyObject* args) {
if (self->data) {
self->data->complete();
}
Py_RETURN_NONE;
}
PyObject* PyAnimation::has_valid_target(PyAnimationObject* self, PyObject* args) {
if (self->data && self->data->hasValidTarget()) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
PyGetSetDef PyAnimation::getsetters[] = {
{"property", (getter)get_property, NULL, "Target property name", NULL},
{"duration", (getter)get_duration, NULL, "Animation duration in seconds", NULL},
{"elapsed", (getter)get_elapsed, NULL, "Elapsed time in seconds", NULL},
{"is_complete", (getter)get_is_complete, NULL, "Whether animation is complete", NULL},
{"is_delta", (getter)get_is_delta, NULL, "Whether animation uses delta mode", NULL},
{NULL}
};
PyMethodDef PyAnimation::methods[] = {
{"start", (PyCFunction)start, METH_VARARGS,
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
"start(target) -> None\n\n"
"Start the animation on a target UI element.\n\n"
"Args:\n"
" target: The UI element to animate (Frame, Caption, Sprite, Grid, or Entity)\n\n"
"Note:\n"
" The animation will automatically stop if the target is destroyed."},
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
{"update", (PyCFunction)update, METH_VARARGS,
"Update the animation by deltaTime (returns True if still running)"},
{"get_current_value", (PyCFunction)get_current_value, METH_NOARGS,
"Get the current interpolated value"},
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 c5e7e8e29835a69f4c50f3c99fd3123012635a9a Update test demos for new Python API and entity system - Update all text input demos to use new Entity constructor signature - Fix pathfinding showcase to work with new entity position handling - Remove entity_waypoints tracking in favor of simplified movement - Delete obsolete exhaustive_api_demo.py (superseded by newer demos) - Adjust entity creation calls to match Entity((x, y), texture, sprite_index) pattern commit 6d29652ae7418745dc24066532454167d447df89 Update animation demo suite with crash fixes and improvements - Add warnings about AnimationManager segfault bug in sizzle_reel_final.py - Create sizzle_reel_final_fixed.py that works around the crash by hiding objects instead of removing them - Increase font sizes for better visibility in demos - Extend demo durations for better showcase of animations - Remove debug prints from animation_sizzle_reel_working.py - Minor cleanup and improvements to all animation demos commit a010e5fa968feaba620dcf2eda44fb9514512151 Update game scripts for new Python API - Convert entity position access from tuple to x/y properties - Update caption size property to font_size - Fix grid boundary checks to use grid_size instead of exceptions - Clean up demo timer on menu exit to prevent callbacks These changes adapt the game scripts to work with the new standardized Python API constructors and property names. commit 9c8d6c459109be883cb8070b8ef83c60bfc1a970 Fix click event z-order handling in PyScene Changed click detection to properly respect z-index by: - Sorting ui_elements in-place when needed (same as render order) - Using reverse iterators to check highest z-index elements first - This ensures top-most elements receive clicks before lower ones commit dcd1b0ca33d46639023221f4d7d52000b947dbdf Add roguelike tutorial implementation files Implement Parts 0-2 of the classic roguelike tutorial adapted for McRogueFace: - Part 0: Basic grid setup and tile rendering - Part 1: Drawing '@' symbol and basic movement - Part 1b: Variant with sprite-based player - Part 2: Entity system and NPC implementation with three movement variants: - part_2.py: Standard implementation - part_2-naive.py: Naive movement approach - part_2-onemovequeued.py: Queued movement system Includes tutorial assets: - tutorial2.png: Tileset for dungeon tiles - tutorial_hero.png: Player sprite sheet commit 6813fb5129738cca2d79c80304834523561ba7fb Standardize Python API constructors and remove PyArgHelpers - Remove PyArgHelpers.h and all macro-based argument parsing - Convert all UI class constructors to use PyArg_ParseTupleAndKeywords - Standardize constructor signatures across UICaption, UIEntity, UIFrame, UIGrid, and UISprite - Replace PYARGHELPER_SINGLE/MULTI macros with explicit argument parsing - Improve error messages and argument validation - Maintain backward compatibility with existing Python code This change improves code maintainability and consistency across the Python API. commit 6f67fbb51efaf70e52fba8c939298dcdff50450a Fix animation callback crashes from iterator invalidation (#119) Resolved segfaults caused by creating new animations from within animation callbacks. The issue was iterator invalidation in AnimationManager::update() when callbacks modified the active animations vector. Changes: - Add deferred animation queue to AnimationManager - New animations created during update are queued and added after - Set isUpdating flag to track when in update loop - Properly handle Animation destructor during callback execution - Add clearCallback() method for safe cleanup scenarios This fixes the "free(): invalid pointer" and "malloc(): unaligned fastbin chunk detected" errors that occurred with rapid animation creation in callbacks. commit eb88c7b3aab3da519db7569106c34f3510b6e963 Add animation completion callbacks (#119) Implement callbacks that fire when animations complete, enabling direct causality between animation end and game state changes. This eliminates race conditions from parallel timer workarounds. - Add optional callback parameter to Animation constructor - Callbacks execute synchronously when animation completes - Proper Python reference counting with GIL safety - Callbacks receive (anim, target) parameters (currently None) - Exception handling prevents crashes from Python errors Example usage: ```python def on_complete(anim, target): player_moving = False anim = mcrfpy.Animation("x", 300.0, 1.0, "easeOut", callback=on_complete) anim.start(player) ``` closes #119 commit 9fb428dd0176a4d7cfad09deb7509d8aa5562868 Update ROADMAP with GitHub issue numbers (#111-#125) Added issue numbers from GitHub tracker to roadmap items: - #111: Grid Click Events Broken in Headless - #112: Object Splitting Bug (Python type preservation) - #113: Batch Operations for Grid - #114: CellView API - #115: SpatialHash Implementation - #116: Dirty Flag System - #117: Memory Pool for Entities - #118: Scene as Drawable - #119: Animation Completion Callbacks - #120: Animation Property Locking - #121: Timer Object System - #122: Parent-Child UI System - #123: Grid Subgrid System - #124: Grid Point Animation - #125: GitHub Issues Automation Also updated existing references: - #101/#110: Constructor standardization - #109: Vector class indexing Note: Tutorial-specific items and Python-implementable features (input queue, collision reservation) are not tracked as engine issues. commit 062e4dadc42833bf5a3559e5d7c4ceb4abb7e9c0 Fix animation segfaults with RAII weak_ptr implementation Resolved two critical segmentation faults in AnimationManager: 1. Race condition when creating multiple animations in timer callbacks 2. Exit crash when animations outlive their target objects Changes: - Replace raw pointers with std::weak_ptr for automatic target invalidation - Add Animation::complete() to jump animations to final value - Add Animation::hasValidTarget() to check if target still exists - Update AnimationManager to auto-remove invalid animations - Add AnimationManager::clear() call to GameEngine::cleanup() - Update Python bindings to pass shared_ptr instead of raw pointers This ensures animations can never reference destroyed objects, following proper RAII principles. Tested with sizzle_reel_final.py and stress tests creating/destroying hundreds of animated objects. commit 98fc49a978ec792ee6096f40fd4e19841b8ec6a3 Directory structure cleanup and organization overhaul
2025-07-15 21:30:49 -04:00
{"complete", (PyCFunction)complete, METH_NOARGS,
"complete() -> None\n\n"
"Complete the animation immediately by jumping to the final value."},
{"hasValidTarget", (PyCFunction)has_valid_target, METH_NOARGS,
"hasValidTarget() -> bool\n\n"
"Check if the animation still has a valid target.\n\n"
"Returns:\n"
" True if the target still exists, False if it was destroyed."},
Squashed commit of the following: [interpreter_mode] closes #63 closes #69 closes #59 closes #47 closes #2 closes #3 closes #33 closes #27 closes #73 closes #74 closes #78 I'd like to thank Claude Code for ~200-250M total tokens and 500-700k output tokens 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> commit 9bd1561bfc9b02d8db71b5d9390ef2631fac5b28 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 11:20:07 2025 -0400 Alpha 0.1 release - Move RenderTexture (#6) out of alpha requirements, I don't need it that badly - alpha blockers resolved: * Animation system (#59) * Z-order rendering (#63) * Python Sequence Protocol (#69) * New README (#47) * Removed deprecated methods (#2, #3) 🍾 McRogueFace 0.1.0 commit 43321487eb762e17639ba4113322b6f5df71a8d9 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:36:09 2025 -0400 Issue #63 (z-order rendering) complete - Archive z-order test files commit 90c318104bfb31ab4c741702e6661e6bf7e4d19c Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 10:34:06 2025 -0400 Fix Issue #63: Implement z-order rendering with dirty flag optimization - Add dirty flags to PyScene and UIFrame to track when sorting is needed - Implement lazy sorting - only sort when z_index changes or elements are added/removed - Make Frame children respect z_index (previously rendered in insertion order only) - Update UIDrawable::set_int to notify when z_index changes - Mark collections dirty on append, remove, setitem, and slice operations - Remove per-frame vector copy in PyScene::render for better performance commit e4482e7189095d88eec1e2ec55e01e271ed4f55f Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 01:58:03 2025 -0400 Implement complete Python Sequence Protocol for collections (closes #69) Major implementation of the full sequence protocol for both UICollection and UIEntityCollection, making them behave like proper Python sequences. Core Features Implemented: - __setitem__ (collection[i] = value) with type validation - __delitem__ (del collection[i]) with proper cleanup - __contains__ (item in collection) by C++ pointer comparison - __add__ (collection + other) returns Python list - __iadd__ (collection += other) with full validation before modification - Negative indexing support throughout - Complete slice support (getting, setting, deletion) - Extended slices with step \!= 1 - index() and count() methods - Type safety enforced for all operations UICollection specifics: - Accepts Frame, Caption, Sprite, and Grid objects only - Preserves z_index when replacing items - Auto-assigns z_index on append (existing behavior maintained) UIEntityCollection specifics: - Accepts Entity objects only - Manages grid references on add/remove/replace - Uses std::list iteration with std::advance() Also includes: - Default value support for constructors: - Caption accepts None for font (uses default_font) - Grid accepts None for texture (uses default_texture) - Sprite accepts None for texture (uses default_texture) - Entity accepts None for texture (uses default_texture) This completes Issue #69, removing it as an Alpha Blocker. commit 70cf44f8f044ed49544dd9444245115187d3b318 Author: John McCardle <mccardle.john@gmail.com> Date: Sat Jul 5 00:56:42 2025 -0400 Implement comprehensive animation system (closes #59) - Add Animation class with 30+ easing functions (linear, ease in/out, quad, cubic, elastic, bounce, etc.) - Add property system to all UI classes for animation support: - UIFrame: position, size, colors (including individual r/g/b/a components) - UICaption: position, size, text, colors - UISprite: position, scale, sprite_number (with sequence support) - UIGrid: position, size, camera center, zoom - UIEntity: position, sprite properties - Create AnimationManager singleton for frame-based updates - Add Python bindings through PyAnimation wrapper - Support for delta animations (relative values) - Fix segfault when running scripts directly (mcrf_module initialization) - Fix headless/windowed mode behavior to respect --headless flag - Animations run purely in C++ without Python callbacks per frame All UI properties are now animatable with smooth interpolation and professional easing curves. commit 05bddae5112f2b5949a9d2b32dd3dc2bf4656837 Author: John McCardle <mccardle.john@gmail.com> Date: Fri Jul 4 06:59:02 2025 -0400 Update comprehensive documentation for Alpha release (Issue #47) - Completely rewrote README.md to reflect current features - Updated GitHub Pages documentation site with: - Modern landing page highlighting Crypt of Sokoban - Comprehensive API reference (2700+ lines) with exhaustive examples - Updated getting-started guide with installation and first game tutorial - 8 detailed tutorials covering all major game systems - Quick reference cheat sheet for common operations - Generated documentation screenshots showing UI elements - Fixed deprecated API references and added new features - Added automation API documentation - Included Python 3.12 requirement and platform-specific instructions Note: Text rendering in headless mode has limitations for screenshots commit af6a5e090b9f52e3328294a988bdc18ff4b6c981 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:58 2025 -0400 Update ROADMAP.md to reflect completion of Issues #2 and #3 - Marked both issues as completed with the removal of deprecated action system - Updated open issue count from ~50 to ~48 - These were both Alpha blockers, bringing us closer to release commit 281800cd2345cc57024c9bcdd18860d2bb8db027 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:43:22 2025 -0400 Remove deprecated registerPyAction/registerInputAction system (closes #2, closes #3) This is our largest net-negative commit yet\! Removed the entire deprecated action registration system that provided unnecessary two-step indirection: keyboard → action string → Python callback Removed components: - McRFPy_API::_registerPyAction() and _registerInputAction() methods - McRFPy_API::callbacks map for storing Python callables - McRFPy_API::doAction() method for executing callbacks - ACTIONPY macro from Scene.h for detecting "_py" suffixed actions - Scene::registerActionInjected() and unregisterActionInjected() methods - tests/api_registerPyAction_issue2_test.py (tested deprecated functionality) The game now exclusively uses keypressScene() for keyboard input handling, which is simpler and more direct. Also commented out the unused _camFollow function that referenced non-existent do_camfollow variable. commit cc8a7d20e8ea5c7b32cad2565cc9e85e27bef147 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:59 2025 -0400 Clean up temporary test files commit ff83fd8bb159cd2e7d9056379576d147bd99656b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:13:46 2025 -0400 Update ROADMAP.md to reflect massive progress today - Fixed 12+ critical bugs in a single session - Implemented 3 missing features (Entity.index, EntityCollection.extend, sprite validation) - Updated Phase 1 progress showing 11 of 12 items complete - Added detailed summary of today's achievements with issue numbers - Emphasized test-driven development approach used throughout commit dae400031fe389025955bee423f9b327fd596b1d Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:12:29 2025 -0400 Remove deprecated player_input and turn-based functions for Issue #3 Removed the commented-out player_input(), computerTurn(), and playerTurn() functions that were part of the old turn-based system. These are no longer needed as input is now handled through Scene callbacks. Partial fix for #3 commit cb0130b46eb873d7a38b4647b0f3d2698f234ab9 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:09:06 2025 -0400 Implement sprite index validation for Issue #33 Added validation to prevent setting sprite indices outside the valid range for a texture. The implementation: - Adds getSpriteCount() method to PyTexture to expose total sprites - Validates sprite_number setter to ensure index is within bounds - Provides clear error messages showing valid range - Works for both Sprite and Entity objects closes #33 commit 1e7f5e9e7e9e4d6e9494ba6c19f1ae0c5282b449 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:05:47 2025 -0400 Implement EntityCollection.extend() method for Issue #27 Added extend() method to EntityCollection that accepts any iterable of Entity objects and adds them all to the collection. The method: - Accepts lists, tuples, generators, or any iterable - Validates all items are Entity objects - Sets the grid association for each added entity - Properly handles errors and empty iterables closes #27 commit 923350137d148c56e617eae966467c77617c131b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 21:02:14 2025 -0400 Implement Entity.index() method for Issue #73 Added index() method to Entity class that returns the entity's position in its parent grid's entity collection. This enables proper entity removal patterns using entity.index(). commit 6134869371cf4e7ae79515690960a563fd0db40e Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:41:03 2025 -0400 Add validation to keypressScene() for non-callable arguments Added PyCallable_Check validation to ensure keypressScene() only accepts callable objects. Now properly raises TypeError with a clear error message when passed non-callable arguments like strings, numbers, None, or dicts. commit 4715356b5e760b9fd8f2087565adaab2fb94573b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:31:36 2025 -0400 Fix Sprite texture setter 'error return without exception set' Implemented the missing UISprite::set_texture method to properly: - Validate the input is a Texture instance - Update the sprite's texture using setTexture() - Return appropriate error messages for invalid inputs The setter now works correctly and no longer returns -1 without setting an exception. commit 6dd1cec600efd3b9f44f67968a23c88e05e19ec8 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 20:27:32 2025 -0400 Fix Entity property setters and PyVector implementation Fixed the 'new style getargs format' error in Entity property setters by: - Implementing PyObject_to_sfVector2f/2i using PyVector::from_arg - Adding proper error checking in Entity::set_position - Implementing PyVector get_member/set_member for x/y properties - Fixing PyVector::from_arg to handle non-tuple arguments correctly Now Entity.pos and Entity.sprite_number setters work correctly with proper type validation. commit f82b861bcdffa9d3df69bd29c7c88be2a30c9ba5 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:48:33 2025 -0400 Fix Issue #74: Add missing Grid.grid_y property Added individual grid_x and grid_y getter properties to the Grid class to complement the existing grid_size property. This allows direct access to grid dimensions and fixes error messages that referenced these properties before they existed. closes #74 commit 59e6f8d53dda6938914ce854249925b3ce7f41f4 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:42:32 2025 -0400 Fix Issue #78: Middle mouse click no longer sends 'C' keyboard event The bug was caused by accessing event.key.code on a mouse event without checking the event type first. Since SFML uses a union for events, this read garbage data. The middle mouse button value (2) coincidentally matched the keyboard 'C' value (2), causing the spurious keyboard event. Fixed by adding event type check before accessing key-specific fields. Only keyboard events (KeyPressed/KeyReleased) now trigger key callbacks. Test added to verify middle clicks no longer generate keyboard events. Closes #78 commit 1c71d8d4f743900bf2bef097b3d1addf64dbe04a Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:36:15 2025 -0400 Fix Grid to support None/null texture and fix error message bug - Allow Grid to be created with None as texture parameter - Use default cell dimensions (16x16) when no texture provided - Skip sprite rendering when texture is null, but still render colors - Fix issue #77: Corrected copy/paste error in Grid.at() error messages - Grid now functional for color-only rendering and entity positioning Test created to verify Grid works without texture, showing colored cells. Closes #77 commit 18cfe93a44a9f4dcde171f442dc3d56711a0906b Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 19:25:49 2025 -0400 Fix --exec interactive prompt bug and create comprehensive test suite Major fixes: - Fixed --exec entering Python REPL instead of game loop - Resolved screenshot transparency issue (requires timer callbacks) - Added debug output to trace Python initialization Test suite created: - 13 comprehensive tests covering all Python-exposed methods - Tests use timer callback pattern for proper game loop interaction - Discovered multiple critical bugs and missing features Critical bugs found: - Grid class segfaults on instantiation (blocks all Grid functionality) - Issue #78 confirmed: Middle mouse click sends 'C' keyboard event - Entity property setters have argument parsing errors - Sprite texture setter returns improper error - keypressScene() segfaults on non-callable arguments Documentation updates: - Updated CLAUDE.md with testing guidelines and TDD practices - Created test reports documenting all findings - Updated ROADMAP.md with test results and new priorities The Grid segfault is now the highest priority as it blocks all Grid-based functionality. commit 9ad0b6850d5f77d93c22eb52cbeb4d8442e77918 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 15:55:24 2025 -0400 Update ROADMAP.md to reflect Python interpreter and automation API progress - Mark #32 (Python interpreter behavior) as 90% complete - All major Python flags implemented: -h, -V, -c, -m, -i - Script execution with proper sys.argv handling works - Only stdin (-) support missing - Note that new automation API enables: - Automated UI testing capabilities - Demo recording and playback - Accessibility testing support - Flag issues #53 and #45 as potentially aided by automation API commit 7ec4698653383cb28f0115d1abf1db0a500257ec Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:57:59 2025 -0400 Update ROADMAP.md to remove closed issues - Remove #72 (iterator improvements - closed) - Remove #51 (UIEntity derive from UIDrawable - closed) - Update issue counts: 64 open issues from original 78 - Update dependencies and references to reflect closed issues - Clarify that core iterators are complete, only grid points remain commit 68c1a016b0e1d1b438c926f5576e5650b9617fe1 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 14:27:01 2025 -0400 Implement --exec flag and PyAutoGUI-compatible automation API - Add --exec flag to execute multiple scripts before main program - Scripts are executed in order and share Python interpreter state - Implement full PyAutoGUI-compatible automation API in McRFPy_Automation - Add screenshot, mouse control, keyboard input capabilities - Fix Python initialization issues when multiple scripts are loaded - Update CommandLineParser to handle --exec with proper sys.argv management - Add comprehensive examples and documentation This enables automation testing by allowing test scripts to run alongside games using the same Python environment. The automation API provides event injection into the SFML render loop for UI testing. Closes #32 partially (Python interpreter emulation) References automation testing requirements commit 763fa201f041a0d32bc45695c1bbbac5590adba0 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 10:43:17 2025 -0400 Python command emulation commit a44b8c93e938ca0c58cff7e5157293d97d182a39 Author: John McCardle <mccardle.john@gmail.com> Date: Thu Jul 3 09:42:46 2025 -0400 Prep: Cleanup for interpreter mode
2025-07-05 12:04:20 -04:00
{NULL}
};