Files
WickedEngine/WickedEngine/wiWidget.h
T
2021-05-30 18:23:04 +02:00

389 lines
10 KiB
C++

#pragma once
#include "CommonInclude.h"
#include "wiColor.h"
#include "wiGraphicsDevice.h"
#include "wiIntersect.h"
#include "wiScene.h"
#include "wiSprite.h"
#include "wiSpriteFont.h"
#include <string>
#include <vector>
#include <functional>
struct wiEventArgs
{
XMFLOAT2 clickPos;
XMFLOAT2 startPos;
XMFLOAT2 deltaPos;
XMFLOAT2 endPos;
float fValue;
bool bValue;
int iValue;
wiColor color;
std::string sValue;
uint64_t userdata;
};
class wiWidget : public wiScene::TransformComponent
{
public:
enum WIDGETSTATE
{
IDLE, // widget is doing nothing
FOCUS, // widget got pointer dragged on or selected
ACTIVE, // widget is interacted with right now
DEACTIVATING, // widget has last been active but no more interactions are occuring
WIDGETSTATE_COUNT,
};
private:
int tooltipTimer = 0;
protected:
std::string name;
std::string tooltip;
std::string scriptTip;
bool enabled = true;
bool visible = true;
WIDGETSTATE state = IDLE;
public:
wiWidget();
virtual ~wiWidget() = default;
const std::string& GetName() const;
void SetName(const std::string& value);
const std::string GetText() const;
void SetText(const std::string& value);
void SetTooltip(const std::string& value);
void SetScriptTip(const std::string& value);
void SetPos(const XMFLOAT2& value);
void SetSize(const XMFLOAT2& value);
WIDGETSTATE GetState() const;
virtual void SetEnabled(bool val);
bool IsEnabled() const;
virtual void SetVisible(bool val);
bool IsVisible() const;
// last param default: set color for all states
void SetColor(wiColor color, WIDGETSTATE state = WIDGETSTATE_COUNT);
wiColor GetColor() const;
// last param default: set color for all states
void SetImage(std::shared_ptr<wiResource> textureResource, WIDGETSTATE state = WIDGETSTATE_COUNT);
virtual void Update(const wiCanvas& canvas, float dt);
virtual void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const = 0;
virtual void RenderTooltip(const wiCanvas& canvas, wiGraphics::CommandList cmd) const;
wiSprite sprites[WIDGETSTATE_COUNT];
wiSpriteFont font;
XMFLOAT3 translation = XMFLOAT3(0, 0, 0);
XMFLOAT3 scale = XMFLOAT3(1, 1, 1);
Hitbox2D hitBox;
wiGraphics::Rect scissorRect;
wiWidget* parent = nullptr;
void AttachTo(wiWidget* parent);
void Detach();
void Activate();
void Deactivate();
void ApplyScissor(const wiCanvas& canvas, const wiGraphics::Rect rect, wiGraphics::CommandList cmd, bool constrain_to_parent = true) const;
Hitbox2D GetPointerHitbox() const;
static void Initialize();
bool priority_change = true;
uint32_t priority = 0;
bool force_disable = false;
};
// Clickable, draggable box
class wiButton : public wiWidget
{
protected:
std::function<void(wiEventArgs args)> onClick;
std::function<void(wiEventArgs args)> onDragStart;
std::function<void(wiEventArgs args)> onDrag;
std::function<void(wiEventArgs args)> onDragEnd;
XMFLOAT2 dragStart = XMFLOAT2(0, 0);
XMFLOAT2 prevPos = XMFLOAT2(0, 0);
public:
void Create(const std::string& name);
void Update(const wiCanvas& canvas, float dt ) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void OnClick(std::function<void(wiEventArgs args)> func);
void OnDragStart(std::function<void(wiEventArgs args)> func);
void OnDrag(std::function<void(wiEventArgs args)> func);
void OnDragEnd(std::function<void(wiEventArgs args)> func);
};
// Static box that holds text
class wiLabel : public wiWidget
{
protected:
public:
void Create(const std::string& name);
void Update(const wiCanvas& canvas, float dt ) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
};
// Text input box
class wiTextInputField : public wiWidget
{
protected:
std::function<void(wiEventArgs args)> onInputAccepted;
static wiSpriteFont font_input;
public:
void Create(const std::string& name);
wiSpriteFont font_description;
void SetValue(const std::string& newValue);
void SetValue(int newValue);
void SetValue(float newValue);
const std::string GetValue();
void SetDescription(const std::string& desc) { font_description.SetText(desc); }
const std::string GetDescription() const { return font_description.GetTextA(); }
// There can only be ONE active text input field, so these methods modify the active one
static void AddInput(const char inputChar);
static void DeleteFromInput();
void Update(const wiCanvas& canvas, float dt) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void OnInputAccepted(std::function<void(wiEventArgs args)> func);
};
// Define an interval and slide the control along it
class wiSlider : public wiWidget
{
protected:
std::function<void(wiEventArgs args)> onSlide;
float start = 0, end = 1;
float step = 1000;
float value = 0;
wiTextInputField valueInputField;
public:
// start : slider minimum value
// end : slider maximum value
// defaultValue : slider default Value
// step : slider step size
void Create(float start, float end, float defaultValue, float step, const std::string& name);
wiSprite sprites_knob[WIDGETSTATE_COUNT];
void SetValue(float value);
float GetValue() const;
void SetRange(float start, float end);
void Update(const wiCanvas& canvas, float dt ) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void RenderTooltip(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void OnSlide(std::function<void(wiEventArgs args)> func);
};
// Two-state clickable box
class wiCheckBox :public wiWidget
{
protected:
std::function<void(wiEventArgs args)> onClick;
bool checked = false;
public:
void Create(const std::string& name);
wiSprite sprites_check[WIDGETSTATE_COUNT];
void SetCheck(bool value);
bool GetCheck() const;
void Update(const wiCanvas& canvas, float dt ) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void OnClick(std::function<void(wiEventArgs args)> func);
};
// Drop-down list
class wiComboBox :public wiWidget
{
protected:
std::function<void(wiEventArgs args)> onSelect;
int selected = -1;
int maxVisibleItemCount = 8;
int firstItemVisible = 0;
// While the widget is active (rolled down) these are the inner states that control behaviour
enum COMBOSTATE
{
COMBOSTATE_INACTIVE, // When the list is just being dropped down, or the widget is not active
COMBOSTATE_HOVER, // The widget is in drop-down state with the last item hovered highlited
COMBOSTATE_SELECTING, // The hovered item is clicked
COMBOSTATE_SCROLLBAR_HOVER, // scrollbar is to be selected
COMBOSTATE_SCROLLBAR_GRABBED, // scrollbar is moved
COMBOSTATE_COUNT,
} combostate = COMBOSTATE_INACTIVE;
int hovered = -1;
float scrollbar_delta = 0;
struct Item
{
std::string name;
uint64_t userdata = 0;
};
std::vector<Item> items;
float GetItemOffset(int index) const;
public:
void Create(const std::string& name);
void AddItem(const std::string& name, uint64_t userdata = 0);
void RemoveItem(int index);
void ClearItems();
void SetMaxVisibleItemCount(int value);
bool HasScrollbar() const;
void SetSelected(int index);
void SetSelectedByUserdata(uint64_t userdata);
int GetSelected() const;
std::string GetItemText(int index) const;
uint64_t GetItemUserData(int index) const;
size_t GetItemCount() const { return items.size(); }
void Update(const wiCanvas& canvas, float dt ) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void OnSelect(std::function<void(wiEventArgs args)> func);
};
// Widget container
class wiWindow :public wiWidget
{
protected:
wiButton closeButton;
wiButton minimizeButton;
wiButton resizeDragger_UpperLeft;
wiButton resizeDragger_BottomRight;
wiButton moveDragger;
wiLabel label;
std::vector<wiWidget*> widgets;
bool minimized = false;
public:
void Create(const std::string& name, bool window_controls = true);
void AddWidget(wiWidget* widget);
void RemoveWidget(wiWidget* widget);
void RemoveWidgets();
void Update(const wiCanvas& canvas, float dt ) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void RenderTooltip(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void SetVisible(bool value) override;
void SetEnabled(bool value) override;
void SetMinimized(bool value);
bool IsMinimized() const;
};
// HSV-Color Picker
class wiColorPicker : public wiWindow
{
protected:
std::function<void(wiEventArgs args)> onColorChanged;
enum COLORPICKERSTATE
{
CPS_IDLE,
CPS_HUE,
CPS_SATURATION,
} colorpickerstate = CPS_IDLE;
float hue = 0.0f; // [0, 360] degrees
float saturation = 0.0f; // [0, 1]
float luminance = 1.0f; // [0, 1]
wiTextInputField text_R;
wiTextInputField text_G;
wiTextInputField text_B;
wiTextInputField text_H;
wiTextInputField text_S;
wiTextInputField text_V;
wiSlider alphaSlider;
void FireEvents();
public:
void Create(const std::string& name, bool window_controls = true);
void Update(const wiCanvas& canvas, float dt ) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
wiColor GetPickColor() const;
void SetPickColor(wiColor value);
void OnColorChanged(std::function<void(wiEventArgs args)> func);
};
// List of items in a tree (parent-child relationships)
class wiTreeList :public wiWidget
{
public:
struct Item
{
std::string name;
int level = 0;
uint64_t userdata = 0;
bool open = false;
bool selected = false;
};
protected:
std::function<void(wiEventArgs args)> onSelect;
float list_height = 0;
float list_offset = 0;
int item_highlight = -1;
int opener_highlight = -1;
enum SCROLLBAR_STATE
{
SCROLLBAR_INACTIVE,
SCROLLBAR_HOVER,
SCROLLBAR_GRABBED,
TREESTATE_COUNT,
} scrollbar_state = SCROLLBAR_INACTIVE;
float scrollbar_delta = 0;
float scrollbar_height = 0;
float scrollbar_value = 0;
Hitbox2D GetHitbox_ListArea() const;
Hitbox2D GetHitbox_Item(int visible_count, int level) const;
Hitbox2D GetHitbox_ItemOpener(int visible_count, int level) const;
std::vector<Item> items;
float GetItemOffset(int index) const;
public:
void Create(const std::string& name);
void AddItem(const Item& item);
void ClearItems();
bool HasScrollbar() const;
void ClearSelection();
void Select(int index);
int GetItemCount() const { return (int)items.size(); }
const Item& GetItem(int index) const;
void Update(const wiCanvas& canvas, float dt) override;
void Render(const wiCanvas& canvas, wiGraphics::CommandList cmd) const override;
void OnSelect(std::function<void(wiEventArgs args)> func);
};