Advertisement
Guest User

Untitled

a guest
Jun 1st, 2018
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.14 KB | None | 0 0
  1. #ifndef __K_UI_UI_H__
  2. #define __K_UI_UI_H__
  3. #include "Common.h"
  4. #include "math/Vector.h"
  5. #include "sol.hpp"
  6.  
  7. union SDL_Event;
  8.  
  9. namespace k
  10. {
  11.     namespace graphics
  12.     {
  13.         class Texture;
  14.     }
  15.  
  16.     namespace ui
  17.     {
  18.         enum struct InputEventType : uint8
  19.         {
  20.             UP = 0,
  21.             DOWN,
  22.             LEFT,
  23.             RIGHT,
  24.             ACCEPT,
  25.             DECLINE,
  26.             TEXT,
  27.         };
  28.  
  29.         struct InputEvent
  30.         {
  31.             InputEventType  type;
  32.             char*           text;
  33.             InputEvent(InputEventType type, char* text = nullptr) : type(type), text(text) { }
  34.         };
  35.  
  36.         class Element
  37.         {
  38.         public:
  39.             Element() : _up(nullptr), _down(nullptr), _left(nullptr), _right(nullptr), _hasFocus(false) {}
  40.             virtual ~Element() {};
  41.  
  42.             math::Vec2I     position;
  43.             void SetPosition(int32 x, int32 y);
  44.  
  45.             void LinkUp     (Element* element);
  46.             void LinkDown   (Element* element);
  47.             void LinkLeft   (Element* element);
  48.             void LinkRight  (Element* element);
  49.  
  50.             inline Element* GetUp() { return _up; }
  51.             inline Element* GetDown() { return _down; }
  52.             inline Element* GetLeft() { return _left; }
  53.             inline Element* GetRight() { return _right; }
  54.  
  55.             virtual bool ProcessEvent(InputEvent e) = 0;
  56.             virtual void Render(const math::Vec2I& parent, graphics::Texture& rt) = 0;
  57.  
  58.             virtual void BecomeActive() = 0;
  59.             virtual void BecomeInactive() = 0;
  60.  
  61.         private:
  62.             Element* _up;
  63.             Element* _down;
  64.             Element* _left;
  65.             Element* _right;
  66.  
  67.             bool _hasFocus;
  68.         };
  69.  
  70.         class Button : public Element
  71.         {
  72.         public:
  73.             Button() : Element(), _active(nullptr), _inactive(nullptr), _isActive(false) {}
  74.             virtual ~Button() override {}
  75.  
  76.             void SetActiveTexture(graphics::Texture& tex);
  77.             void SetInactiveTexture(graphics::Texture& tex);
  78.             void SetFunction(const sol::function& fun);
  79.  
  80.             virtual bool ProcessEvent(InputEvent e) override;
  81.             virtual void Render(const math::Vec2I& parent, graphics::Texture& rt) override;
  82.  
  83.             virtual void BecomeActive() override;
  84.             virtual void BecomeInactive() override;
  85.  
  86.         private:
  87.             sol::function       _onClick;
  88.             graphics::Texture*  _active;
  89.             graphics::Texture*  _inactive;
  90.             bool                _isActive;
  91.         };
  92.  
  93.         class Text : public Element
  94.         {
  95.         public:
  96.             Text() : Element(),  _text(), _dirty(true), _active(nullptr), _inactive(nullptr), _isActive(false) {}
  97.             void                SetText(const std::string& text);
  98.             const std::string&  GetText() const;
  99.  
  100.             virtual bool ProcessEvent(InputEvent e) override;
  101.             virtual void Render(const math::Vec2I& parent, graphics::Texture& rt) override;
  102.  
  103.             virtual void BecomeActive() override;
  104.             virtual void BecomeInactive() override;
  105.  
  106.         private:
  107.             std::string _text;
  108.             bool        _dirty;
  109.             std::unique_ptr<graphics::Texture> _active;
  110.             std::unique_ptr<graphics::Texture> _inactive;
  111.             bool        _isActive;
  112.         };
  113.  
  114.         class Window
  115.         {
  116.         public:
  117.             math::Vec2I position;
  118.  
  119.             bool Close();
  120.  
  121.             bool ProcessEvent(InputEvent e);
  122.             void Render(graphics::Texture& rt);
  123.  
  124.             void SetPosition(int32 x, int32 y);
  125.             void SetTexture(graphics::Texture& tex);
  126.             void AddElement(Element* element);
  127.  
  128.         private:
  129.             std::vector<Element*>   _elements;
  130.             graphics::Texture*      _texture;
  131.             Element*                _active;
  132.             inline void             _changeFocus(Element* e)
  133.             {
  134.                 if (e && e != _active)
  135.                 {
  136.                     _active->BecomeInactive();
  137.                     _active = e;
  138.                     _active->BecomeActive();
  139.                 }
  140.             }
  141.         };
  142.  
  143.         class WindowManager
  144.         {
  145.         public:
  146.             static void OpenWindow(Window& wnd);
  147.             static void CloseWindow();
  148.  
  149.             static bool ProcessEvent(const SDL_Event &event);
  150.             static void Render(graphics::Texture& rt);
  151.         private:
  152.             static Window* _active;
  153.             static std::stack<Window*> _inactive;
  154.         };
  155.     }
  156. }
  157.  
  158. #endif // !__K_UI_UI_H__
  159.  
  160. #include "ui/UI.h"
  161. #include "SDL2/SDL.h"
  162. #include "Input.h"
  163. #include "graphics/Texture.h"
  164.  
  165. #include "sol.hpp"
  166.  
  167. using namespace k;
  168. using namespace ui;
  169.  
  170. void Element::SetPosition(int32 x, int32 y) {
  171.     position.Set(x, y);
  172. }
  173.  
  174. void Element::LinkUp(Element* element) {
  175.     if (this->_up) // unlink first
  176.         this->_up->_down = nullptr;
  177.  
  178.     this->_up = element;
  179.     if (element)
  180.         element->_down = this;
  181. }
  182.  
  183. void Element::LinkDown(Element* element) {
  184.     if (this->_down) // unlink first
  185.         this->_down->_up = nullptr;
  186.  
  187.     this->_down = element;
  188.     if (element)
  189.         element->_up = this;
  190. }
  191.  
  192. void Element::LinkLeft(Element* element) {
  193.     if (this->_left) // unlink first
  194.         this->_left->_right = nullptr;
  195.  
  196.     this->_left = element;
  197.     if (element)
  198.         element->_right = this;
  199. }
  200.  
  201. void Element::LinkRight(Element* element) {
  202.     if (this->_right) // unlink first
  203.         this->_right->_left = nullptr;
  204.  
  205.     this->_right = element;
  206.     if(element)
  207.         element->_left = this;
  208. }
  209.  
  210.  
  211. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
  212. //:::::::::::::::::::::::::::::: Button ::::::::::::::::::::::::::::::://
  213. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
  214.  
  215. void Button::SetActiveTexture(graphics::Texture& tex) {
  216.     _active = &tex;
  217. }
  218.  
  219. void Button::SetInactiveTexture(graphics::Texture& tex) {
  220.     _inactive = &tex;
  221. }
  222.  
  223. void Button::SetFunction(const sol::function& fun) {
  224.     _onClick = fun;
  225. }
  226.  
  227. bool Button::ProcessEvent(InputEvent e) {
  228.     if (e.type == InputEventType::ACCEPT)
  229.     {
  230.         _onClick();
  231.         return true;
  232.     }
  233.     return false;
  234. }
  235.  
  236. void Button::Render(const math::Vec2I& parent, graphics::Texture& rt)
  237. {
  238.     graphics::Texture* _texture = _isActive ? _active : _inactive;
  239.  
  240.     graphics::Color* target = rt.GetPixels();
  241.     graphics::Color* source = _texture->GetPixels();
  242.     uint16 line = _texture->GetWidth();
  243.     uint16 count = _texture->GetHeight();
  244.     target += (parent.y + position.y) * rt.GetWidth() + (parent.x + position.x);
  245.     for (int y = 0; y < count; ++y)
  246.     {
  247.         memcpy(target, source, line * sizeof(graphics::Color));
  248.         target += rt.GetWidth();
  249.         source += line;
  250.     }
  251. }
  252.  
  253. void Button::BecomeActive() {
  254.     _isActive = true;
  255. }
  256.  
  257. void Button::BecomeInactive() {
  258.     _isActive = false;
  259. }
  260.  
  261. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
  262. //::::::::::::::::::::::::::::::: Text :::::::::::::::::::::::::::::::://
  263. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
  264.  
  265. void Text::SetText(const std::string& value)
  266. {
  267.     if (_text != value)
  268.     {
  269.         _text = value;
  270.         _dirty = true;
  271.     }
  272. }
  273.  
  274. const std::string& Text::GetText() const {
  275.     return _text;
  276. }
  277.  
  278. bool Text::ProcessEvent(InputEvent e) {
  279.     return false;
  280. }
  281. void Text::Render(const math::Vec2I& parent, graphics::Texture& rt)
  282. {
  283. }
  284.  
  285. void Text::BecomeActive() {
  286.     _isActive = true;
  287. }
  288. void Text::BecomeInactive() {
  289.     _isActive = false;
  290. }
  291.  
  292. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
  293. //:::::::::::::::::::::::::::::: Window ::::::::::::::::::::::::::::::://
  294. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
  295.  
  296. bool Window::Close() {
  297.     if (_elements.size() > 1) {
  298.         _changeFocus(_elements[0]);
  299.     }
  300.     return true;
  301. }
  302.  
  303. bool Window::ProcessEvent(InputEvent evt) {
  304.  
  305.     if (_active->ProcessEvent(evt))
  306.         return true;
  307.  
  308.     switch (evt.type) {
  309.     case k::ui::InputEventType::UP: {
  310.         _changeFocus(_active->GetUp());
  311.     }
  312.     break;
  313.     case k::ui::InputEventType::DOWN: {
  314.         _changeFocus(_active->GetDown());
  315.     }
  316.     break;
  317.     case k::ui::InputEventType::LEFT: {
  318.         _changeFocus(_active->GetLeft());
  319.     }
  320.     break;
  321.     case k::ui::InputEventType::RIGHT: {
  322.         _changeFocus(_active->GetRight());
  323.     }
  324.     break;
  325.     case k::ui::InputEventType::DECLINE:
  326.         WindowManager::CloseWindow();
  327.         break;
  328.     default:
  329.         break;
  330.     }
  331.  
  332.     return true;
  333. }
  334.  
  335. void Window::Render(graphics::Texture& rt) {
  336.     graphics::Color* target = rt.GetPixels();
  337.     graphics::Color* source = _texture->GetPixels();
  338.     uint16 line = _texture->GetWidth();
  339.     uint16 count = _texture->GetHeight();
  340.     target += position.y * rt.GetWidth() + position.x;
  341.     for (int y = 0; y < count; ++y)
  342.     {
  343.         memcpy(target, source, line * sizeof(graphics::Color));
  344.         target += rt.GetWidth();
  345.         source += line;
  346.     }
  347.  
  348.     for (auto it = _elements.begin(); it != _elements.end(); ++it)
  349.         (*it)->Render(position, rt);
  350. }
  351.  
  352. void Window::SetTexture(graphics::Texture& tex) {
  353.     _texture = &tex;
  354. }
  355.  
  356. void Window::SetPosition(int32 x, int32 y) {
  357.     position.Set(x, y);
  358. }
  359.  
  360. void Window::AddElement(Element* element) {
  361.     if (_active == nullptr)
  362.     {
  363.         _active = element;
  364.         _active->BecomeActive();
  365.     }
  366.     _elements.push_back(element);
  367. }
  368.  
  369. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
  370. //::::::::::::::::::::::::: Window manager :::::::::::::::::::::::::::://
  371. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
  372.  
  373. Window*             WindowManager::_active = nullptr;
  374. std::stack<Window*> WindowManager::_inactive = std::stack<Window*>();
  375.  
  376. void WindowManager::OpenWindow(Window& wnd) {
  377.     if (_active)
  378.         _inactive.push(_active);
  379.  
  380.     _active = &wnd;
  381. }
  382.  
  383. void WindowManager::CloseWindow() {
  384.     if (_active->Close())
  385.     {
  386.         if (_inactive.size()) {
  387.             _active = _inactive.top(); _inactive.pop();
  388.         }
  389.         else
  390.             _active = nullptr;
  391.     }
  392. }
  393.  
  394. bool WindowManager::ProcessEvent(const SDL_Event& event)
  395. {
  396.     if (!_active)
  397.         return false;
  398.  
  399.     switch (event.type)
  400.     {
  401.         case SDL_KEYDOWN:
  402.         {
  403.             KeyCode c = (KeyCode)event.key.keysym.sym;
  404.             switch (c)
  405.             {
  406.             case k::KeyCode::Return:
  407.             case k::KeyCode::NumEnter:
  408.             case k::KeyCode::Space:
  409.                 _active->ProcessEvent(InputEvent(InputEventType::ACCEPT));
  410.                 break;
  411.  
  412.             case k::KeyCode::Escape:
  413.             case k::KeyCode::BackSpace:
  414.                 _active->ProcessEvent(InputEvent(InputEventType::DECLINE));
  415.                 break;
  416.  
  417.             case k::KeyCode::Right:
  418.             case k::KeyCode::D:
  419.                 _active->ProcessEvent(InputEvent(InputEventType::RIGHT));
  420.                 break;
  421.             case k::KeyCode::Left:
  422.             case k::KeyCode::A:
  423.                 _active->ProcessEvent(InputEvent(InputEventType::LEFT));
  424.                 break;
  425.             case k::KeyCode::Down:
  426.             case k::KeyCode::S:
  427.                 _active->ProcessEvent(InputEvent(InputEventType::DOWN));
  428.                 break;
  429.             case k::KeyCode::Up:
  430.             case k::KeyCode::W:
  431.                 _active->ProcessEvent(InputEvent(InputEventType::UP));
  432.                 break;
  433.             default:
  434.                 break;
  435.             }
  436.         }
  437.         return true;
  438.         break;
  439.         case SDL_MOUSEMOTION:
  440.             return true;
  441.             break;
  442.         case SDL_TEXTINPUT:
  443.             _active->ProcessEvent(InputEvent(InputEventType::TEXT, (char*)event.text.text));
  444.             break;
  445.     }
  446.  
  447.     return false;
  448. }
  449.  
  450. void WindowManager::Render(graphics::Texture& rt)
  451. {
  452.     if (!_active)
  453.         return;
  454.  
  455.     _active->Render(rt);
  456. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement