Add menu stuff
This commit is contained in:
parent
3e284af672
commit
b6f6b28c98
@ -199,6 +199,12 @@ void gui::Context::DrawText(std::string_view text, const glm::vec2& pos, uint32_
|
||||
}
|
||||
}
|
||||
|
||||
void gui::Context::DrawTextAligned(std::string_view text, const glm::vec2& pos, const glm::vec2& align, uint32_t color, float scale)
|
||||
{
|
||||
auto size = MeasureText(text) * scale;
|
||||
DrawText(text, pos + size * align, color, scale);
|
||||
}
|
||||
|
||||
void gui::Context::Render()
|
||||
{
|
||||
va_.SetVBOData(vertices_.data(), vertices_.size() * sizeof(vertices_[0]));
|
||||
|
||||
@ -36,6 +36,7 @@ public:
|
||||
|
||||
glm::vec2 MeasureText(std::string_view text);
|
||||
void DrawText(std::string_view text, const glm::vec2& pos, uint32_t color = 0xFFFFFFFF, float scale = 1.0f);
|
||||
void DrawTextAligned(std::string_view text, const glm::vec2& pos, const glm::vec2& align, uint32_t color = 0xFFFFFFFF, float scale = 1.0f);
|
||||
|
||||
void Render();
|
||||
|
||||
|
||||
120
src/gui/menu.cpp
Normal file
120
src/gui/menu.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "menu.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
// Menu
|
||||
|
||||
void gui::Menu::Draw(Context& ctx, const glm::vec2& pos) const
|
||||
{
|
||||
// TODO: draw bg
|
||||
|
||||
glm::vec2 cursor = pos;
|
||||
|
||||
for (size_t i = 0; i < items_.size(); ++i)
|
||||
{
|
||||
items_[i]->Draw(DrawMenuItemArgs(ctx, cursor, focus_ == i));
|
||||
cursor.y += items_[i]->GetSize().y;
|
||||
}
|
||||
}
|
||||
|
||||
void gui::Menu::Input(MenuInput in)
|
||||
{
|
||||
switch (in)
|
||||
{
|
||||
case MI_UP:
|
||||
SwitchFocus(-1);
|
||||
break;
|
||||
|
||||
case MI_DOWN:
|
||||
SwitchFocus(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!items_.empty())
|
||||
items_[focus_]->Input(in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 gui::Menu::MeasureSize() const
|
||||
{
|
||||
glm::vec2 size(0.0f);
|
||||
|
||||
for (const auto& item : items_)
|
||||
{
|
||||
const auto& itemsize = item->GetSize();
|
||||
size.x = glm::max(size.x, itemsize.x);
|
||||
size.y += itemsize.y;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void gui::Menu::SwitchFocus(int dir)
|
||||
{
|
||||
if (items_.empty())
|
||||
return;
|
||||
|
||||
focus_ = (focus_ + items_.size() + dir) % items_.size();
|
||||
}
|
||||
|
||||
// ButtonMenuItem
|
||||
|
||||
gui::ButtonMenuItem::ButtonMenuItem(std::string text, std::function<void()> click_cb)
|
||||
: text_(std::move(text)), click_cb_(std::move(click_cb))
|
||||
{
|
||||
size_ = glm::vec2(500.0f, 30.0f);
|
||||
}
|
||||
|
||||
void gui::ButtonMenuItem::Draw(const DrawMenuItemArgs& args) const
|
||||
{
|
||||
Super::Draw(args);
|
||||
glm::vec2 center = args.pos + glm::vec2(0.0f, size_.y * 0.5f);
|
||||
args.ctx.DrawTextAligned(text_, center, glm::vec2(0.0f, -0.5f), args.focused ? COLOR_FOCUSED : COLOR_INACTIVE);
|
||||
}
|
||||
|
||||
void gui::ButtonMenuItem::Input(MenuInput in)
|
||||
{
|
||||
if (in == MI_ENTER && click_cb_)
|
||||
click_cb_();
|
||||
}
|
||||
|
||||
// SelectMenuItem
|
||||
|
||||
gui::SelectMenuItem::SelectMenuItem(std::string text, std::function<void()> click_cb,
|
||||
std::function<void(int)> switch_cb)
|
||||
: ButtonMenuItem(std::move(text), std::move(click_cb)), switch_cb_(std::move(switch_cb))
|
||||
{
|
||||
}
|
||||
|
||||
void gui::SelectMenuItem::Draw(const DrawMenuItemArgs& args) const
|
||||
{
|
||||
Super::Draw(args);
|
||||
|
||||
char buffer[128];
|
||||
size_t len = snprintf(buffer, sizeof(buffer), "< %s >", select_text_.c_str());
|
||||
|
||||
glm::vec2 center_right = args.pos + glm::vec2(size_.x, size_.y * 0.5f);
|
||||
args.ctx.DrawTextAligned(std::string_view(buffer, len), center_right, glm::vec2(-1.0f, -0.5f),
|
||||
args.focused ? COLOR_FOCUSED : COLOR_INACTIVE);
|
||||
}
|
||||
|
||||
void gui::SelectMenuItem::Input(MenuInput in)
|
||||
{
|
||||
switch (in)
|
||||
{
|
||||
case MI_LEFT:
|
||||
if (switch_cb_)
|
||||
switch_cb_(-1);
|
||||
break;
|
||||
|
||||
case MI_RIGHT:
|
||||
if (switch_cb_)
|
||||
switch_cb_(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
Super::Input(in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
119
src/gui/menu.hpp
Normal file
119
src/gui/menu.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <concepts>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
enum MenuInput
|
||||
{
|
||||
MI_UP,
|
||||
MI_DOWN,
|
||||
MI_LEFT,
|
||||
MI_RIGHT,
|
||||
MI_BACK,
|
||||
MI_ENTER,
|
||||
};
|
||||
|
||||
class MenuItem;
|
||||
|
||||
struct DrawMenuItemArgs
|
||||
{
|
||||
Context& ctx;
|
||||
glm::vec2 pos;
|
||||
bool focused;
|
||||
|
||||
DrawMenuItemArgs(Context& ctx, const glm::vec2& pos, bool focused) : ctx(ctx), pos(pos), focused(focused) {}
|
||||
};
|
||||
|
||||
class Menu
|
||||
{
|
||||
public:
|
||||
Menu() = default;
|
||||
|
||||
template <std::derived_from<MenuItem> T, typename... TArgs>
|
||||
T& Add(TArgs&&... args)
|
||||
{
|
||||
auto item = std::make_unique<T>(std::forward<TArgs>(args)...);
|
||||
auto& item_ref = *item;
|
||||
items_.emplace_back(std::move(item));
|
||||
return item_ref;
|
||||
}
|
||||
|
||||
void Draw(Context& ctx, const glm::vec2& pos) const;
|
||||
void Input(MenuInput in);
|
||||
|
||||
glm::vec2 MeasureSize() const;
|
||||
|
||||
private:
|
||||
void SwitchFocus(int dir);
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<MenuItem>> items_;
|
||||
size_t focus_ = 0;
|
||||
|
||||
};
|
||||
|
||||
class MenuItem
|
||||
{
|
||||
public:
|
||||
constexpr static uint32_t COLOR_INACTIVE = 0xFFFFFFFF;
|
||||
constexpr static uint32_t COLOR_FOCUSED = 0xFF00FFFF;
|
||||
|
||||
MenuItem() = default;
|
||||
|
||||
virtual void Draw(const DrawMenuItemArgs& args) const {}
|
||||
virtual void Input(MenuInput in) {}
|
||||
|
||||
const glm::vec2& GetSize() const { return size_; }
|
||||
|
||||
virtual ~MenuItem() = default;
|
||||
|
||||
protected:
|
||||
glm::vec2 size_;
|
||||
|
||||
};
|
||||
|
||||
class ButtonMenuItem : public MenuItem
|
||||
{
|
||||
public:
|
||||
using Super = MenuItem;
|
||||
|
||||
ButtonMenuItem(std::string text, std::function<void()> click_cb);
|
||||
|
||||
virtual void Draw(const DrawMenuItemArgs& args) const override;
|
||||
virtual void Input(MenuInput in) override;
|
||||
|
||||
virtual ~ButtonMenuItem() = default;
|
||||
|
||||
private:
|
||||
std::string text_;
|
||||
std::function<void()> click_cb_;
|
||||
};
|
||||
|
||||
class SelectMenuItem : public ButtonMenuItem
|
||||
{
|
||||
public:
|
||||
using Super = ButtonMenuItem;
|
||||
|
||||
SelectMenuItem(std::string text, std::function<void()> click_cb, std::function<void(int)> switch_cb);
|
||||
|
||||
virtual void Draw(const DrawMenuItemArgs& args) const override;
|
||||
virtual void Input(MenuInput in) override;
|
||||
|
||||
void SetSelectionText(std::string select_text) { select_text_ = std::move(select_text); }
|
||||
|
||||
virtual ~SelectMenuItem() = default;
|
||||
|
||||
protected:
|
||||
std::string select_text_;
|
||||
std::function<void(int)> switch_cb_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user