Files
NazaraEngine/src/Nazara/Widgets/SimpleWidgetStyles.cpp

506 lines
14 KiB
C++

// Copyright (C) 2023 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 <Nazara/Widgets/SimpleWidgetStyles.hpp>
#include <Nazara/Graphics/Components/GraphicsComponent.hpp>
#include <Nazara/Utility/Components/NodeComponent.hpp>
#include <Nazara/Widgets/ButtonWidget.hpp>
#include <Nazara/Widgets/Canvas.hpp>
#include <Nazara/Widgets/CheckboxWidget.hpp>
#include <Nazara/Widgets/ImageButtonWidget.hpp>
#include <Nazara/Widgets/LabelWidget.hpp>
#include <Nazara/Widgets/ScrollAreaWidget.hpp>
#include <Nazara/Widgets/ScrollbarButtonWidget.hpp>
#include <Nazara/Widgets/ScrollbarWidget.hpp>
#include <Nazara/Widgets/Widgets.hpp>
#include <Nazara/Widgets/Debug.hpp>
namespace Nz
{
SimpleButtonWidgetStyle::SimpleButtonWidgetStyle(ButtonWidget* buttonWidget, StyleConfig config) :
ButtonWidgetStyle(buttonWidget, 2),
m_hoveredMaterial(std::move(config.hoveredMaterial)),
m_material(std::move(config.material)),
m_pressedMaterial(std::move(config.pressedMaterial)),
m_pressedHoveredMaterial(std::move(config.pressedHoveredMaterial)),
m_isHovered(false),
m_isPressed(false)
{
assert(m_material);
auto& registry = GetRegistry();
UInt32 renderMask = GetRenderMask();
SlicedSprite::Corner corner;
corner.size = Vector2f(config.cornerSize);
corner.textureCoords = Vector2f(config.cornerTexCoords);
m_sprite = std::make_shared<SlicedSprite>(m_material);
m_sprite->SetCorners(corner, corner);
m_textSprite = std::make_shared<TextSprite>(Widgets::Instance()->GetTransparentMaterial());
m_spriteEntity = CreateGraphicsEntity();
registry.get<GraphicsComponent>(m_spriteEntity).AttachRenderable(m_sprite, renderMask);
m_textEntity = CreateGraphicsEntity();
registry.get<GraphicsComponent>(m_textEntity).AttachRenderable(m_textSprite, renderMask);
}
void SimpleButtonWidgetStyle::Layout(const Vector2f& size)
{
m_sprite->SetSize(size);
entt::registry& registry = GetRegistry();
Boxf textBox = m_textSprite->GetAABB();
registry.get<NodeComponent>(m_textEntity).SetPosition(size.x / 2.f - textBox.width / 2.f, size.y / 2.f - textBox.height / 2.f);
}
void SimpleButtonWidgetStyle::OnHoverBegin()
{
UpdateMaterial(true, m_isPressed);
m_isHovered = true;
}
void SimpleButtonWidgetStyle::OnHoverEnd()
{
UpdateMaterial(false, m_isPressed);
m_isHovered = false;
}
void SimpleButtonWidgetStyle::OnPress()
{
UpdateMaterial(m_isHovered, true);
m_isPressed = true;
}
void SimpleButtonWidgetStyle::OnRelease()
{
UpdateMaterial(m_isHovered, false);
m_isPressed = false;
}
void SimpleButtonWidgetStyle::UpdateRenderLayer(int baseRenderLayer)
{
m_sprite->UpdateRenderLayer(baseRenderLayer);
m_textSprite->UpdateRenderLayer(baseRenderLayer + 1);
}
void SimpleButtonWidgetStyle::UpdateText(const AbstractTextDrawer& drawer)
{
m_textSprite->Update(drawer);
}
void SimpleButtonWidgetStyle::UpdateMaterial(bool hovered, bool pressed)
{
if (pressed && hovered && m_pressedHoveredMaterial)
m_sprite->SetMaterial(m_pressedHoveredMaterial);
else if (pressed && m_pressedMaterial)
m_sprite->SetMaterial(m_pressedMaterial);
else if (hovered && m_hoveredMaterial)
m_sprite->SetMaterial(m_hoveredMaterial);
else
m_sprite->SetMaterial(m_material);
}
SimpleCheckboxWidgetStyle::SimpleCheckboxWidgetStyle(CheckboxWidget* buttonWidget, StyleConfig config) :
CheckboxWidgetStyle(buttonWidget, 2),
m_checkMaterial(std::move(config.checkMaterial)),
m_hoveredMaterial(std::move(config.backgroundHoveredMaterial)),
m_material(std::move(config.backgroundMaterial)),
m_tristateMaterial(std::move(config.tristateMaterial)),
m_isHovered(false)
{
assert(m_material);
assert(m_checkMaterial);
assert(m_tristateMaterial);
auto& registry = GetRegistry();
UInt32 renderMask = GetRenderMask();
SlicedSprite::Corner corner;
corner.size = Vector2f(config.backgroundCornerSize);
corner.textureCoords = Vector2f(config.backgroundCornerTexCoords);
m_backgroundSprite = std::make_shared<SlicedSprite>(m_material);
m_backgroundSprite->SetCorners(corner, corner);
m_checkSprite = std::make_shared<Sprite>(m_checkMaterial);
m_backgroundEntity = CreateGraphicsEntity();
registry.get<GraphicsComponent>(m_backgroundEntity).AttachRenderable(m_backgroundSprite, renderMask);
m_checkEntity = CreateGraphicsEntity();
{
auto& gfxComponent = registry.get<GraphicsComponent>(m_checkEntity);
gfxComponent.AttachRenderable(m_checkSprite, renderMask);
gfxComponent.Hide();
}
}
void SimpleCheckboxWidgetStyle::Layout(const Vector2f& size)
{
m_backgroundSprite->SetSize(size);
Vector2f checkSize = size * 0.66f;
m_checkSprite->SetSize(checkSize);
GetRegistry().get<NodeComponent>(m_checkEntity).SetPosition(size.x / 2.f - checkSize.x / 2.f, size.y / 2.f - checkSize.y / 2.f);
}
void SimpleCheckboxWidgetStyle::OnHoverBegin()
{
m_isHovered = true;
UpdateMaterial(m_isHovered);
}
void SimpleCheckboxWidgetStyle::OnHoverEnd()
{
m_isHovered = false;
UpdateMaterial(m_isHovered);
}
void SimpleCheckboxWidgetStyle::OnNewState(CheckboxState newState)
{
switch (newState)
{
case CheckboxState::Unchecked:
{
GetRegistry().get<GraphicsComponent>(m_checkEntity).Hide();
break;
}
case CheckboxState::Tristate:
case CheckboxState::Checked:
{
m_checkSprite->SetMaterial((newState == CheckboxState::Checked) ? m_checkMaterial : m_tristateMaterial);
GetRegistry().get<GraphicsComponent>(m_checkEntity).Show();
break;
}
}
}
void SimpleCheckboxWidgetStyle::UpdateRenderLayer(int baseRenderLayer)
{
m_backgroundSprite->UpdateRenderLayer(baseRenderLayer);
m_checkSprite->UpdateRenderLayer(baseRenderLayer + 1);
}
void SimpleCheckboxWidgetStyle::UpdateMaterial(bool hovered)
{
if (hovered && m_hoveredMaterial)
m_backgroundSprite->SetMaterial(m_hoveredMaterial);
else
m_backgroundSprite->SetMaterial(m_material);
}
SimpleImageButtonWidgetStyle::SimpleImageButtonWidgetStyle(ImageButtonWidget* imageButtonWidget, StyleConfig config) :
ImageButtonWidgetStyle(imageButtonWidget, 1),
m_isHovered(false),
m_isPressed(false)
{
auto& registry = GetRegistry();
UInt32 renderMask = GetRenderMask();
SlicedSprite::Corner hoveredCorner;
hoveredCorner.size = Vector2f(config.hoveredCornerSize, config.hoveredCornerSize);
hoveredCorner.textureCoords = Vector2f(config.hoveredCornerTexCoords, config.hoveredCornerTexCoords);
m_hoveredSprite = std::make_shared<SlicedSprite>(config.hoveredMaterial);
m_hoveredSprite->SetCorners(hoveredCorner, hoveredCorner);
float imageCornerSize = imageButtonWidget->GetCornerSize();
float imageCornerTexCoords = imageButtonWidget->GetCornerTexCoords();
SlicedSprite::Corner corner;
corner.size = Vector2f(imageCornerSize, imageCornerSize);
corner.textureCoords = Vector2f(imageCornerTexCoords, imageCornerTexCoords);
m_sprite = std::make_shared<SlicedSprite>(imageButtonWidget->GetMaterial());
m_sprite->SetCorners(corner, corner);
m_sprite->SetTextureCoords(imageButtonWidget->GetTextureCoords());
m_entity = CreateGraphicsEntity();
GraphicsComponent& gfxComponent = registry.get<GraphicsComponent>(m_entity);
gfxComponent.AttachRenderable(m_sprite, renderMask);
}
void SimpleImageButtonWidgetStyle::Layout(const Vector2f& size)
{
m_hoveredSprite->SetSize(size);
m_sprite->SetSize(size);
}
void SimpleImageButtonWidgetStyle::OnHoverBegin()
{
Update(true, m_isPressed);
m_isHovered = true;
}
void SimpleImageButtonWidgetStyle::OnHoverEnd()
{
Update(false, m_isPressed);
m_isHovered = false;
}
void SimpleImageButtonWidgetStyle::OnPress()
{
Update(m_isHovered, true);
m_isPressed = true;
}
void SimpleImageButtonWidgetStyle::OnRelease()
{
Update(m_isHovered, false);
m_isPressed = false;
}
void SimpleImageButtonWidgetStyle::OnUpdate()
{
ImageButtonWidget* owner = GetOwnerWidget<ImageButtonWidget>();
// If a hovering material was added while we're being hovered, we need to detach the hovering sprite
if (owner->GetHoveredMaterial())
{
GraphicsComponent& gfxComponent = GetRegistry().get<GraphicsComponent>(m_entity);
gfxComponent.DetachRenderable(m_hoveredSprite);
}
m_sprite->SetTextureCoords(owner->GetTextureCoords());
Update(m_isHovered, m_isPressed);
}
void SimpleImageButtonWidgetStyle::UpdateRenderLayer(int baseRenderLayer)
{
m_sprite->UpdateRenderLayer(baseRenderLayer);
m_hoveredSprite->UpdateRenderLayer(baseRenderLayer + 1);
}
void SimpleImageButtonWidgetStyle::Update(bool hovered, bool pressed)
{
ImageButtonWidget* owner = GetOwnerWidget<ImageButtonWidget>();
if (pressed)
{
if (const auto& pressedMaterial = owner->GetPressedMaterial())
{
m_sprite->SetColor(owner->GetColor());
m_sprite->SetMaterial(pressedMaterial);
}
else
{
m_sprite->SetColor(owner->GetColor() * Nz::Color::FromRGB8(120, 120, 120));
m_sprite->SetMaterial(owner->GetMaterial());
}
}
else
{
m_sprite->SetColor(owner->GetColor());
m_sprite->SetMaterial(owner->GetMaterial());
}
if (hovered)
{
if (const auto& hoveredMaterial = owner->GetHoveredMaterial())
{
if (!pressed)
m_sprite->SetMaterial(hoveredMaterial);
}
else
{
if (!pressed)
m_sprite->SetMaterial(owner->GetMaterial());
if (!m_isHovered)
{
GraphicsComponent& gfxComponent = GetRegistry().get<GraphicsComponent>(m_entity);
gfxComponent.AttachRenderable(m_hoveredSprite, GetRenderMask());
}
}
}
else
{
if (!pressed)
m_sprite->SetMaterial(owner->GetMaterial());
if (m_isHovered)
{
GraphicsComponent& gfxComponent = GetRegistry().get<GraphicsComponent>(m_entity);
gfxComponent.DetachRenderable(m_hoveredSprite);
}
}
}
SimpleLabelWidgetStyle::SimpleLabelWidgetStyle(LabelWidget* labelWidget, std::shared_ptr<MaterialInstance> material, std::shared_ptr<MaterialInstance> hoveredMaterial) :
LabelWidgetStyle(labelWidget, 1),
m_hoveredMaterial(std::move(hoveredMaterial)),
m_material(std::move(material))
{
assert(m_material);
auto& registry = GetRegistry();
UInt32 renderMask = GetRenderMask();
m_textSprite = std::make_shared<TextSprite>(m_material);
m_entity = CreateGraphicsEntity();
registry.get<GraphicsComponent>(m_entity).AttachRenderable(m_textSprite, renderMask);
}
void SimpleLabelWidgetStyle::Layout(const Vector2f& size)
{
entt::registry& registry = GetRegistry();
Boxf textBox = m_textSprite->GetAABB();
registry.get<NodeComponent>(m_entity).SetPosition(size.x / 2.f - textBox.width / 2.f, size.y / 2.f - textBox.height / 2.f);
}
void SimpleLabelWidgetStyle::OnHoverBegin()
{
UpdateMaterial(true);
}
void SimpleLabelWidgetStyle::OnHoverEnd()
{
UpdateMaterial(false);
}
void SimpleLabelWidgetStyle::UpdateMaterial(bool hovered)
{
if (hovered && m_hoveredMaterial)
m_textSprite->SetMaterial(m_hoveredMaterial);
else
m_textSprite->SetMaterial(m_material);
}
void SimpleLabelWidgetStyle::UpdateRenderLayer(int baseRenderLayer)
{
m_textSprite->UpdateRenderLayer(baseRenderLayer);
}
void SimpleLabelWidgetStyle::UpdateText(const AbstractTextDrawer& drawer)
{
m_textSprite->Update(drawer);
}
SimpleScrollAreaWidgetStyle::SimpleScrollAreaWidgetStyle(ScrollAreaWidget* scrollAreaWidget) :
ScrollAreaWidgetStyle(scrollAreaWidget, 0)
{
}
void SimpleScrollAreaWidgetStyle::Layout(const Vector2f& /*size*/)
{
}
void SimpleScrollAreaWidgetStyle::UpdateRenderLayer(int /*baseRenderLayer*/)
{
}
SimpleScrollbarWidgetStyle::SimpleScrollbarWidgetStyle(ScrollbarWidget* scrollBarWidget, StyleConfig config) :
ScrollbarWidgetStyle(scrollBarWidget, 1),
m_config(std::move(config))
{
auto& registry = GetRegistry();
UInt32 renderMask = GetRenderMask();
m_backgroundScrollbarSprite = std::make_shared<Sprite>((scrollBarWidget->GetOrientation() == ScrollbarOrientation::Horizontal) ? m_config.backgroundHorizontalMaterial : m_config.backgroundVerticalMaterial);
m_backgroundScrollbarSpriteEntity = CreateGraphicsEntity();
registry.get<GraphicsComponent>(m_backgroundScrollbarSpriteEntity).AttachRenderable(m_backgroundScrollbarSprite, renderMask);
m_scrollbarSpriteEntity = CreateGraphicsEntity();
registry.get<GraphicsComponent>(m_scrollbarSpriteEntity).AttachRenderable(m_scrollbarSprite, renderMask);
}
void SimpleScrollbarWidgetStyle::Layout(const Vector2f& size)
{
m_backgroundScrollbarSprite->SetSize(size);
}
void SimpleScrollbarWidgetStyle::UpdateRenderLayer(int baseRenderLayer)
{
m_backgroundScrollbarSprite->UpdateRenderLayer(baseRenderLayer);
}
SimpleScrollbarButtonWidgetStyle::SimpleScrollbarButtonWidgetStyle(ScrollbarButtonWidget* scrollbarButtonWidget, StyleConfig config) :
ScrollbarButtonWidgetStyle(scrollbarButtonWidget, 1),
m_hoveredMaterial(std::move(config.hoveredMaterial)),
m_material(std::move(config.material)),
m_pressedMaterial(std::move(config.grabbedMaterial)),
m_pressedHoveredMaterial(std::move(config.grabbedHoveredMaterial)),
m_isHovered(false),
m_isPressed(false)
{
assert(m_material);
auto& registry = GetRegistry();
UInt32 renderMask = GetRenderMask();
SlicedSprite::Corner corner;
corner.size = Vector2f(config.cornerSize);
corner.textureCoords = Vector2f(config.cornerTexCoords);
m_sprite = std::make_shared<SlicedSprite>(m_material);
m_sprite->SetCorners(corner, corner);
m_entity = CreateGraphicsEntity();
registry.get<GraphicsComponent>(m_entity).AttachRenderable(m_sprite, renderMask);
}
void SimpleScrollbarButtonWidgetStyle::Layout(const Vector2f& size)
{
m_sprite->SetSize(size);
}
void SimpleScrollbarButtonWidgetStyle::OnHoverBegin()
{
Update(true, m_isPressed);
m_isHovered = true;
}
void SimpleScrollbarButtonWidgetStyle::OnHoverEnd()
{
Update(false, m_isPressed);
m_isHovered = false;
}
void SimpleScrollbarButtonWidgetStyle::OnGrab()
{
Update(m_isHovered, true);
m_isPressed = true;
}
void SimpleScrollbarButtonWidgetStyle::OnRelease()
{
Update(m_isHovered, false);
m_isPressed = false;
}
void SimpleScrollbarButtonWidgetStyle::UpdateRenderLayer(int baseRenderLayer)
{
m_sprite->UpdateRenderLayer(baseRenderLayer);
}
void SimpleScrollbarButtonWidgetStyle::Update(bool hovered, bool pressed)
{
if (pressed && hovered && m_pressedHoveredMaterial)
m_sprite->SetMaterial(m_pressedHoveredMaterial);
else if (pressed && m_pressedMaterial)
m_sprite->SetMaterial(m_pressedMaterial);
else if (hovered && m_hoveredMaterial)
m_sprite->SetMaterial(m_hoveredMaterial);
else
m_sprite->SetMaterial(m_material);
}
}