Commit graph

72 commits

Author SHA1 Message Date
322beeaf78 add __ne__ support to enum types for input 2026-02-06 21:43:52 -05:00
992ea781cb Voxel functionality extension 2026-02-05 12:52:18 -05:00
3e6b6a5847 voxel example 2026-02-05 10:49:31 -05:00
b85f225789 billboards 2026-02-04 20:47:51 -05:00
544c44ca31 glTF model loading 2026-02-04 19:35:48 -05:00
f4c9db8436 3D entities 2026-02-04 17:45:12 -05:00
63008bdefd pathfinding on heightmap 2026-02-04 16:36:21 -05:00
e277663ba0 3D viewport, milestone 1 2026-02-04 13:33:14 -05:00
d8fec5fea0 DiscreteMap class - mask for operations or uint8 tile data 2026-02-03 20:36:42 -05:00
2fb29a102e Animation and Scene clean up functions. Playground build target 2026-02-01 21:17:29 -05:00
3b27401f29 Remove debugging output 2026-02-01 16:40:23 -05:00
c5cc022aa2 Add SDL2+OpenGL ES 2 renderer backend for Emscripten/WebGL
Implements Phase 1 of renderer abstraction plan:
- SDL2Types.h: SFML-compatible type stubs in sf:: namespace
- SDL2Renderer.h/cpp: OpenGL ES 2 rendering implementation
- EmscriptenStubs.cpp: Stubs for missing POSIX functions (wait3, wait4, wcsftime)

Build system changes:
- Add MCRF_SDL2 compile-time backend selection
- Add Emscripten SDL2 link options (-sUSE_SDL=2, -sFULL_ES2=1)
- Fix LONG_BIT mismatch for Emscripten in pyport.h

Code changes for SDL2/headless compatibility:
- Guard ImGui includes with !MCRF_HEADLESS && !MCRF_SDL2
- Defer GL shader initialization until after context creation

Current status: Python runs in browser, rendering WIP (canvas sizing issues)

Build commands:
  emcmake cmake -DMCRF_SDL2=ON -B build-emscripten
  emmake make -C build-emscripten

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 11:13:15 -05:00
8c3128e29c WASM Python integration milestone - game.py runs in browser
Major milestone for issue #158 (Emscripten/WebAssembly build target):
- Python 3.14 successfully initializes and runs in WASM
- mcrfpy module loads and works correctly
- Game scripts execute with full level generation
- Entities (boulders, rats, cyclops, spawn points) placed correctly

Key changes:
- CMakeLists.txt: Add 2MB stack, Emscripten link options, preload files
- platform.h: Add WASM-specific implementations for executable paths
- HeadlessTypes.h: Make Texture/Font/Sound stubs return success
- CommandLineParser.cpp: Guard filesystem operations for WASM
- McRFPy_API.cpp: Add WASM path configuration, debug output
- game.py: Make 'code' module import optional (not available in WASM)
- wasm_stdlib/: Add minimal Python stdlib for WASM (~4MB)

Build with: emmake make (from build-emscripten/)
Test with: node mcrogueface.js

Next steps:
- Integrate VRSFML for actual WebGL rendering
- Create HTML page to host WASM build
- Test in actual browsers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 05:15:11 -05:00
7621ae35bb Add MCRF_HEADLESS compile-time build option for #158
This commit enables McRogueFace to compile without SFML dependencies
when built with -DMCRF_HEADLESS, a prerequisite for Emscripten/WebAssembly
support.

Changes:
- Add src/platform/HeadlessTypes.h (~900 lines of SFML type stubs)
- Consolidate all SFML includes through src/Common.h (15 files fixed)
- Wrap ImGui-SFML with #ifndef MCRF_HEADLESS guards
- Disable debug console/explorer in headless builds
- Add comprehensive research document: docs/EMSCRIPTEN_RESEARCH.md

The headless build compiles successfully but uses stub implementations
that return failure/no-op. This proves the abstraction boundary is clean
and enables future work on alternative backends (VRSFML, Emscripten).

