Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef __K_UI_UI_H__
- #define __K_UI_UI_H__
- #include "Common.h"
- #include "math/Vector.h"
- #include "sol.hpp"
- union SDL_Event;
- namespace k
- {
- namespace graphics
- {
- class Texture;
- }
- namespace ui
- {
- enum struct InputEventType : uint8
- {
- UP = 0,
- DOWN,
- LEFT,
- RIGHT,
- ACCEPT,
- DECLINE,
- TEXT,
- };
- struct InputEvent
- {
- InputEventType type;
- char* text;
- InputEvent(InputEventType type, char* text = nullptr) : type(type), text(text) { }
- };
- class Element
- {
- public:
- Element() : _up(nullptr), _down(nullptr), _left(nullptr), _right(nullptr), _hasFocus(false) {}
- virtual ~Element() {};
- math::Vec2I position;
- void SetPosition(int32 x, int32 y);
- void LinkUp (Element* element);
- void LinkDown (Element* element);
- void LinkLeft (Element* element);
- void LinkRight (Element* element);
- inline Element* GetUp() { return _up; }
- inline Element* GetDown() { return _down; }
- inline Element* GetLeft() { return _left; }
- inline Element* GetRight() { return _right; }
- virtual bool ProcessEvent(InputEvent e) = 0;
- virtual void Render(const math::Vec2I& parent, graphics::Texture& rt) = 0;
- virtual void BecomeActive() = 0;
- virtual void BecomeInactive() = 0;
- private:
- Element* _up;
- Element* _down;
- Element* _left;
- Element* _right;
- bool _hasFocus;
- };
- class Button : public Element
- {
- public:
- Button() : Element(), _active(nullptr), _inactive(nullptr), _isActive(false) {}
- virtual ~Button() override {}
- void SetActiveTexture(graphics::Texture& tex);
- void SetInactiveTexture(graphics::Texture& tex);
- void SetFunction(const sol::function& fun);
- virtual bool ProcessEvent(InputEvent e) override;
- virtual void Render(const math::Vec2I& parent, graphics::Texture& rt) override;
- virtual void BecomeActive() override;
- virtual void BecomeInactive() override;
- private:
- sol::function _onClick;
- graphics::Texture* _active;
- graphics::Texture* _inactive;
- bool _isActive;
- };
- class Text : public Element
- {
- public:
- Text() : Element(), _text(), _dirty(true), _active(nullptr), _inactive(nullptr), _isActive(false) {}
- void SetText(const std::string& text);
- const std::string& GetText() const;
- virtual bool ProcessEvent(InputEvent e) override;
- virtual void Render(const math::Vec2I& parent, graphics::Texture& rt) override;
- virtual void BecomeActive() override;
- virtual void BecomeInactive() override;
- private:
- std::string _text;
- bool _dirty;
- std::unique_ptr<graphics::Texture> _active;
- std::unique_ptr<graphics::Texture> _inactive;
- bool _isActive;
- };
- class Window
- {
- public:
- math::Vec2I position;
- bool Close();
- bool ProcessEvent(InputEvent e);
- void Render(graphics::Texture& rt);
- void SetPosition(int32 x, int32 y);
- void SetTexture(graphics::Texture& tex);
- void AddElement(Element* element);
- private:
- std::vector<Element*> _elements;
- graphics::Texture* _texture;
- Element* _active;
- inline void _changeFocus(Element* e)
- {
- if (e && e != _active)
- {
- _active->BecomeInactive();
- _active = e;
- _active->BecomeActive();
- }
- }
- };
- class WindowManager
- {
- public:
- static void OpenWindow(Window& wnd);
- static void CloseWindow();
- static bool ProcessEvent(const SDL_Event &event);
- static void Render(graphics::Texture& rt);
- private:
- static Window* _active;
- static std::stack<Window*> _inactive;
- };
- }
- }
- #endif // !__K_UI_UI_H__
- #include "ui/UI.h"
- #include "SDL2/SDL.h"
- #include "Input.h"
- #include "graphics/Texture.h"
- #include "sol.hpp"
- using namespace k;
- using namespace ui;
- void Element::SetPosition(int32 x, int32 y) {
- position.Set(x, y);
- }
- void Element::LinkUp(Element* element) {
- if (this->_up) // unlink first
- this->_up->_down = nullptr;
- this->_up = element;
- if (element)
- element->_down = this;
- }
- void Element::LinkDown(Element* element) {
- if (this->_down) // unlink first
- this->_down->_up = nullptr;
- this->_down = element;
- if (element)
- element->_up = this;
- }
- void Element::LinkLeft(Element* element) {
- if (this->_left) // unlink first
- this->_left->_right = nullptr;
- this->_left = element;
- if (element)
- element->_right = this;
- }
- void Element::LinkRight(Element* element) {
- if (this->_right) // unlink first
- this->_right->_left = nullptr;
- this->_right = element;
- if(element)
- element->_left = this;
- }
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
- //:::::::::::::::::::::::::::::: Button ::::::::::::::::::::::::::::::://
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
- void Button::SetActiveTexture(graphics::Texture& tex) {
- _active = &tex;
- }
- void Button::SetInactiveTexture(graphics::Texture& tex) {
- _inactive = &tex;
- }
- void Button::SetFunction(const sol::function& fun) {
- _onClick = fun;
- }
- bool Button::ProcessEvent(InputEvent e) {
- if (e.type == InputEventType::ACCEPT)
- {
- _onClick();
- return true;
- }
- return false;
- }
- void Button::Render(const math::Vec2I& parent, graphics::Texture& rt)
- {
- graphics::Texture* _texture = _isActive ? _active : _inactive;
- graphics::Color* target = rt.GetPixels();
- graphics::Color* source = _texture->GetPixels();
- uint16 line = _texture->GetWidth();
- uint16 count = _texture->GetHeight();
- target += (parent.y + position.y) * rt.GetWidth() + (parent.x + position.x);
- for (int y = 0; y < count; ++y)
- {
- memcpy(target, source, line * sizeof(graphics::Color));
- target += rt.GetWidth();
- source += line;
- }
- }
- void Button::BecomeActive() {
- _isActive = true;
- }
- void Button::BecomeInactive() {
- _isActive = false;
- }
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
- //::::::::::::::::::::::::::::::: Text :::::::::::::::::::::::::::::::://
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
- void Text::SetText(const std::string& value)
- {
- if (_text != value)
- {
- _text = value;
- _dirty = true;
- }
- }
- const std::string& Text::GetText() const {
- return _text;
- }
- bool Text::ProcessEvent(InputEvent e) {
- return false;
- }
- void Text::Render(const math::Vec2I& parent, graphics::Texture& rt)
- {
- }
- void Text::BecomeActive() {
- _isActive = true;
- }
- void Text::BecomeInactive() {
- _isActive = false;
- }
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
- //:::::::::::::::::::::::::::::: Window ::::::::::::::::::::::::::::::://
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
- bool Window::Close() {
- if (_elements.size() > 1) {
- _changeFocus(_elements[0]);
- }
- return true;
- }
- bool Window::ProcessEvent(InputEvent evt) {
- if (_active->ProcessEvent(evt))
- return true;
- switch (evt.type) {
- case k::ui::InputEventType::UP: {
- _changeFocus(_active->GetUp());
- }
- break;
- case k::ui::InputEventType::DOWN: {
- _changeFocus(_active->GetDown());
- }
- break;
- case k::ui::InputEventType::LEFT: {
- _changeFocus(_active->GetLeft());
- }
- break;
- case k::ui::InputEventType::RIGHT: {
- _changeFocus(_active->GetRight());
- }
- break;
- case k::ui::InputEventType::DECLINE:
- WindowManager::CloseWindow();
- break;
- default:
- break;
- }
- return true;
- }
- void Window::Render(graphics::Texture& rt) {
- graphics::Color* target = rt.GetPixels();
- graphics::Color* source = _texture->GetPixels();
- uint16 line = _texture->GetWidth();
- uint16 count = _texture->GetHeight();
- target += position.y * rt.GetWidth() + position.x;
- for (int y = 0; y < count; ++y)
- {
- memcpy(target, source, line * sizeof(graphics::Color));
- target += rt.GetWidth();
- source += line;
- }
- for (auto it = _elements.begin(); it != _elements.end(); ++it)
- (*it)->Render(position, rt);
- }
- void Window::SetTexture(graphics::Texture& tex) {
- _texture = &tex;
- }
- void Window::SetPosition(int32 x, int32 y) {
- position.Set(x, y);
- }
- void Window::AddElement(Element* element) {
- if (_active == nullptr)
- {
- _active = element;
- _active->BecomeActive();
- }
- _elements.push_back(element);
- }
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
- //::::::::::::::::::::::::: Window manager :::::::::::::::::::::::::::://
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
- Window* WindowManager::_active = nullptr;
- std::stack<Window*> WindowManager::_inactive = std::stack<Window*>();
- void WindowManager::OpenWindow(Window& wnd) {
- if (_active)
- _inactive.push(_active);
- _active = &wnd;
- }
- void WindowManager::CloseWindow() {
- if (_active->Close())
- {
- if (_inactive.size()) {
- _active = _inactive.top(); _inactive.pop();
- }
- else
- _active = nullptr;
- }
- }
- bool WindowManager::ProcessEvent(const SDL_Event& event)
- {
- if (!_active)
- return false;
- switch (event.type)
- {
- case SDL_KEYDOWN:
- {
- KeyCode c = (KeyCode)event.key.keysym.sym;
- switch (c)
- {
- case k::KeyCode::Return:
- case k::KeyCode::NumEnter:
- case k::KeyCode::Space:
- _active->ProcessEvent(InputEvent(InputEventType::ACCEPT));
- break;
- case k::KeyCode::Escape:
- case k::KeyCode::BackSpace:
- _active->ProcessEvent(InputEvent(InputEventType::DECLINE));
- break;
- case k::KeyCode::Right:
- case k::KeyCode::D:
- _active->ProcessEvent(InputEvent(InputEventType::RIGHT));
- break;
- case k::KeyCode::Left:
- case k::KeyCode::A:
- _active->ProcessEvent(InputEvent(InputEventType::LEFT));
- break;
- case k::KeyCode::Down:
- case k::KeyCode::S:
- _active->ProcessEvent(InputEvent(InputEventType::DOWN));
- break;
- case k::KeyCode::Up:
- case k::KeyCode::W:
- _active->ProcessEvent(InputEvent(InputEventType::UP));
- break;
- default:
- break;
- }
- }
- return true;
- break;
- case SDL_MOUSEMOTION:
- return true;
- break;
- case SDL_TEXTINPUT:
- _active->ProcessEvent(InputEvent(InputEventType::TEXT, (char*)event.text.text));
- break;
- }
- return false;
- }
- void WindowManager::Render(graphics::Texture& rt)
- {
- if (!_active)
- return;
- _active->Render(rt);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement