Implement Scene subclass on_key callback support

Scene subclasses can now define on_key(self, key, state) methods that
receive keyboard events, matching the existing on_enter, on_exit, and
update lifecycle callbacks.

Changes:
- Rename call_on_keypress to call_on_key (consistent naming with property)
- Add triggerKeyEvent helper in McRFPy_API
- Call triggerKeyEvent from GameEngine when key_callable is not set
- Fix condition to check key_callable.isNone() (not just pointer existence)
- Handle both bound methods and instance-assigned callables

Usage:
    class GameScene(mcrfpy.Scene):
        def on_key(self, key, state):
            if key == "Escape" and state == "end":
                quit_game()

Property assignment (scene.on_key = callable) still works and takes
precedence when key_callable is set via the property setter.

Includes comprehensive test: tests/unit/scene_subclass_on_key_test.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John McCardle 2026-01-09 15:51:20 -05:00
commit 1d11b020b0
5 changed files with 118 additions and 10 deletions

View file

@ -457,11 +457,17 @@ void GameEngine::processEvent(const sf::Event& event)
std::string name = currentScene()->action(actionCode);
currentScene()->doAction(name, actionType);
}
else if (currentScene()->key_callable &&
else if (currentScene()->key_callable && !currentScene()->key_callable->isNone() &&
(event.type == sf::Event::KeyPressed || event.type == sf::Event::KeyReleased))
{
// Property-assigned handler (scene.on_key = callable)
currentScene()->key_callable->call(ActionCode::key_str(event.key.code), actionType);
}
else if (event.type == sf::Event::KeyPressed || event.type == sf::Event::KeyReleased)
{
// Try subclass on_key method if no property handler is set
McRFPy_API::triggerKeyEvent(ActionCode::key_str(event.key.code), actionType);
}
}
void GameEngine::sUserInput()