I worked again on the Input module. Besides large internal simplifications and refactorings of the action resolution system, the following parts have changed:
1. Custom actionsIt is now possible to bind user-defined actions to
thor::Action. That is, you can not only combine existing action types with the boolean operators, but define yourself when an action is considered active. For this purpose, two factory functions
thor::eventAction() and
thor::realtimeAction() have been added. These take functors that return a
bool whenever an action is supposed to be active.
For example, you can react specifically to every event, or once per frame to a realtime condition:
bool enteredLowerH(const sf::Event& event)
{
return event.type == sf::Event::TextEntered && event.text.unicode == 'h';
}
bool joystickConnected()
{
return sf::Joystick::isConnected(1);
}
thor::Action a = thor::eventAction(&enteredLowerH);
thor::Action b = thor::realtimeAction(&joystickConnected);
As you see, the realtime action is not directly linked to SFML, so you can also use it to check other states in your application.
2. Simpler callback registrationThe two classes
thor::EventSystem and
thor::CallbackTimer allow you to register callbacks through the
connect() function:
void listener(thor::CallbackTimer& trigger)
{
std::cout << "expired" << std::endl;
trigger.restart(sf::seconds(1.f));
}
thor::CallbackTimer timer;
timer.connect(&listener);
These callbacks take the instance that triggered them as a parameter. While this is useful in the above example, there are many cases where you just want to perform an action and don't care about the source. That is why I added the additional member functions
connect0(), where 0 stands for "nullary" (meaning the function takes no arguments). Unfortunately I can't overload
connect() because of ambiguities, at least not without a lot of black TMP magic.
An implication of this change is that the functions registered at
thor::ActionMap::CallbackSystem do not need to carry a unused
thor::ActionContext parameter. Instead of
void listener(thor::ActionContext<MyAction> context);
thor::ActionMap<MyAction>::CallbackSystem system;
system.connect(ActionXY, &listener);
you can now omit the parameter:
void listener();
thor::ActionMap<MyAction>::CallbackSystem system;
system.connect0(ActionXY, &listener);
3. API changesThe named-parameter-idiom function
thor::joy() has been renamed to
thor::joystick() for clarity.
The member typedefs
Listener of
thor::CallbackTimer and
thor::EventSystem have been removed, and the
connect() and
connect0() parameters are written directly as
std::function<...> instead of
Listener. I hope that, by omitting this abstraction, it is clearer how the signature of the callbacks has to look.