324 lines
11 KiB
C++
324 lines
11 KiB
C++
#pragma once
|
|
#include "util.h"
|
|
#include "event.h"
|
|
|
|
enum class kAttribute : uint16_t
|
|
{
|
|
id = const_hash("id"),
|
|
Width = const_hash("width"),
|
|
MinWidth = const_hash("min-width"),
|
|
MaxWidth = const_hash("max-width"),
|
|
Height = const_hash("height"),
|
|
MinHeight = const_hash("min-height"),
|
|
MaxHeight = const_hash("max-height"),
|
|
Divisions = const_hash("divisions"),
|
|
InnerRadius = const_hash("inner-radius"),
|
|
OuterRadius = const_hash("outer-radius"),
|
|
Grow = const_hash("grow"),
|
|
Shrink = const_hash("shrink"),
|
|
FlexDir = const_hash("dir"),
|
|
FlexWrap = const_hash("wrap"),
|
|
Padding = const_hash("pad"),
|
|
Margin = const_hash("margin"),
|
|
Color = const_hash("color"),
|
|
Thickness = const_hash("thickness"),
|
|
BorderColor = const_hash("border-color"),
|
|
Type = const_hash("type"),
|
|
Text = const_hash("text"),
|
|
TextWrapWidth = const_hash("text-wrap-width"),
|
|
FontFace = const_hash("font-face"),
|
|
FontSize = const_hash("font-size"),
|
|
Justify = const_hash("justify"),
|
|
Align = const_hash("align"),
|
|
Path = const_hash("path"),
|
|
Url = const_hash("url"),
|
|
Region = const_hash("region"),
|
|
Position = const_hash("position"),
|
|
Positioning = const_hash("positioning"),
|
|
FloodEvents = const_hash("flood-events"),
|
|
Icon = const_hash("icon"),
|
|
Selected = const_hash("selected"),
|
|
Template = const_hash("template"),
|
|
Value = const_hash("value"),
|
|
Range = const_hash("range"),
|
|
AspectRatio = const_hash("aspect-ratio"),
|
|
ComboList = const_hash("combo-list"),
|
|
Mips = const_hash("mips"),
|
|
Default = const_hash("default"),
|
|
RTL = const_hash("rtl"),
|
|
AutoSize = const_hash("autosize"),
|
|
MouseCapture = const_hash("mouse-capture"),
|
|
ScrollColor = const_hash("scroll-color"),
|
|
ScrollDir = const_hash("scroll-dir"),
|
|
Multiline = const_hash("multiline"),
|
|
TextAlign = const_hash("text-align"),
|
|
TextVerticalAlign = const_hash("text-vertical-align"),
|
|
};
|
|
|
|
enum class kWidget : uint16_t
|
|
{
|
|
Node = const_hash("node"),
|
|
Border = const_hash("border"),
|
|
Shape = const_hash("shape"),
|
|
Text = const_hash("text"),
|
|
TextInput = const_hash("text-input"),
|
|
Image = const_hash("image"),
|
|
ImageTexture = const_hash("image-texture"),
|
|
Icon = const_hash("icon"),
|
|
Button = const_hash("button"),
|
|
ButtonCustom = const_hash("button-custom"),
|
|
ComboBox = const_hash("combobox"),
|
|
SliderH = const_hash("slider-h"),
|
|
SliderV = const_hash("slider-v"),
|
|
SliderHue = const_hash("slider-hue"),
|
|
PopupMenu = const_hash("popup-menu"),
|
|
Viewport = const_hash("viewport"),
|
|
Ref = const_hash("ref"),
|
|
CheckBox = const_hash("checkbox"),
|
|
Layer = const_hash("layer"),
|
|
PanelLayer = const_hash("panel-layer"),
|
|
PanelBrush = const_hash("panel-brush"),
|
|
PanelColor = const_hash("panel-color"),
|
|
PanelStroke = const_hash("panel-stroke"),
|
|
PanelGrid = const_hash("panel-grid"),
|
|
PanelQuick = const_hash("panel-quick"),
|
|
ColorQuad = const_hash("color-quad"),
|
|
StrokePreview = const_hash("stroke-preview"),
|
|
Canvas = const_hash("canvas"),
|
|
Scroll = const_hash("scroll"),
|
|
DialogBrowse = const_hash("dialog-browse"),
|
|
DialogBrowseItem = const_hash("dialog-browse-item"),
|
|
DialogCloud = const_hash("dialog-cloud"),
|
|
DialogCloudItem = const_hash("dialog-cloud-item"),
|
|
ColorWheel = const_hash("colorwheel"),
|
|
ColorPicker = const_hash("color-picker"),
|
|
About = const_hash("about"),
|
|
Changelog = const_hash("changelog"),
|
|
UserManual = const_hash("usermanual"),
|
|
ToolBucket = const_hash("tool-bucket"),
|
|
Timeline = const_hash("timeline"),
|
|
};
|
|
|
|
class Node : public std::enable_shared_from_this<Node>
|
|
{
|
|
friend class LayoutManager;
|
|
public:
|
|
Node* m_parent{ nullptr };
|
|
YGNodeRef y_node{ nullptr };
|
|
class LayoutManager* m_manager = nullptr;
|
|
uint16_t m_nodeID = 0;
|
|
std::string m_nodeID_s;
|
|
std::vector<std::shared_ptr<Node>> m_children;
|
|
std::shared_ptr<Node> current_mouse_capture = nullptr;
|
|
std::shared_ptr<Node> current_key_capture = nullptr;
|
|
std::shared_ptr<Node> child_mouse_focus = nullptr;
|
|
bool m_mouse_captured = false;
|
|
bool m_key_captured = false;
|
|
|
|
glm::mat4 m_proj;
|
|
glm::mat4 m_mvp;
|
|
glm::mat4 m_mvp_visible;
|
|
bool m_mouse_focus = false;
|
|
bool m_mouse_inside = false;
|
|
bool m_flood_events = false;
|
|
bool m_force_mouse_capture = false;
|
|
bool m_capture_children = true; // wether to capture children events when xx_capture() is used
|
|
bool m_destroyed = false;
|
|
std::vector<std::shared_ptr<Node>> m_capture_stack;
|
|
|
|
bool m_mouse_ignore = true;
|
|
float m_zoom = 1.f;
|
|
glm::vec2 m_scale{ 1, 1 };
|
|
glm::vec2 m_pos{ 0, 0 };
|
|
glm::vec2 m_pos_origin{ 0, 0 }; // original layout position without offset
|
|
glm::vec2 m_pos_offset{ 0, 0 }; // artificial position offset for scrolling
|
|
glm::vec2 m_pos_offset_childred{ 0, 0 }; // artificial position offset for scrolling
|
|
glm::vec2 m_size{ 0, 0 };
|
|
// rect: {origin}{size}
|
|
glm::vec4 m_clip{ 0, 0, 0, 0 };
|
|
// rect: {origin}{size}
|
|
glm::vec4 m_clip_uncut{ 0, 0, 0, 0 };
|
|
std::string m_name;
|
|
bool m_display = true;
|
|
// it's actually rendering
|
|
bool m_on_screen = false;
|
|
|
|
Node(const Node&) = delete;
|
|
Node& operator=(const Node&) = delete;
|
|
Node&& operator=(Node&& o);
|
|
Node(Node&& o);
|
|
Node();
|
|
virtual ~Node();
|
|
|
|
void SetWidth(float value);
|
|
void SetWidthP(float value);
|
|
void SetHeight(float value);
|
|
void SetHeightP(float value);
|
|
void SetSize(glm::vec2 value);
|
|
void SetSize(float w, float h);
|
|
void SetMinSize(float w, float h);
|
|
void SetMaxSize(float w, float h);
|
|
void SetMinSize(glm::vec2 value);
|
|
void SetMaxSize(glm::vec2 value);
|
|
void SetMaxWidth(float value);
|
|
void SetMaxWidthP(float value);
|
|
void SetMaxHeight(float value);
|
|
void SetMaxHeightP(float value);
|
|
void SetMinWidth(float value);
|
|
void SetMinWidthP(float value);
|
|
void SetMinHeight(float value);
|
|
void SetMinHeightP(float value);
|
|
|
|
void SetPadding(float t, float r, float b, float l);
|
|
glm::vec4 GetPadding() const;
|
|
void SetMargin(float t, float r, float b, float l);
|
|
glm::vec4 GetMargin() const;
|
|
void SetPosition(float l, float t, float r, float b);
|
|
void SetPosition(float l, float t);
|
|
void SetPosition(const glm::vec2 pos);
|
|
|
|
void SetFlexGrow(float value);
|
|
void SetFlexShrink(float value);
|
|
void SetFlexDir(YGFlexDirection value);
|
|
void SetFlexWrap(YGWrap value);
|
|
void SetJustify(YGJustify value);
|
|
void SetAlign(YGAlign value);
|
|
void SetPositioning(YGPositionType value);
|
|
void SetAspectRatio(float ar);
|
|
void SetRTL(YGDirection dir);
|
|
|
|
// used in visibility switch
|
|
YGNodeRef y_placeholder = nullptr;
|
|
bool GetVisibility();
|
|
void SetVisibility(bool visible);
|
|
void ToggleVisibility();
|
|
|
|
glm::vec2 GetPosition();
|
|
float GetWidth();
|
|
float GetHeight();
|
|
glm::vec2 GetSize();
|
|
YGDirection GetRTL();
|
|
|
|
virtual void restore_context();;
|
|
virtual void clear_context();
|
|
void update(float width, float height, float zoom);
|
|
void update();
|
|
void update_internal(const glm::vec2& origin, const glm::mat4& proj, float zoom);
|
|
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
|
|
void load_internal(const tinyxml2::XMLElement* x_node);
|
|
virtual void draw();
|
|
virtual Node* clone_instantiate() const;
|
|
virtual void clone_copy(Node* dest) const;
|
|
virtual void clone_children(Node* dest) const;
|
|
virtual void clone_finalize(Node* dest) const;;
|
|
void watch(std::function<bool(Node*)> observer);
|
|
virtual void destroy();
|
|
Node* root();
|
|
void set_manager(LayoutManager* manager);
|
|
bool added_to_root();
|
|
|
|
template<class T = Node> std::shared_ptr<T> clone()
|
|
{
|
|
std::shared_ptr<T> n = std::shared_ptr<T>((T*)clone_instantiate());
|
|
clone_copy(n.get());
|
|
clone_children(n.get());
|
|
clone_finalize(n.get());
|
|
return n;
|
|
}
|
|
|
|
template<class T = Node> T* find(const char* ids)
|
|
{
|
|
uint16_t id = const_hash(ids);
|
|
if (id == m_nodeID)
|
|
return static_cast<T*>(this);
|
|
for (auto& c : m_children)
|
|
if (auto found = c->find(ids))
|
|
return static_cast<T*>(found);
|
|
return nullptr;
|
|
}
|
|
template<class T = Node> std::shared_ptr<T> find_ref(const char* ids)
|
|
{
|
|
uint16_t id = const_hash(ids);
|
|
for (auto& c : m_children)
|
|
{
|
|
if (c->m_nodeID == id)
|
|
return std::static_pointer_cast<T>(c);
|
|
else if (auto found = c->find_ref(ids))
|
|
return std::static_pointer_cast<T>(found);
|
|
}
|
|
return nullptr;
|
|
}
|
|
template<class T> T* add_child()
|
|
{
|
|
auto* n = new T;
|
|
n->set_manager(m_manager);
|
|
n->m_parent = m_parent;
|
|
n->init();
|
|
n->create();
|
|
n->loaded();
|
|
add_child(n);
|
|
return n;
|
|
}
|
|
template<class T> std::shared_ptr<T> add_child_ref()
|
|
{
|
|
auto n = std::make_shared<T>();
|
|
n->set_manager(m_manager);
|
|
n->m_parent = m_parent;
|
|
n->init();
|
|
n->create();
|
|
n->loaded();
|
|
add_child(n);
|
|
return n;
|
|
}
|
|
template<class T = Node> std::shared_ptr<T> add_child_file(const std::string& filename, const std::string& name)
|
|
{
|
|
if (auto t = load_template(filename, name))
|
|
{
|
|
add_child(t);
|
|
return std::dynamic_pointer_cast<T>(t);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
virtual void on_tick(float dt) { };
|
|
virtual kEventResult on_event(Event* e);
|
|
virtual kEventResult handle_event(Event* e);
|
|
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size, float zoom);
|
|
virtual void handle_on_screen(bool old_visibility, bool new_visibility);
|
|
virtual void handle_parent_resize(glm::vec2 old_size, glm::vec2 new_size);
|
|
virtual void create();
|
|
virtual void init();
|
|
virtual void loaded();
|
|
virtual void added(Node* parent);
|
|
virtual void removed(Node* parent);
|
|
virtual void on_child_added(Node* child) { };
|
|
virtual void on_child_removed(Node* child) { };
|
|
const Node* init_template(const char* id);
|
|
bool init_template_file(const std::string& path, const std::string& id);
|
|
std::shared_ptr<Node> load_template(const std::string& filename, const std::string& name) const;
|
|
void tick(float dt);
|
|
void app_redraw();
|
|
void add_child(Node* n);
|
|
void add_child(Node* n, int index);
|
|
void add_child(std::shared_ptr<Node> n);
|
|
void add_child(std::shared_ptr<Node> n, int index);
|
|
void remove_from_parent();
|
|
void remove_child(Node* n);
|
|
void remove_all_children();
|
|
void move_child(Node* n, int index);
|
|
void move_child_front(Node* n);
|
|
void move_child_offset(Node* n, int offset);
|
|
int get_child_index(Node* n);
|
|
Node* get_child_at(int index);
|
|
// returns {origin, size} form
|
|
glm::vec4 get_children_rect() const;
|
|
std::vector<std::shared_ptr<Node>> get_children_at_point(glm::vec2 point) const;
|
|
bool is_child_recursive(Node* o) const;
|
|
bool is_child(Node* o) const;
|
|
void mouse_capture();
|
|
void mouse_release();
|
|
void key_capture();
|
|
void key_release();
|
|
};
|
|
|