-
-
Save Rapptz/c999ec9a6fb7475e2aaf to your computer and use it in GitHub Desktop.
Action WIP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FIRE_ACTION_HPP | |
#define FIRE_ACTION_HPP | |
#include <SFML/Window/Event.hpp> | |
#include <memory> | |
#include <vector> | |
namespace fire { | |
enum class ActionType : char { | |
PressedOnce, | |
Held, | |
Released, | |
Triggered | |
}; | |
class Action { | |
private: | |
bool active = false; | |
bool state = false; | |
const sf::Event::EventType* event = nullptr; | |
const sf::Keyboard::Key* key = nullptr; | |
const sf::Mouse::Button* mouse = nullptr; | |
ActionType type = ActionType::Triggered; | |
enum ChainType : char { And, Or }; | |
struct Node { | |
ChainType type; | |
std::shared_ptr<Action> action; | |
}; | |
std::vector<Node> nodes; | |
void update(bool value) { | |
switch(type) { | |
case ActionType::Triggered: | |
active = value; | |
break; | |
case ActionType::Held: | |
active = value && state; | |
break; | |
case ActionType::PressedOnce: | |
active = value && !state; | |
break; | |
case ActionType::Released: | |
active = !value && state; | |
break; | |
} | |
state = value; | |
} | |
template<typename Key> | |
friend class ActionMap; | |
public: | |
Action() = default; | |
explicit Action(sf::Event::EventType event) noexcept: event(&event) {} | |
explicit Action(sf::Keyboard::Key key, ActionType type = ActionType::Triggered) noexcept: key(&key), type(type) {} | |
explicit Action(sf::Mouse::Button mouse, ActionType type = ActionType::Triggered) noexcept: mouse(&mouse), type(type) {} | |
Action(Action&&) = default; | |
Action(const Action&) = default; | |
friend Action operator&(const Action& lhs, const Action& rhs) { | |
Action result(lhs); | |
result.nodes.push_back({ Action::ChainType::And, std::make_shared<Action>(rhs) }); | |
return result; | |
} | |
friend Action operator|(const Action& lhs, const Action& rhs) { | |
Action result(lhs); | |
result.nodes.push_back({ Action::ChainType::Or, std::make_shared<Action>(rhs) }); | |
return result; | |
} | |
bool isChained() const { | |
return nodes.empty(); | |
} | |
explicit operator bool() const noexcept { | |
return active; | |
} | |
}; | |
} // fire | |
#endif // FIRE_ACTION_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FIRE_ACTIONMAP_HPP | |
#define FIRE_ACTIONMAP_HPP | |
#include "Action.hpp" | |
#include <unordered_map> | |
namespace fire { | |
template<typename Key> | |
class ActionMap { | |
private: | |
std::unordered_map<Key, Action> actions; | |
sf::Event eventdata; | |
void updateAction(Action& action) noexcept { | |
if(action.mouse != nullptr) { | |
action.update(sf::Mouse::isButtonPressed((*action.mouse))); | |
} | |
if(action.key != nullptr) { | |
action.update(sf::Keyboard::isKeyPressed((*action.key))); | |
} | |
if(action.event != nullptr) { | |
action.update(eventdata.type == *action.event); | |
} | |
} | |
void all(Action& action) { | |
auto first = action.nodes.begin(); | |
auto last = action.nodes.end(); | |
for(; first != last; ++first) { | |
if(!action.active) { | |
break; | |
} | |
updateAction(*(first->action)); | |
if((first->type == Action::ChainType::Or) && (first + 1) != last) { | |
bool temporary = first->action->active; | |
++first; | |
updateAction(*(first->action)); | |
action.active = temporary || first->action->active; | |
continue; | |
} | |
action.active = first->action->active; | |
} | |
} | |
void any(Action& action) { | |
auto first = action.nodes.begin(); | |
auto last = action.nodes.end(); | |
for(; first != last; ++first) { | |
if(action.active) { | |
break; | |
} | |
updateAction(*(first->action)); | |
if((first->type == Action::ChainType::And) && (first + 1) != last) { | |
bool temporary = first->action->active; | |
++first; | |
updateAction(*(first->action)); | |
action.active = temporary && first->action->active; | |
continue; | |
} | |
action.active = first->action->active; | |
} | |
} | |
public: | |
ActionMap() = default; | |
ActionMap(std::initializer_list<std::pair<Key, Action>> l) noexcept: actions(l.begin(), l.end()) {} | |
bool isActive(Key&& key) noexcept { | |
return actions.count(std::forward<Key>(key)) ? actions[std::forward<Key>(key)].active : false; | |
} | |
sf::Event getEvent() const noexcept { | |
return eventdata; | |
} | |
template<typename Window> | |
void update(Window& window) noexcept { | |
window.pollEvent(eventdata); | |
for(auto&& action : actions) { | |
updateAction(action.second); | |
switch(action.second.nodes.begin()->type) { | |
case Action::ChainType::Or: | |
any(action.second); | |
break; | |
case Action::ChainType::And: | |
all(action.second); | |
break; | |
} | |
} | |
} | |
}; | |
} // fire | |
#endif // FIRE_ACTIONMAP_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SFML/Graphics.hpp> | |
#include "ActionMap.hpp" | |
int main() { | |
sf::RenderWindow window(sf::VideoMode(800, 600), "Cynre", sf::Style::Close); | |
fire::Action ctrl(sf::Keyboard::LControl, fire::ActionType::Held); | |
fire::Action w(sf::Keyboard::W, fire::ActionType::Held); | |
fire::Action k(sf::Keyboard::K, fire::ActionType::Released); | |
fire::Action close(sf::Event::Closed); | |
fire::Action binded = (ctrl & w & k) | close; | |
fire::ActionMap<const char*> map = { | |
{"close", binded} | |
}; | |
while(window.isOpen()) { | |
map.update(window); | |
if(map.isActive("close")) | |
window.close(); | |
window.clear(); | |
window.display(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment