From fd686eadf81e85bd4993a483adcefd6a153d259f Mon Sep 17 00:00:00 2001 From: hop311 Date: Tue, 7 Nov 2023 22:18:08 +0000 Subject: GUI and GFX file loading --- src/openvic-simulation/interface/GFX.cpp | 98 +++++++++++ src/openvic-simulation/interface/GFX.hpp | 138 +++++++++++++++ src/openvic-simulation/interface/GUI.cpp | 182 ++++++++++++++++++++ src/openvic-simulation/interface/GUI.hpp | 235 ++++++++++++++++++++++++++ src/openvic-simulation/interface/LoadBase.hpp | 82 +++++++++ src/openvic-simulation/interface/UI.cpp | 92 ++++++++++ src/openvic-simulation/interface/UI.hpp | 27 +++ 7 files changed, 854 insertions(+) create mode 100644 src/openvic-simulation/interface/GFX.cpp create mode 100644 src/openvic-simulation/interface/GFX.hpp create mode 100644 src/openvic-simulation/interface/GUI.cpp create mode 100644 src/openvic-simulation/interface/GUI.hpp create mode 100644 src/openvic-simulation/interface/LoadBase.hpp create mode 100644 src/openvic-simulation/interface/UI.cpp create mode 100644 src/openvic-simulation/interface/UI.hpp (limited to 'src/openvic-simulation/interface') diff --git a/src/openvic-simulation/interface/GFX.cpp b/src/openvic-simulation/interface/GFX.cpp new file mode 100644 index 0000000..24f4b21 --- /dev/null +++ b/src/openvic-simulation/interface/GFX.cpp @@ -0,0 +1,98 @@ +#include "GFX.hpp" + +using namespace OpenVic; +using namespace OpenVic::GFX; +using namespace OpenVic::NodeTools; + +Font::Font(std::string_view new_identifier, colour_t new_colour, std::string_view new_fontname) + : HasIdentifierAndColour { new_identifier, new_colour, false, true }, fontname { new_fontname } {} + +node_callback_t Sprite::expect_sprite(callback_t&&> callback) { + return expect_dictionary_keys( + "spriteType", ZERO_OR_MORE, _expect_instance(callback), + "progressbartype", ZERO_OR_MORE, _expect_instance(callback), + "PieChartType", ZERO_OR_MORE, _expect_instance(callback), + "LineChartType", ZERO_OR_MORE, _expect_instance(callback), + "textSpriteType", ZERO_OR_MORE, _expect_instance(callback), + "maskedShieldType", ZERO_OR_MORE, _expect_instance(callback), + "corneredTileSpriteType", ZERO_OR_MORE, success_callback, + "tileSpriteType", ZERO_OR_MORE, success_callback, + "BarChartType", ZERO_OR_MORE, success_callback, + "scrollingSprite", ZERO_OR_MORE, success_callback + ); +} + +TextureSprite::TextureSprite() : texture_file {}, no_of_frames { NO_FRAMES } {} + +bool TextureSprite::_fill_key_map(key_map_t& key_map) { + bool ret = Sprite::_fill_key_map(key_map); + ret &= add_key_map_entries(key_map, + "texturefile", ZERO_OR_ONE, expect_string(assign_variable_callback_string(texture_file)), + "textureFile", ZERO_OR_ONE, expect_string(assign_variable_callback_string(texture_file)), + "noOfFrames", ZERO_OR_ONE, expect_uint(assign_variable_callback(no_of_frames)), + + "norefcount", ZERO_OR_ONE, success_callback, + "effectFile", ZERO_OR_ONE, success_callback, + "allwaystransparent", ZERO_OR_ONE, success_callback, + "transparencecheck", ZERO_OR_ONE, success_callback, + "loadType", ZERO_OR_ONE, success_callback, + "clicksound", ZERO_OR_ONE, success_callback + ); + return ret; +} + +ProgressBar::ProgressBar() +: back_colour {}, back_texture_file {}, + progress_colour {}, progress_texture_file {}, + size {} {} + +bool ProgressBar::_fill_key_map(key_map_t& key_map) { + bool ret = Sprite::_fill_key_map(key_map); + ret &= add_key_map_entries(key_map, + "color", ONE_EXACTLY, expect_colour(assign_variable_callback(back_colour)), + "colortwo", ONE_EXACTLY, expect_colour(assign_variable_callback(progress_colour)), + "textureFile1", ZERO_OR_ONE, expect_string(assign_variable_callback_string(back_texture_file)), + "textureFile2", ZERO_OR_ONE, expect_string(assign_variable_callback_string(progress_texture_file)), + "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)), + + "effectFile", ONE_EXACTLY, success_callback, + "allwaystransparent", ZERO_OR_ONE, success_callback, + "loadType", ZERO_OR_ONE, success_callback, + "horizontal", ZERO_OR_ONE, success_callback + ); + return ret; +} + +PieChart::PieChart() : size {} {} + +bool PieChart::_fill_key_map(key_map_t& key_map) { + bool ret = Sprite::_fill_key_map(key_map); + ret &= add_key_map_entries(key_map, "size", ONE_EXACTLY, expect_uint(assign_variable_callback(size))); + return ret; +} + +LineChart::LineChart() : size {}, linewidth {} {} + +bool LineChart::_fill_key_map(key_map_t& key_map) { + bool ret = Sprite::_fill_key_map(key_map); + ret &= add_key_map_entries(key_map, + "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)), + "linewidth", ONE_EXACTLY, expect_uint(assign_variable_callback(linewidth)), + "allwaystransparent", ZERO_OR_ONE, success_callback + ); + return ret; +} + +MaskedFlag::MaskedFlag() : texture_file {}, mask_file {} {} + +bool MaskedFlag::_fill_key_map(key_map_t& key_map) { + bool ret = Sprite::_fill_key_map(key_map); + ret &= add_key_map_entries(key_map, + "textureFile1", ONE_EXACTLY, expect_string(assign_variable_callback_string(texture_file)), + "textureFile2", ONE_EXACTLY, expect_string(assign_variable_callback_string(mask_file)), + "effectFile", ONE_EXACTLY, success_callback, + "allwaystransparent", ZERO_OR_ONE, success_callback, + "flipv", ZERO_OR_ONE, success_callback + ); + return ret; +} diff --git a/src/openvic-simulation/interface/GFX.hpp b/src/openvic-simulation/interface/GFX.hpp new file mode 100644 index 0000000..e155486 --- /dev/null +++ b/src/openvic-simulation/interface/GFX.hpp @@ -0,0 +1,138 @@ +#pragma once + +#include "openvic-simulation/interface/LoadBase.hpp" + +namespace OpenVic { + class UIManager; +} + +namespace OpenVic::GFX { + + struct Font : HasIdentifierAndColour { + friend class OpenVic::UIManager; + + private: + const std::string PROPERTY(fontname); + + // TODO - colorcodes, effect + + Font(std::string_view new_identifier, colour_t new_colour, std::string_view new_fontname); + + public: + Font(Font&&) = default; + }; + + using frame_t = int32_t; + static constexpr frame_t NO_FRAMES = 0; + + class Sprite : public Named<> { + protected: + Sprite() = default; + + public: + Sprite(Sprite&&) = default; + virtual ~Sprite() = default; + + OV_DETAIL_GET_BASE_TYPE(Sprite) + OV_DETAIL_GET_TYPE + + static NodeTools::node_callback_t expect_sprite(NodeTools::callback_t&&> callback); + }; + + class TextureSprite final : public Sprite { + friend std::unique_ptr std::make_unique(); + + std::string PROPERTY(texture_file); + frame_t PROPERTY(no_of_frames); + + // TODO - norefcount, effectFile, allwaystransparent + + protected: + TextureSprite(); + + bool _fill_key_map(NodeTools::key_map_t& key_map) override; + + public: + TextureSprite(TextureSprite&&) = default; + virtual ~TextureSprite() = default; + + OV_DETAIL_GET_TYPE + }; + + class ProgressBar final : public Sprite { + friend std::unique_ptr std::make_unique(); + + colour_t PROPERTY(back_colour); + std::string PROPERTY(back_texture_file); + colour_t PROPERTY(progress_colour); + std::string PROPERTY(progress_texture_file); + ivec2_t PROPERTY(size); + + // TODO - effectFile + + protected: + ProgressBar(); + + bool _fill_key_map(NodeTools::key_map_t& key_map) override; + + public: + ProgressBar(ProgressBar&&) = default; + virtual ~ProgressBar() = default; + + OV_DETAIL_GET_TYPE + }; + + class PieChart final : public Sprite { + friend std::unique_ptr std::make_unique(); + + uint32_t PROPERTY(size); + + protected: + PieChart(); + + bool _fill_key_map(NodeTools::key_map_t& key_map) override; + + public: + PieChart(PieChart&&) = default; + virtual ~PieChart() = default; + + OV_DETAIL_GET_TYPE + }; + + class LineChart final : public Sprite { + friend std::unique_ptr std::make_unique(); + + ivec2_t PROPERTY(size); + uint32_t PROPERTY(linewidth); + + protected: + LineChart(); + + bool _fill_key_map(NodeTools::key_map_t& key_map) override; + + public: + LineChart(LineChart&&) = default; + virtual ~LineChart() = default; + + OV_DETAIL_GET_TYPE + }; + + + class MaskedFlag final : public Sprite { + friend std::unique_ptr std::make_unique(); + + std::string PROPERTY(texture_file) + std::string PROPERTY(mask_file); + + protected: + MaskedFlag(); + + bool _fill_key_map(NodeTools::key_map_t& key_map) override; + + public: + MaskedFlag(MaskedFlag&&) = default; + virtual ~MaskedFlag() = default; + + OV_DETAIL_GET_TYPE + }; +} diff --git a/src/openvic-simulation/interface/GUI.cpp b/src/openvic-simulation/interface/GUI.cpp new file mode 100644 index 0000000..534f552 --- /dev/null +++ b/src/openvic-simulation/interface/GUI.cpp @@ -0,0 +1,182 @@ +#include "GUI.hpp" + +#include "openvic-simulation/interface/UI.hpp" + +using namespace OpenVic; +using namespace OpenVic::GUI; +using namespace OpenVic::NodeTools; + +Element::Element() : position {}, orientation { orientation_t::UPPER_LEFT } {} + +bool Element::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = Named::_fill_key_map(key_map, ui_manager); + using enum orientation_t; + static const string_map_t orientation_map = { + { "UPPER_LEFT", UPPER_LEFT }, { "LOWER_LEFT", LOWER_LEFT }, + { "LOWER_RIGHT", LOWER_RIGHT }, { "UPPER_RIGHT", UPPER_RIGHT }, + { "CENTER", CENTER } + }; + ret &= add_key_map_entries(key_map, + "position", ONE_EXACTLY, expect_ivec2(assign_variable_callback(position)), + "orientation", ZERO_OR_ONE, expect_string(expect_mapped_string(orientation_map, assign_variable_callback(orientation))), + "Orientation", ZERO_OR_ONE, expect_string(expect_mapped_string(orientation_map, assign_variable_callback(orientation))) + ); + return ret; +} + +bool Element::_fill_elements_key_map( + NodeTools::key_map_t& key_map, callback_t&&> callback, UIManager const& ui_manager +) { + bool ret = true; + ret &= add_key_map_entries(key_map, + "iconType", ZERO_OR_MORE, _expect_instance(callback, ui_manager), + "guiButtonType", ZERO_OR_MORE, _expect_instance(callback, ui_manager), + "checkboxType", ZERO_OR_MORE, _expect_instance(callback, ui_manager), + "textBoxType", ZERO_OR_MORE, _expect_instance(callback, ui_manager), + "instantTextBoxType", ZERO_OR_MORE, _expect_instance(callback, ui_manager), + "OverlappingElementsBoxType", ZERO_OR_MORE, _expect_instance(callback, ui_manager), + "listboxType", ZERO_OR_MORE, _expect_instance(callback, ui_manager), + "windowType", ZERO_OR_MORE, _expect_instance(callback, ui_manager), + "positionType", ZERO_OR_MORE, success_callback + ); + return ret; +} + +Scene::Scene() : elements { "scene elements" } {} + +bool Scene::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + return Element::_fill_elements_key_map(key_map, [this](std::unique_ptr&& element) -> bool { + return elements.add_item(std::move(element)); + }, ui_manager); +} + +node_callback_t Scene::expect_scene( + std::string_view scene_name, callback_t&&> callback, UIManager const& ui_manager +) { + return _expect_instance([scene_name, callback](std::unique_ptr&& scene) -> bool { + scene->_set_name(scene_name); + return callback(std::move(scene)); + }, ui_manager); +} + +Window::Window() : elements { "window elements" }, size {}, moveable { false }, fullscreen { false } {} + +bool Window::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = Element::_fill_elements_key_map(key_map, [this](std::unique_ptr&& element) -> bool { + return elements.add_item(std::move(element)); + }, ui_manager); + ret &= Element::_fill_key_map(key_map, ui_manager); + ret &= add_key_map_entries(key_map, + "backGround", ZERO_OR_ONE, success_callback, + "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)), + "moveable", ONE_EXACTLY, expect_int_bool(assign_variable_callback(moveable)), + "dontRender", ZERO_OR_ONE, success_callback, + "horizontalBorder", ZERO_OR_ONE, success_callback, + "verticalBorder", ZERO_OR_ONE, success_callback, + "fullScreen", ZERO_OR_ONE, expect_bool(assign_variable_callback(fullscreen)) + ); + return ret; +} + +Icon::Icon() : sprite { nullptr }, frame { GFX::NO_FRAMES } {} + +bool Icon::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = Element::_fill_key_map(key_map, ui_manager); + ret &= add_key_map_entries(key_map, + "spriteType", ONE_EXACTLY, expect_string(ui_manager.expect_sprite_str(assign_variable_callback_pointer(sprite))), + "frame", ZERO_OR_ONE, expect_uint(assign_variable_callback(frame)) + ); + return ret; +} + +BaseButton::BaseButton() : sprite { nullptr } {} + +bool BaseButton::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = Element::_fill_key_map(key_map, ui_manager); + // look up sprite registry for texture sprite with name... + ret &= add_key_map_entries(key_map, + "quadTextureSprite", ONE_EXACTLY, + expect_string(ui_manager.expect_sprite_str(assign_variable_callback_pointer(sprite))), + "shortcut", ZERO_OR_ONE, success_callback + ); + return ret; +} + +Button::Button() : text {}, font { nullptr} {} + +bool Button::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = BaseButton::_fill_key_map(key_map, ui_manager); + ret &= add_key_map_entries(key_map, + "buttonText", ZERO_OR_ONE, expect_string(assign_variable_callback_string(text), true), + "buttonFont", ZERO_OR_ONE, expect_string(ui_manager.expect_font_str(assign_variable_callback_pointer(font))), + "clicksound", ZERO_OR_ONE, success_callback, + /* These are always empty in the base defines */ + "tooltip", ZERO_OR_ONE, success_callback, + "tooltipText", ZERO_OR_ONE, success_callback, + "delayedTooltipText", ZERO_OR_ONE, success_callback + ); + return ret; +} + +bool Checkbox::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = BaseButton::_fill_key_map(key_map, ui_manager); + return ret; +} + +AlignedElement::AlignedElement() : format { format_t::left } {} + +bool AlignedElement::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = Element::_fill_key_map(key_map, ui_manager); + using enum format_t; + static const string_map_t format_map = { + { "left", left }, { "right", right }, { "centre", centre }, { "center", centre } + }; + ret &= add_key_map_entries(key_map, + "format", ZERO_OR_ONE, expect_identifier(expect_mapped_string(format_map, assign_variable_callback(format)) + )); + return ret; +} + +Text::Text() : text {}, font { nullptr } {} + +bool Text::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = AlignedElement::_fill_key_map(key_map, ui_manager); + ret &= add_key_map_entries(key_map, + "text", ZERO_OR_ONE, expect_string(assign_variable_callback_string(text), true), + "font", ONE_EXACTLY, expect_string(ui_manager.expect_font_str(assign_variable_callback_pointer(font))), + "maxWidth", ONE_EXACTLY, expect_uint(assign_variable_callback(max_size.x)), + "maxHeight", ONE_EXACTLY, expect_uint(assign_variable_callback(max_size.y)), + + "borderSize", ZERO_OR_ONE, success_callback, + "fixedsize", ZERO_OR_ONE, success_callback, + + // Add warning about redundant key? + "textureFile", ZERO_OR_ONE, success_callback + ); + return ret; +} + +OverlappingElementsBox::OverlappingElementsBox() : size {} {} + +bool OverlappingElementsBox::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = AlignedElement::_fill_key_map(key_map, ui_manager); + ret &= add_key_map_entries(key_map, + "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)), + "spacing", ONE_EXACTLY, success_callback + ); + return ret; +} + +ListBox::ListBox() : size {} {} + +bool ListBox::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) { + bool ret = Element::_fill_key_map(key_map, ui_manager); + ret &= add_key_map_entries(key_map, + "backGround", ZERO_OR_ONE, success_callback, + "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)), + "spacing", ZERO_OR_ONE, success_callback, + "scrollbartype", ZERO_OR_ONE, success_callback, + "borderSize", ZERO_OR_ONE, success_callback + ); + return ret; +} diff --git a/src/openvic-simulation/interface/GUI.hpp b/src/openvic-simulation/interface/GUI.hpp new file mode 100644 index 0000000..1a76ca0 --- /dev/null +++ b/src/openvic-simulation/interface/GUI.hpp @@ -0,0 +1,235 @@ +#pragma once + +#include "openvic-simulation/interface/GFX.hpp" + +namespace OpenVic { + class UIManager; +} +namespace OpenVic::GUI { + class Scene; + + class Element : public Named { + friend class Scene; + + public: + enum class orientation_t { + UPPER_LEFT, LOWER_LEFT, LOWER_RIGHT, UPPER_RIGHT, CENTER + }; + + private: + ivec2_t PROPERTY(position); + orientation_t PROPERTY(orientation); + + protected: + Element(); + + bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override; + static bool _fill_elements_key_map( + NodeTools::key_map_t& key_map, NodeTools::callback_t&&> callback, + UIManager const& ui_manager + ); + + public: + Element(Element&&) = default; + virtual ~Element() = default; + + OV_DETAIL_GET_BASE_TYPE(Element) + OV_DETAIL_GET_TYPE + }; + + class Scene : public Named { + friend std::unique_ptr std::make_unique(); + + NamedInstanceRegistry elements; + + protected: + Scene(); + + bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override; + + public: + Scene(Scene&&) = default; + virtual ~Scene() = default; + + OV_DETAIL_GET_TYPE + + static NodeTools::node_callback_t expect_scene( + std::string_view scene_name, NodeTools::callback_t&&> callback, UIManager const& ui_manager + ); + + IDENTIFIER_REGISTRY_ACCESSORS(element) + }; + + class Window final : public Element { + friend std::unique_ptr std::make_unique(); + + NamedInstanceRegistry elements; + + ivec2_t PROPERTY(size); + bool PROPERTY(moveable); + bool PROPERTY(fullscreen); + // TODO - background, dontRender, horizontalBorder, verticalBorder + + protected: + Window(); + + bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override; + + public: + Window(Window&&) = default; + virtual ~Window() = default; + + OV_DETAIL_GET_TYPE + + IDENTIFIER_REGISTRY_ACCESSORS(element) + }; + + class Icon final : public Element { + friend std::unique_ptr std::make_unique(); + + GFX::Sprite const* PROPERTY(sprite); + GFX::frame_t PROPERTY(frame); + + protected: + Icon(); + + bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override; + + public: + Icon(Icon&&) = default; + virtual ~Icon() = default; + + OV_DETAIL_GET_TYPE + }; + + class BaseButton : public Element { + GFX::Sprite const* PROPERTY(sprite); + // TODO - shortcut + + protected: + BaseButton(); + + bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override; + + public: + BaseButton(BaseButton&&) = default; + virtual ~BaseButton() = default; + + OV_DETAIL_GET_TYPE + }; + + class Button final : public BaseButton { + friend std::unique_ptr