What still works in headless mode:
- Python interpreter and script execution
- libtcod integrations (pathfinding, FOV, noise, BSP, heightmaps)
- Timer system and scene management
- All game logic and data structures

Build commands:
  Normal:   make
  Headless: cmake .. -DCMAKE_CXX_FLAGS="-DMCRF_HEADLESS" && make

Addresses #158

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 23:09:07 -05:00
486087b9cb Shaders 2026-01-25 21:04:01 -05:00
4ead2f25fe Fix #215: Replace mcrfpy.libtcod with mcrfpy.bresenham()
- Remove mcrfpy.libtcod submodule entirely
- Add mcrfpy.bresenham(start, end, include_start=True, include_end=True)
  - Accepts tuples or Vector objects for positions
  - Returns list of (x, y) tuples along the line
- compute_fov() was redundant with Grid.compute_fov()
- line() functionality now available as top-level bresenham()

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 00:10:13 -05:00
257e52327b Fix #219: Add threading support with mcrfpy.lock() context manager
Enables background Python threads to safely modify UI objects by
synchronizing with the render loop at frame boundaries.

Implementation:
- FrameLock class provides mutex/condvar synchronization
- GIL released during window.display() allowing background threads to run
- Safe window opens between frames for synchronized UI updates
- mcrfpy.lock() context manager blocks until safe window, then executes
- Main thread detection: lock() is a no-op when called from callbacks
  or script initialization (already synchronized)

Usage:
    import threading
    import mcrfpy

    def background_worker():
        with mcrfpy.lock():  # Blocks until safe
            player.x = new_x  # Safe to modify UI

    threading.Thread(target=background_worker).start()

The lock works transparently from any context - background threads get
actual synchronization, main thread calls (callbacks, init) get no-op.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 23:37:49 -05:00
4bf590749c Alignment: reactive or automatically calculated repositioning of UIDrawables on their parent 2026-01-13 20:40:34 -05:00
8628ac164b BSP: add room adjacency graph for corridor generation (closes #210)
New features:
- bsp.adjacency[i] returns tuple of neighbor leaf indices
- bsp.get_leaf(index) returns BSPNode by leaf index (O(1) lookup)
- node.leaf_index returns this leaf's index (0..n-1) or None
- node.adjacent_tiles[j] returns tuple of Vector wall tiles bordering neighbor j

Implementation details:
- Lazy-computed adjacency cache with generation-based invalidation
- O(n²) pairwise adjacency check on first access
- Wall tiles computed per-direction (not symmetric) for correct perspective
- Supports 'in' operator: `5 in leaf.adjacent_tiles`

Code review fixes applied:
- split_once now increments generation to invalidate cache
- Wall tile cache uses (self, neighbor) key, not symmetric
- Added sq_contains for 'in' operator support
- Documented wall tile semantics (tiles on THIS leaf's boundary)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 23:43:57 -05:00
e5d0eb4847 Noise, combination, and sampling: first pass at #207, #208, #194, #209 2026-01-12 19:01:20 -05:00
8699bba9e6 BSP: add Binary Space Partitioning for procedural dungeon generation
Implements #202, #203, #204, #205; partially implements #206:
- BSP class: core tree structure with bounds, split_once, split_recursive, clear
- BSPNode class: lightweight node reference with bounds, level, is_leaf,
  split_horizontal, split_position; navigation via left/right/parent/sibling;
  contains() and center() methods
- Traversal enum: PRE_ORDER, IN_ORDER, POST_ORDER, LEVEL_ORDER, INVERTED_LEVEL_ORDER
- BSP iteration: leaves() for leaf nodes only, traverse(order) for all nodes
- BSP query: find(pos) returns deepest node containing position
- BSP.to_heightmap(): converts BSP to HeightMap with select, shrink, value options

Note: #206's BSPMap subclass deferred - to_heightmap returns plain HeightMap.
The HeightMap already has all necessary operations (inverse, threshold, etc.)
for procedural generation workflows.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 07:02:54 -05:00
c095be4b73 HeightMap: core class with scalar operations (closes #193)
Implement the foundational HeightMap class for procedural generation:

- HeightMap(size, fill=0.0) constructor with libtcod backend
- Immutable size property after construction
- Scalar operations returning self for method chaining:
  - fill(value), clear()
  - add_constant(value), scale(factor)
  - clamp(min=0.0, max=1.0), normalize(min=0.0, max=1.0)

Includes procedural generation spec document and unit tests.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 20:07:55 -05:00
b32f5af28c UIGridPathfinding: clear and separate A-star and Djikstra path systems 2026-01-10 22:09:45 -05:00
9eacedc624 Input Enums instead of strings. 2026-01-10 21:31:20 -05:00
d6ef29f3cd Grid code quality improvements
* Grid [x, y] subscript - convenience for `.at()`
* Extract UIEntityCollection - cleanup of UIGrid.cpp
* Thread-safe type cache - PyTypeCache
* Exception-safe extend() - validate before modify
2026-01-10 08:37:31 -05:00
a77ac6c501 Monkey Patch support + Robust callback tracking
McRogueFace needs to accept callable objects (properties on C++ objects)
and also support subclassing (getattr on user objects). Only direct
properties were supported previously, now shadowing a callback by name
will allow custom objects to "just work".
- Added CallbackCache struct and is_python_subclass flag to UIDrawable.h
- Created metaclass for tracking class-level callback changes
- Updated all UI type init functions to detect subclasses
- Modified PyScene.cpp event dispatch to try subclass methods
2026-01-09 21:37:23 -05:00
1438044c6a mingw toolchain and final fixes for Windows. Closes #162 2026-01-08 21:16:27 -05:00
75127ac9d1 mcrfpy.Mouse: a new class built for symmetry with mcrfpy.Keyboard. Closes #186 2026-01-06 21:39:01 -05:00
b0b17f4633 timer fixes: timers managed by engine can run in the background. Closes #180 2026-01-06 20:13:51 -05:00
2c20455003 support for Scene object as parent, from Python: closes #183 2026-01-06 14:04:53 -05:00
f9b6cdef1c Python API improvements: Vectors, bounds, window singleton, hidden types
- #177: GridPoint.grid_pos property returns (x, y) tuple
- #179: Grid.grid_size returns Vector instead of tuple
- #181: Grid.center returns Vector instead of tuple
- #182: Caption.size/w/h read-only properties for text dimensions
- #184: mcrfpy.window singleton for window access
- #185: Removed get_bounds() method, use .bounds property instead
- #188: bounds/global_bounds return (pos, size) as pair of Vectors
- #189: Hide internal types from module namespace (iterators, collections)

Also fixed critical bug: Changed static PyTypeObject to inline in headers
to ensure single instance across translation units (was causing segfaults).

Closes #177, closes #179, closes #181, closes #182, closes #184, closes #185, closes #188, closes #189

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 23:00:48 -05:00
d878c8684d Easing functions as enum 2026-01-04 12:59:28 -05:00
5d41292bf6 Timer refactor: stopwatch-like semantics, mcrfpy.timers collection closes #173
Major Timer API improvements:
- Add `stopped` flag to Timer C++ class for proper state management
- Add `start()` method to restart stopped timers (preserves callback)
- Add `stop()` method that removes from engine but preserves callback
- Make `active` property read-write (True=start/resume, False=pause)
- Add `start=True` init parameter to create timers in stopped state
- Add `mcrfpy.timers` module-level collection (tuple of active timers)
- One-shot timers now set stopped=true instead of clearing callback
- Remove deprecated `setTimer()` and `delTimer()` module functions

Timer callbacks now receive (timer, runtime) instead of just (runtime).
Updated all tests to use new Timer API and callback signature.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 22:09:18 -05:00
fc95fc2844 scene transitions via Scene object 2026-01-03 13:53:18 -05:00
d7e34a3f72 Remove old scene management methods 2026-01-03 11:01:42 -05:00
c025cd7da3 feat: Add Sound/Music classes, keyboard state, version (#66, #160, #164)
Replace module-level audio functions with proper OOP API:
- mcrfpy.Sound: Wraps sf::SoundBuffer + sf::Sound for short effects
- mcrfpy.Music: Wraps sf::Music for streaming long tracks
- Both support: volume, loop, playing, duration, play/pause/stop
- Music adds position property for seeking

Add mcrfpy.keyboard singleton for real-time modifier state:
- shift, ctrl, alt, system properties (bool, read-only)
- Queries sf::Keyboard::isKeyPressed() directly

Add mcrfpy.__version__ = "1.0.0" for version identity

Remove old audio API entirely (no deprecation - unused in codebase):
- createSoundBuffer, loadMusic, playSound
- setMusicVolume, getMusicVolume, setSoundVolume, getSoundVolume

closes #66, closes #160, closes #164

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 16:24:27 -05:00
71c91e19a5 feat: Add consistent Scene API with module-level properties (closes #151)
Replaces module-level scene functions with more Pythonic OO interface:

Scene class changes:
- Add `scene.children` property (replaces get_ui() method)
- Add `scene.on_key` getter/setter (matches on_click pattern)
- Remove get_ui() method

Module-level properties:
- Add `mcrfpy.current_scene` (getter returns Scene, setter activates)
- Add `mcrfpy.scenes` (read-only tuple of all Scene objects)

Implementation uses custom module type (McRFPyModuleType) inheriting
from PyModule_Type with tp_setattro for property assignment support.

New usage:
  scene = mcrfpy.Scene("game")
  mcrfpy.current_scene = scene
  scene.on_key = handler
  ui = scene.children

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-22 22:15:03 -05:00
f2f8d6422f Add warning when starting benchmark in headless mode
The benchmark API captures per-frame data from the game loop, which is
bypassed when using step()-based simulation control. This warning
informs users to use Python's time module for headless performance
measurement instead.

Also adds test_headless_benchmark.py which verifies:
- step() and screenshot() don't produce benchmark frames
- Wall-clock timing for headless operations
- Complex scene throughput measurement

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 22:20:19 -05:00
60ffa68d04 feat: Add mcrfpy.step() and synchronous screenshot for headless mode (closes #153)
Implements Python-controlled simulation advancement for headless mode:

- Add mcrfpy.step(dt) to advance simulation by dt seconds
- step(None) advances to next scheduled event (timer/animation)
- Timers use simulation_time in headless mode for deterministic behavior
- automation.screenshot() now renders synchronously in headless mode
  (captures current state, not previous frame)

This enables LLM agent orchestration (#156) by allowing:
- Set perspective, take screenshot, query LLM - all synchronous
- Deterministic simulation control without frame timing issues
- Event-driven advancement with step(None)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:56:47 -05:00
018e73590f feat: Implement FOV enum and layer draw_fov for #114 and #113
Phase 1 - FOV Enum System:
- Create PyFOV.h/cpp with mcrfpy.FOV IntEnum (BASIC, DIAMOND, SHADOW, etc.)
- Add mcrfpy.default_fov module property initialized to FOV.BASIC
- Add grid.fov and grid.fov_radius properties for per-grid defaults
- Remove deprecated module-level FOV_* constants (breaking change)

Phase 2 - Layer Operations:
- Implement ColorLayer.fill_rect(pos, size, color) for rectangle fills
- Implement TileLayer.fill_rect(pos, size, index) for tile rectangle fills
- Implement ColorLayer.draw_fov(source, radius, fov, visible, discovered, unknown)
  to paint FOV-based visibility on color layers using parent grid's TCOD map

The FOV enum uses Python's IntEnum for type safety while maintaining
backward compatibility with integer values. Tests updated to use new API.

Addresses #114 (FOV enum), #113 (layer operations)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 15:18:10 -05:00
4b05a95efe feat: Add dynamic layer system for Grid (closes #147)
Implements ColorLayer and TileLayer classes with z_index ordering:
- ColorLayer: stores RGBA color per cell for overlays, fog of war, etc.
- TileLayer: stores sprite index per cell with optional texture
- z_index < 0: renders below entities
- z_index >= 0: renders above entities

Python API:
- grid.add_layer(type, z_index, texture) - create layer
- grid.remove_layer(layer) - remove layer
- grid.layers - list of layers sorted by z_index
- grid.layer(z_index) - get layer by z_index
- layer.at(x,y) / layer.set(x,y,value) - cell access
- layer.fill(value) - fill entire layer

Layers are allocated separately from UIGridPoint, reducing memory
for grids that don't need all features. Base grid retains walkable/
transparent arrays for TCOD pathfinding.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:35:38 -05:00
a7fef2aeb6 feat: Add benchmark logging system for performance analysis (closes #104)
Add Python API for capturing performance data to JSON files:
- mcrfpy.start_benchmark() - start capturing frame data
- mcrfpy.end_benchmark() - stop and return filename
- mcrfpy.log_benchmark(msg) - add log message to current frame

The benchmark system captures per-frame data including:
- Frame timing (frame_time_ms, fps, timestamp)
- Detailed timing breakdown (grid_render, entity_render, python, animation, fov)
- Draw call and element counts
- User log messages attached to frames

Output JSON format supports analysis tools and includes:
- Benchmark metadata (PID, timestamps, duration, total frames)
- Full frame-by-frame metrics array

Also refactors ProfilingMetrics from nested GameEngine struct to
top-level struct for easier forward declaration.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 16:05:55 -05:00
219a559c35 feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
  - UISprite: position, scale, sprite_index changes
  - UICaption: position, font_size, colors, text changes
  - UIGrid: position, size, center, zoom, color changes
  - UILine: thickness, position, endpoints, color changes
  - UICircle: radius, position, colors changes
  - UIArc: radius, angles, position, color changes
  - UIEntity: position changes propagate to parent grid

- Expand getMetrics() Python API to include detailed timing breakdown:
  - grid_render_time, entity_render_time, fov_overlay_time
  - python_time, animation_time
  - grid_cells_rendered, entities_rendered, total_entities

- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
  - 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
  - Automated metrics collection and performance assessment
  - Timing breakdown percentages

This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
bbc744f8dc feat: Add self-contained venv support for pip packages (closes #137)
- Set sys.executable in PyConfig for subprocess/pip calls
- Detect sibling venv/ directory and prepend site-packages to sys.path
- Add mcrf_venv.py reference implementation for bootstrapping pip
- Supports both Linux (lib/python3.14/site-packages) and Windows (Lib/site-packages)

Usage: ./mcrogueface -m pip install numpy
Or via Python: mcrf_venv.pip_install("numpy")

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 22:01:09 -05:00
3f6ea4fe33 feat: Add ImGui-based developer console overlay
Integrates Dear ImGui for an in-game debug console that replaces the
blocking Python REPL. Press ~ (grave/tilde) to toggle the console.

Features:
- Python code execution without blocking the game loop
- Output capture with color coding (yellow=input, red=errors, gray=output)
- Expression results show repr() automatically
- Command history navigation with up/down arrows
- Word wrapping for long output lines
- Auto-scroll that doesn't fight manual scrolling
- mcrfpy.setDevConsole(bool) API to disable for shipping

Technical changes:
- Update imgui submodule to v1.89.9 (stable)
- Update imgui-sfml submodule to 2.6.x branch (SFML 2.x compatible)
- Add ImGui sources to CMakeLists.txt with OpenGL dependency
- Integrate ImGui lifecycle into GameEngine
- Add ImGuiConsole class for console overlay

closes #36, closes #65, closes #75

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:03:58 -05:00
28396b65c9 feat: Migrate to Python 3.14 (closes #135)
Replace deprecated Python C API calls with modern PyConfig-based initialization:
- PySys_SetArgvEx() -> PyConfig.argv (deprecated since 3.11)
- Py_InspectFlag -> PyConfig.inspect (deprecated since 3.12)

Fix critical memory safety bugs discovered during migration:
- PyColor::from_arg() and PyVector::from_arg() now return new references
  instead of borrowed references, preventing use-after-free when callers
  call Py_DECREF on the result
- GameEngine::testTimers() now holds a local shared_ptr copy during
  callback execution, preventing use-after-free when timer callbacks
  call delTimer() on themselves

Fix double script execution bug with --exec flag:
- Scripts were running twice because GameEngine constructor executed them,
  then main.cpp deleted and recreated the engine
- Now reuses existing engine and just sets auto_exit_after_exec flag

Update test syntax to use keyword arguments for Frame/Caption constructors.

Test results: 127/130 passing (97.7%)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 17:48:12 -05:00
19ded088b0 feat: Exit on first Python callback exception (closes #133)
By default, McRogueFace now exits with code 1 on the first unhandled
exception in timer, click, key, or animation callbacks. This prevents
repeated exception output that wastes resources in AI-driven development.

Changes:
- Add exit_on_exception config flag (default: true)
- Add --continue-after-exceptions CLI flag to preserve old behavior
- Update exception handlers in Timer, PyCallable, and Animation
- Signal game loop via McRFPy_API atomic flags
- Return proper exit code from main()

Before: Timer exceptions repeated 1000+ times until timeout
After: Single traceback, clean exit with code 1

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 10:26:30 -05:00
311dc02f1d feat: Add UILine, UICircle, and UIArc drawing primitives
Implement new UIDrawable-derived classes for vector graphics:

- UILine: Thick line segments using sf::ConvexShape for proper thickness
  - Properties: start, end, color, thickness
  - Supports click detection along the line

- UICircle: Filled and outlined circles using sf::CircleShape
  - Properties: radius, center, fill_color, outline_color, outline
  - Full property system for animations

- UIArc: Arc segments for orbital paths and partial circles
  - Properties: center, radius, start_angle, end_angle, color, thickness
  - Uses sf::VertexArray with TriangleStrip for smooth rendering
  - Supports arbitrary angle spans including negative (reverse) arcs

All primitives integrate with the Python API through mcrfpy module:
- Added to PyObjectsEnum for type identification
- Full getter/setter support for all properties
- Added to UICollection for scene management
- Support for visibility, opacity, z_index, name, and click handling

closes #128, closes #129

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 21:42:33 -05:00
621d719c25 docs: Phase 3 - Convert 19 module functions to MCRF_FUNCTION macros
Converted all module-level functions in McRFPy_API.cpp to use the MCRF_*
documentation macro system:

Audio functions (7):
- createSoundBuffer, loadMusic, setMusicVolume, setSoundVolume
- playSound, getMusicVolume, getSoundVolume

Scene functions (5):
- sceneUI, currentScene, setScene, createScene, keypressScene

Timer functions (2):
- setTimer, delTimer

Utility functions (5):
- exit, setScale, find, findAll, getMetrics

Each function now uses:
- MCRF_SIG for signatures
- MCRF_DESC for descriptions
- MCRF_ARG for parameters
- MCRF_RETURNS for return values
- MCRF_RAISES for exceptions
- MCRF_NOTE for additional details

Phase 4 assessment: PyCallable.cpp and PythonObjectCache.cpp contain only
internal C++ implementation with no Python API to document.

All conversions tested and verified with test_phase3_docs.py.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 19:38:22 -04:00
6aa4625b76 fix: correct module docstring newline escaping
Fixed module-level docstring in PyModuleDef where double-backslash newlines
(\\n) were appearing as literal "\n" text in help(mcrfpy) output.

Changed from escaped newlines (\\n) to actual newlines (\n) so the C compiler
interprets them correctly.

Before: help(mcrfpy) showed "McRogueFace Python API\\n\\nCore game..."
After:  help(mcrfpy) shows proper formatting with line breaks

The issue was in the PyDoc_STR() macro call - it doesn't interpret escape
sequences, so the string literal itself needs to have proper newlines.
2025-10-30 15:57:17 -04:00