diff --git a/include/Nazara/Widgets.hpp b/include/Nazara/Widgets.hpp index a9862c07a..eb8803692 100644 --- a/include/Nazara/Widgets.hpp +++ b/include/Nazara/Widgets.hpp @@ -34,11 +34,13 @@ #include #include #include +#include #include #include #include #include #include #include +#include #endif // NAZARA_GLOBAL_WIDGETS_HPP diff --git a/include/Nazara/Widgets/BaseWidget.hpp b/include/Nazara/Widgets/BaseWidget.hpp index 2b09c8c75..56cb3f034 100644 --- a/include/Nazara/Widgets/BaseWidget.hpp +++ b/include/Nazara/Widgets/BaseWidget.hpp @@ -19,10 +19,13 @@ namespace Nz { + class BaseWidgetStyle; class Canvas; + class WidgetTheme; - class NAZARA_WIDGETS_API BaseWidget : public Nz::Node + class NAZARA_WIDGETS_API BaseWidget : public Node { + friend BaseWidgetStyle; friend Canvas; public: @@ -70,6 +73,7 @@ namespace Nz inline const Rectf& GetRenderingRect() const; inline Vector2f GetSize() const; + const std::shared_ptr& GetTheme() const; inline float GetWidth() const; inline std::size_t GetWidgetChildCount() const; @@ -118,6 +122,7 @@ namespace Nz Rectf GetScissorRect() const; virtual bool IsFocusable() const; + inline bool IsInside(float x, float y) const; virtual void OnFocusLost(); virtual void OnFocusReceived(); virtual bool OnKeyPressed(const WindowEvent::KeyEvent& key); @@ -137,7 +142,7 @@ namespace Nz virtual void ShowChildren(bool show); private: - inline BaseWidget(); + inline BaseWidget(std::shared_ptr theme); void DestroyChild(BaseWidget* widget); void DestroyChildren(); @@ -158,6 +163,7 @@ namespace Nz std::optional m_backgroundEntity; std::size_t m_canvasIndex; std::shared_ptr m_backgroundSprite; + std::shared_ptr m_theme; std::vector m_entities; std::vector> m_children; entt::registry* m_registry; diff --git a/include/Nazara/Widgets/BaseWidget.inl b/include/Nazara/Widgets/BaseWidget.inl index 6a861e2d4..7dd7ae4c1 100644 --- a/include/Nazara/Widgets/BaseWidget.inl +++ b/include/Nazara/Widgets/BaseWidget.inl @@ -10,8 +10,9 @@ namespace Nz { - inline BaseWidget::BaseWidget() : + inline BaseWidget::BaseWidget(std::shared_ptr theme) : m_canvasIndex(InvalidCanvasIndex), + m_theme(std::move(theme)), m_registry(nullptr), m_canvas(nullptr), m_backgroundColor(Color(230, 230, 230, 255)), @@ -164,6 +165,11 @@ namespace Nz return Vector2f(GetWidth(), GetHeight()); } + inline const std::shared_ptr& BaseWidget::GetTheme() const + { + return m_theme; + } + inline float BaseWidget::GetWidth() const { return m_size.x; @@ -179,6 +185,12 @@ namespace Nz return Show(false); } + inline bool BaseWidget::IsInside(float x, float y) const + { + Rectf rect(0.f, 0.f, m_size.x, m_size.y); + return rect.Contains(x, y); + } + inline bool BaseWidget::IsVisible() const { return m_visible; diff --git a/include/Nazara/Widgets/ButtonWidget.hpp b/include/Nazara/Widgets/ButtonWidget.hpp index 8fd9cd726..de7a572e2 100644 --- a/include/Nazara/Widgets/ButtonWidget.hpp +++ b/include/Nazara/Widgets/ButtonWidget.hpp @@ -8,9 +8,10 @@ #define NAZARA_WIDGETS_BUTTONWIDGET_HPP #include -#include +#include #include #include +#include namespace Nz { @@ -25,18 +26,7 @@ namespace Nz ButtonWidget(ButtonWidget&&) = default; ~ButtonWidget() = default; - inline const Color& GetColor() const; - inline const Color& GetCornerColor() const; - inline const Color& GetHoverColor() const; - inline const Color& GetHoverCornerColor() const; - inline const Color& GetPressColor() const; - inline const Color& GetPressCornerColor() const; - - inline void SetColor(const Color& color, const Color& cornerColor); - inline void SetHoverColor(const Color& color, const Color& cornerColor); - inline void SetPressColor(const Color& color, const Color& cornerColor); - - inline void UpdateText(const AbstractTextDrawer& drawer); + void UpdateText(const AbstractTextDrawer& drawer); ButtonWidget& operator=(const ButtonWidget&) = delete; ButtonWidget& operator=(ButtonWidget&&) = default; @@ -51,17 +41,7 @@ namespace Nz void OnMouseButtonRelease(int x, int y, Mouse::Button button) override; void OnMouseExit() override; - std::shared_ptr m_gradientMaterialPass; - std::shared_ptr m_gradientSprite; - std::shared_ptr m_textSprite; - entt::entity m_textEntity; - entt::entity m_gradientEntity; - Color m_color; - Color m_cornerColor; - Color m_hoverColor; - Color m_hoverCornerColor; - Color m_pressColor; - Color m_pressCornerColor; + std::unique_ptr m_style; }; } diff --git a/include/Nazara/Widgets/ButtonWidget.inl b/include/Nazara/Widgets/ButtonWidget.inl index ba260f863..d6e1316ba 100644 --- a/include/Nazara/Widgets/ButtonWidget.inl +++ b/include/Nazara/Widgets/ButtonWidget.inl @@ -7,68 +7,6 @@ namespace Nz { - inline const Color& ButtonWidget::GetColor() const - { - return m_color; - } - - inline const Color& ButtonWidget::GetCornerColor() const - { - return m_cornerColor; - } - - inline const Color& ButtonWidget::GetHoverColor() const - { - return m_hoverColor; - } - - inline const Color& ButtonWidget::GetHoverCornerColor() const - { - return m_hoverCornerColor; - } - - inline const Color& ButtonWidget::GetPressColor() const - { - return m_pressColor; - } - - inline const Color& ButtonWidget::GetPressCornerColor() const - { - return m_pressCornerColor; - } - - inline void ButtonWidget::SetColor(const Color& color, const Color& cornerColor) - { - m_color = color; - m_cornerColor = cornerColor; - - m_gradientSprite->SetColor(m_color); - m_gradientSprite->SetCornerColor(RectCorner::LeftBottom, m_cornerColor); - m_gradientSprite->SetCornerColor(RectCorner::RightBottom, m_cornerColor); - } - - inline void ButtonWidget::SetHoverColor(const Color& color, const Color& cornerColor) - { - m_hoverColor = color; - m_hoverCornerColor = cornerColor; - } - - inline void ButtonWidget::SetPressColor(const Color& color, const Color& cornerColor) - { - m_pressColor = color; - m_pressCornerColor = cornerColor; - } - - inline void ButtonWidget::UpdateText(const AbstractTextDrawer& drawer) - { - m_textSprite->Update(drawer); - - Vector2f textSize = Vector2f(m_textSprite->GetAABB().GetLengths()); - SetMinimumSize(textSize); - SetPreferredSize(textSize + Vector2f(20.f, 10.f)); - - Layout(); - } } #include diff --git a/include/Nazara/Widgets/Canvas.hpp b/include/Nazara/Widgets/Canvas.hpp index 8952266ab..5df36176c 100644 --- a/include/Nazara/Widgets/Canvas.hpp +++ b/include/Nazara/Widgets/Canvas.hpp @@ -20,7 +20,7 @@ namespace Nz friend BaseWidget; public: - inline Canvas(entt::registry& registry, EventHandler& eventHandler, CursorControllerHandle cursorController, UInt32 renderMask); + Canvas(entt::registry& registry, EventHandler& eventHandler, CursorControllerHandle cursorController, UInt32 renderMask); Canvas(const Canvas&) = delete; Canvas(Canvas&&) = delete; inline ~Canvas(); diff --git a/include/Nazara/Widgets/Canvas.inl b/include/Nazara/Widgets/Canvas.inl index 323513c38..dbafd3a4d 100644 --- a/include/Nazara/Widgets/Canvas.inl +++ b/include/Nazara/Widgets/Canvas.inl @@ -8,33 +8,6 @@ namespace Nz { - inline Canvas::Canvas(entt::registry& registry, Nz::EventHandler& eventHandler, Nz::CursorControllerHandle cursorController, UInt32 renderMask) : - m_renderMask(renderMask), - m_keyboardOwner(InvalidCanvasIndex), - m_hoveredWidget(InvalidCanvasIndex), - m_mouseOwner(InvalidCanvasIndex), - m_registry(registry), - m_cursorController(cursorController) - { - m_canvas = this; - m_widgetParent = nullptr; - - // Register ourselves as a widget to handle cursor change - RegisterToCanvas(); - - // Connect to every meaningful event - m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, this, &Canvas::OnEventKeyPressed); - m_keyReleasedSlot.Connect(eventHandler.OnKeyReleased, this, &Canvas::OnEventKeyReleased); - m_mouseButtonPressedSlot.Connect(eventHandler.OnMouseButtonPressed, this, &Canvas::OnEventMouseButtonPressed); - m_mouseButtonReleasedSlot.Connect(eventHandler.OnMouseButtonReleased, this, &Canvas::OnEventMouseButtonRelease); - m_mouseEnteredSlot.Connect(eventHandler.OnMouseEntered, this, &Canvas::OnEventMouseEntered); - m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, this, &Canvas::OnEventMouseLeft); - m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnEventMouseMoved); - m_mouseWheelMovedSlot.Connect(eventHandler.OnMouseWheelMoved, this, &Canvas::OnEventMouseWheelMoved); - m_textEnteredSlot.Connect(eventHandler.OnTextEntered, this, &Canvas::OnEventTextEntered); - m_textEditedSlot.Connect(eventHandler.OnTextEdited, this, &Canvas::OnEventTextEdited); - } - inline Canvas::~Canvas() { // Destroy children explicitly because they signal us when getting destroyed, and that can't happen after our own destruction diff --git a/include/Nazara/Widgets/DefaultWidgetTheme.hpp b/include/Nazara/Widgets/DefaultWidgetTheme.hpp new file mode 100644 index 000000000..0e7ae68aa --- /dev/null +++ b/include/Nazara/Widgets/DefaultWidgetTheme.hpp @@ -0,0 +1,69 @@ +// Copyright (C) 2021 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Widgets module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_WIDGETS_DEFAULTWIDGETTHEME_HPP +#define NAZARA_WIDGETS_DEFAULTWIDGETTHEME_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class DefaultDefaultButtonWidgetStyle; + + class NAZARA_WIDGETS_API DefaultWidgetTheme : public WidgetTheme + { + public: + DefaultWidgetTheme(); + DefaultWidgetTheme(const DefaultWidgetTheme&) = delete; + DefaultWidgetTheme(DefaultWidgetTheme&&) = default; + ~DefaultWidgetTheme() = default; + + std::unique_ptr CreateStyle(ButtonWidget* buttonWidget) const override; + + DefaultWidgetTheme& operator=(const DefaultWidgetTheme&) = delete; + DefaultWidgetTheme& operator=(DefaultWidgetTheme&&) = default; + + private: + std::shared_ptr m_buttonMaterial; + std::shared_ptr m_pressedButtonMaterial; + }; + + class NAZARA_WIDGETS_API DefaultButtonWidgetStyle : public ButtonWidgetStyle + { + public: + DefaultButtonWidgetStyle(ButtonWidget* buttonWidget, std::shared_ptr defaultMaterial, std::shared_ptr pressedMaterial); + DefaultButtonWidgetStyle(const DefaultButtonWidgetStyle&) = delete; + DefaultButtonWidgetStyle(DefaultButtonWidgetStyle&&) = default; + ~DefaultButtonWidgetStyle() = default; + + void Layout(const Vector2f& size) override; + + void OnHoverBegin() override; + void OnHoverEnd() override; + void OnPress() override; + void OnRelease() override; + + void UpdateText(const AbstractTextDrawer& drawer) override; + + DefaultButtonWidgetStyle& operator=(const DefaultButtonWidgetStyle&) = delete; + DefaultButtonWidgetStyle& operator=(DefaultButtonWidgetStyle&&) = default; + + private: + std::shared_ptr m_defaultMaterial; + std::shared_ptr m_pressedMaterial; + std::shared_ptr m_sprite; + std::shared_ptr m_textSprite; + entt::entity m_textEntity; + entt::entity m_gradientEntity; + }; +} + +#include + +#endif // NAZARA_WIDGETS_DEFAULTWIDGETTHEME_HPP diff --git a/include/Nazara/Widgets/DefaultWidgetTheme.inl b/include/Nazara/Widgets/DefaultWidgetTheme.inl new file mode 100644 index 000000000..2026d1b04 --- /dev/null +++ b/include/Nazara/Widgets/DefaultWidgetTheme.inl @@ -0,0 +1,13 @@ +// Copyright (C) 2021 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Widgets module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Widgets/WidgetTheme.hpp b/include/Nazara/Widgets/WidgetTheme.hpp new file mode 100644 index 000000000..7ad59065d --- /dev/null +++ b/include/Nazara/Widgets/WidgetTheme.hpp @@ -0,0 +1,84 @@ +// Copyright (C) 2021 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Widgets module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_WIDGETS_WIDGETTHEME_HPP +#define NAZARA_WIDGETS_WIDGETTHEME_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class AbstractTextDrawer; + class ButtonWidget; + class ButtonWidgetStyle; + + class NAZARA_WIDGETS_API WidgetTheme + { + public: + WidgetTheme() = default; + WidgetTheme(const WidgetTheme&) = delete; + WidgetTheme(WidgetTheme&&) = default; + virtual ~WidgetTheme(); + + virtual std::unique_ptr CreateStyle(ButtonWidget* buttonWidget) const = 0; + + WidgetTheme& operator=(const WidgetTheme&) = delete; + WidgetTheme& operator=(WidgetTheme&&) = default; + + private: + }; + + class NAZARA_WIDGETS_API BaseWidgetStyle + { + public: + inline BaseWidgetStyle(BaseWidget* widget); + BaseWidgetStyle(const BaseWidgetStyle&) = delete; + BaseWidgetStyle(BaseWidgetStyle&&) = default; + virtual ~BaseWidgetStyle(); + + inline entt::entity CreateEntity(); + inline void DestroyEntity(entt::entity entity); + + inline entt::registry& GetRegistry(); + inline const entt::registry& GetRegistry() const; + UInt32 GetRenderMask() const; + + BaseWidgetStyle& operator=(const BaseWidgetStyle&) = delete; + BaseWidgetStyle& operator=(BaseWidgetStyle&&) = default; + + private: + BaseWidget* m_widgetOwner; + }; + + class NAZARA_WIDGETS_API ButtonWidgetStyle : public BaseWidgetStyle + { + public: + using BaseWidgetStyle::BaseWidgetStyle; + ButtonWidgetStyle(const ButtonWidgetStyle&) = delete; + ButtonWidgetStyle(ButtonWidgetStyle&&) = default; + ~ButtonWidgetStyle() = default; + + virtual void Layout(const Vector2f& size) = 0; + + virtual void OnHoverBegin(); + virtual void OnHoverEnd(); + virtual void OnPress(); + virtual void OnRelease(); + + virtual void UpdateText(const AbstractTextDrawer& drawer) = 0; + + ButtonWidgetStyle& operator=(const ButtonWidgetStyle&) = delete; + ButtonWidgetStyle& operator=(ButtonWidgetStyle&&) = default; + + }; +} + +#include + +#endif // NAZARA_WIDGETS_WIDGETTHEME_HPP diff --git a/include/Nazara/Widgets/WidgetTheme.inl b/include/Nazara/Widgets/WidgetTheme.inl new file mode 100644 index 000000000..9f1941592 --- /dev/null +++ b/include/Nazara/Widgets/WidgetTheme.inl @@ -0,0 +1,36 @@ +// Copyright (C) 2021 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Widgets module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline BaseWidgetStyle::BaseWidgetStyle(BaseWidget* widget) : + m_widgetOwner(widget) + { + } + + inline entt::entity BaseWidgetStyle::CreateEntity() + { + return m_widgetOwner->CreateEntity(); + } + + inline void BaseWidgetStyle::DestroyEntity(entt::entity entity) + { + m_widgetOwner->DestroyEntity(entity); + } + + inline entt::registry& BaseWidgetStyle::GetRegistry() + { + return m_widgetOwner->GetRegistry(); + } + + inline const entt::registry& BaseWidgetStyle::GetRegistry() const + { + return m_widgetOwner->GetRegistry(); + } +} + +#include diff --git a/src/Nazara/Widgets/BaseWidget.cpp b/src/Nazara/Widgets/BaseWidget.cpp index fdbe2ce43..2d124817f 100644 --- a/src/Nazara/Widgets/BaseWidget.cpp +++ b/src/Nazara/Widgets/BaseWidget.cpp @@ -29,7 +29,7 @@ namespace Nz * This will also register the widget to the canvas owning the top-most widget. */ BaseWidget::BaseWidget(BaseWidget* parent) : - BaseWidget() + BaseWidget(parent->GetTheme()) { NazaraAssert(parent, "Invalid parent"); NazaraAssert(parent->GetCanvas(), "Parent has no canvas"); @@ -46,6 +46,15 @@ namespace Nz */ BaseWidget::~BaseWidget() { + if (m_registry) + { + for (WidgetEntity& entity : m_entities) + { + if (m_registry->valid(entity.handle)) + m_registry->destroy(entity.handle); + } + } + UnregisterFromCanvas(); } diff --git a/src/Nazara/Widgets/ButtonWidget.cpp b/src/Nazara/Widgets/ButtonWidget.cpp index c759965c3..c8a18dcda 100644 --- a/src/Nazara/Widgets/ButtonWidget.cpp +++ b/src/Nazara/Widgets/ButtonWidget.cpp @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -15,31 +17,20 @@ namespace Nz { ButtonWidget::ButtonWidget(BaseWidget* parent) : - BaseWidget(parent), - m_color { 74, 74, 74 }, - m_cornerColor { 180, 180, 180 }, - m_hoverColor { 128, 128, 128 }, - m_hoverCornerColor { 180, 180, 180 }, - m_pressColor { 180, 180, 180 }, - m_pressCornerColor { 74, 74, 74 } + BaseWidget(parent) { - entt::registry& registry = GetRegistry(); - UInt32 renderMask = GetCanvas()->GetRenderMask(); + m_style = GetTheme()->CreateStyle(this); - m_gradientSprite = std::make_shared(Widgets::Instance()->GetOpaqueMaterial()); - m_gradientSprite->SetColor(m_color); - m_gradientSprite->SetCornerColor(RectCorner::LeftBottom, m_cornerColor); - m_gradientSprite->SetCornerColor(RectCorner::RightBottom, m_cornerColor); + Layout(); + } - m_gradientEntity = CreateEntity(); - registry.emplace(m_gradientEntity).SetParent(this); - registry.emplace(m_gradientEntity).AttachRenderable(m_gradientSprite, renderMask); + void ButtonWidget::UpdateText(const AbstractTextDrawer& drawer) + { + m_style->UpdateText(drawer); - m_textSprite = std::make_shared(Widgets::Instance()->GetTransparentMaterial()); - - m_textEntity = CreateEntity(); - registry.emplace(m_textEntity).SetParent(this); - registry.emplace(m_textEntity).AttachRenderable(m_textSprite, renderMask); + Vector2f size(drawer.GetBounds().GetLengths()); + SetMinimumSize(size); + SetPreferredSize(size + Vector2f(20.f, 10.f)); Layout(); } @@ -47,49 +38,35 @@ namespace Nz void ButtonWidget::Layout() { BaseWidget::Layout(); - - Vector2f size = GetSize(); - m_gradientSprite->SetSize(size); - - entt::registry& registry = GetRegistry(); - - Boxf textBox = m_textSprite->GetAABB(); - registry.get(m_textEntity).SetPosition(size.x / 2.f - textBox.width / 2.f, size.y / 2.f - textBox.height / 2.f); + m_style->Layout(GetSize()); } void ButtonWidget::OnMouseButtonPress(int /*x*/, int /*y*/, Mouse::Button button) { if (button == Mouse::Left) - { - m_gradientSprite->SetColor(m_pressColor); - m_gradientSprite->SetCornerColor(RectCorner::LeftBottom, m_pressCornerColor); - m_gradientSprite->SetCornerColor(RectCorner::RightBottom, m_pressCornerColor); - } + m_style->OnPress(); } - void ButtonWidget::OnMouseButtonRelease(int /*x*/, int /*y*/, Mouse::Button button) + void ButtonWidget::OnMouseButtonRelease(int x, int y, Mouse::Button button) { if (button == Mouse::Left) { - m_gradientSprite->SetColor(m_hoverColor); - m_gradientSprite->SetCornerColor(RectCorner::LeftBottom, m_hoverCornerColor); - m_gradientSprite->SetCornerColor(RectCorner::RightBottom, m_hoverCornerColor); + m_style->OnRelease(); - OnButtonTrigger(this); + // If user clicks inside button and holds it outside, a release mouse button event will be triggered outside of the widget + // we don't want this to trigger the button, so double-check + if (IsInside(x, y)) + OnButtonTrigger(this); } } void ButtonWidget::OnMouseEnter() { - m_gradientSprite->SetColor(m_hoverColor); - m_gradientSprite->SetCornerColor(RectCorner::LeftBottom, m_hoverCornerColor); - m_gradientSprite->SetCornerColor(RectCorner::RightBottom, m_hoverCornerColor); + m_style->OnHoverBegin(); } void ButtonWidget::OnMouseExit() { - m_gradientSprite->SetColor(m_color); - m_gradientSprite->SetCornerColor(RectCorner::LeftBottom, m_cornerColor); - m_gradientSprite->SetCornerColor(RectCorner::RightBottom, m_cornerColor); + m_style->OnHoverEnd(); } } diff --git a/src/Nazara/Widgets/Canvas.cpp b/src/Nazara/Widgets/Canvas.cpp index cb9f332d5..e2d180469 100644 --- a/src/Nazara/Widgets/Canvas.cpp +++ b/src/Nazara/Widgets/Canvas.cpp @@ -3,11 +3,40 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include namespace Nz { + Canvas::Canvas(entt::registry& registry, Nz::EventHandler& eventHandler, Nz::CursorControllerHandle cursorController, UInt32 renderMask) : + BaseWidget(std::make_shared()), + m_renderMask(renderMask), + m_keyboardOwner(InvalidCanvasIndex), + m_hoveredWidget(InvalidCanvasIndex), + m_mouseOwner(InvalidCanvasIndex), + m_registry(registry), + m_cursorController(cursorController) + { + m_canvas = this; + m_widgetParent = nullptr; + + // Register ourselves as a widget to handle cursor change + RegisterToCanvas(); + + // Connect to every meaningful event + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, this, &Canvas::OnEventKeyPressed); + m_keyReleasedSlot.Connect(eventHandler.OnKeyReleased, this, &Canvas::OnEventKeyReleased); + m_mouseButtonPressedSlot.Connect(eventHandler.OnMouseButtonPressed, this, &Canvas::OnEventMouseButtonPressed); + m_mouseButtonReleasedSlot.Connect(eventHandler.OnMouseButtonReleased, this, &Canvas::OnEventMouseButtonRelease); + m_mouseEnteredSlot.Connect(eventHandler.OnMouseEntered, this, &Canvas::OnEventMouseEntered); + m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, this, &Canvas::OnEventMouseLeft); + m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnEventMouseMoved); + m_mouseWheelMovedSlot.Connect(eventHandler.OnMouseWheelMoved, this, &Canvas::OnEventMouseWheelMoved); + m_textEnteredSlot.Connect(eventHandler.OnTextEntered, this, &Canvas::OnEventTextEntered); + m_textEditedSlot.Connect(eventHandler.OnTextEdited, this, &Canvas::OnEventTextEdited); + } + std::size_t Canvas::RegisterWidget(BaseWidget* widget) { WidgetEntry box; diff --git a/src/Nazara/Widgets/DefaultWidgetTheme.cpp b/src/Nazara/Widgets/DefaultWidgetTheme.cpp new file mode 100644 index 000000000..5fc0f7a1a --- /dev/null +++ b/src/Nazara/Widgets/DefaultWidgetTheme.cpp @@ -0,0 +1,121 @@ +// Copyright (C) 2021 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Widgets module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace + { + const UInt8 ButtonImage[] = { + #include + }; + + const UInt8 ButtonPressedImage[] = { + #include + }; + } + + DefaultWidgetTheme::DefaultWidgetTheme() + { + TextureParams texParams; + texParams.renderDevice = Graphics::Instance()->GetRenderDevice(); + texParams.loadFormat = PixelFormat::RGBA8_SRGB; + + // Button material + { + std::shared_ptr buttonMaterialPass = std::make_shared(BasicMaterial::GetSettings()); + buttonMaterialPass->EnableDepthBuffer(true); + buttonMaterialPass->EnableDepthWrite(false); + + m_buttonMaterial = std::make_shared(); + m_buttonMaterial->AddPass("ForwardPass", buttonMaterialPass); + + BasicMaterial buttonBasicMat(*buttonMaterialPass); + buttonBasicMat.SetDiffuseMap(Texture::LoadFromMemory(ButtonImage, sizeof(ButtonImage), texParams)); + } + + // Button (pressed) material + { + std::shared_ptr buttonMaterialPass = std::make_shared(BasicMaterial::GetSettings()); + buttonMaterialPass->EnableDepthBuffer(true); + buttonMaterialPass->EnableDepthWrite(false); + + m_pressedButtonMaterial = std::make_shared(); + m_pressedButtonMaterial->AddPass("ForwardPass", buttonMaterialPass); + + BasicMaterial buttonBasicMat(*buttonMaterialPass); + buttonBasicMat.SetDiffuseMap(Texture::LoadFromMemory(ButtonPressedImage, sizeof(ButtonPressedImage), texParams)); + } + } + + std::unique_ptr DefaultWidgetTheme::CreateStyle(ButtonWidget* buttonWidget) const + { + return std::make_unique(buttonWidget, m_buttonMaterial, m_pressedButtonMaterial); + } + + DefaultButtonWidgetStyle::DefaultButtonWidgetStyle(ButtonWidget* buttonWidget, std::shared_ptr defaultMaterial, std::shared_ptr pressedMaterial) : + ButtonWidgetStyle(buttonWidget), + m_defaultMaterial(std::move(defaultMaterial)), + m_pressedMaterial(std::move(pressedMaterial)) + { + auto& registry = GetRegistry(); + UInt32 renderMask = GetRenderMask(); + + m_sprite = std::make_shared(m_defaultMaterial); + + m_gradientEntity = CreateEntity(); + registry.emplace(m_gradientEntity).SetParent(buttonWidget); + registry.emplace(m_gradientEntity).AttachRenderable(m_sprite, renderMask); + + m_textSprite = std::make_shared(Widgets::Instance()->GetTransparentMaterial()); + + m_textEntity = CreateEntity(); + registry.emplace(m_textEntity).SetParent(buttonWidget); + registry.emplace(m_textEntity).AttachRenderable(m_textSprite, renderMask); + } + + void DefaultButtonWidgetStyle::Layout(const Vector2f& size) + { + m_sprite->SetSize(size); + + entt::registry& registry = GetRegistry(); + + Boxf textBox = m_textSprite->GetAABB(); + registry.get(m_textEntity).SetPosition(size.x / 2.f - textBox.width / 2.f, size.y / 2.f - textBox.height / 2.f); + } + + void DefaultButtonWidgetStyle::OnHoverBegin() + { + } + + void DefaultButtonWidgetStyle::OnHoverEnd() + { + m_sprite->SetMaterial(m_defaultMaterial); + } + + void DefaultButtonWidgetStyle::OnPress() + { + m_sprite->SetMaterial(m_pressedMaterial); + } + + void DefaultButtonWidgetStyle::OnRelease() + { + m_sprite->SetMaterial(m_defaultMaterial); + } + + void DefaultButtonWidgetStyle::UpdateText(const AbstractTextDrawer& drawer) + { + m_textSprite->Update(drawer); + } +} diff --git a/src/Nazara/Widgets/WidgetTheme.cpp b/src/Nazara/Widgets/WidgetTheme.cpp new file mode 100644 index 000000000..741295e92 --- /dev/null +++ b/src/Nazara/Widgets/WidgetTheme.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2021 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Widgets module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + WidgetTheme::~WidgetTheme() = default; + + BaseWidgetStyle::~BaseWidgetStyle() = default; + + UInt32 BaseWidgetStyle::GetRenderMask() const + { + return m_widgetOwner->GetCanvas()->GetRenderMask(); + } + + void ButtonWidgetStyle::OnHoverBegin() + { + } + + void ButtonWidgetStyle::OnHoverEnd() + { + } + + void ButtonWidgetStyle::OnPress() + { + } + + void ButtonWidgetStyle::OnRelease() + { + } +}