Compare commits

..

No commits in common. "2a2044c632abfa0f8608d32b6f0fb32deeca077f" and "b530f65f386a2cbff8bae3546bb72fe9bc6a41b7" have entirely different histories.

46 changed files with 408 additions and 1344 deletions

4
.ccls
View file

@ -1,8 +1,6 @@
clangd clang++
-std=c++17 -std=c++17
-DDEBUG -DDEBUG
-Wall
-Wconversion
-Iinclude -Iinclude
-I/usr/include/freetype2 -I/usr/include/freetype2
-I/usr/include/libpng16 -I/usr/include/libpng16

View file

@ -1,5 +1,5 @@
BasedOnStyle: Microsoft BasedOnStyle: Microsoft
AccessModifierOffset: -4 AccessModifierOffset: -3
AlignAfterOpenBracket: AlwaysBreak AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None AlignConsecutiveBitFields: None
@ -21,7 +21,7 @@ AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: No AlwaysBreakTemplateDeclarations: No
AttributeMacros: ['__unused'] AttributeMacros: ['__ununsed']
BinPackArguments: true BinPackArguments: true
BinPackParameters: true BinPackParameters: true
BitFieldColonSpacing: Both BitFieldColonSpacing: Both
@ -50,13 +50,12 @@ BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon BreakInheritanceList: AfterColon
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 120 ColumnLimit: 140
CompactNamespaces: false CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerAllOnOneLineOrOnePerLine: false
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
DeriveLineEnding: true DeriveLineEnding: true
DerivePointerAlignment: false DerivePointerAlignment: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock EmptyLineBeforeAccessModifier: LogicalBlock
FixNamespaceComments: true FixNamespaceComments: true
IncludeBlocks: Regroup IncludeBlocks: Regroup
@ -79,14 +78,13 @@ IncludeCategories:
- Regex: '^"' - Regex: '^"'
Priority: 4 Priority: 4
SortPriority: 4 SortPriority: 4
IndentAccessModifiers: false
IndentCaseBlocks: true IndentCaseBlocks: true
IndentCaseLabels: true IndentCaseLabels: true
IndentExternBlock: NoIndent IndentExternBlock: NoIndent
IndentGotoLabels: false IndentGotoLabels: false
IndentPPDirectives: BeforeHash IndentPPDirectives: BeforeHash
IndentRequires: true IndentRequires: true
IndentWidth: 4 IndentWidth: 3
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
InsertTrailingCommas: None InsertTrailingCommas: None
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: false
@ -118,6 +116,6 @@ SpacesInContainerLiterals: false
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false SpacesInSquareBrackets: false
Standard: c++17 Standard: c++17
TabWidth: 4 TabWidth: 3
UseCRLF: false UseCRLF: false
UseTab: Always UseTab: Always

1
.gitignore vendored
View file

@ -1,6 +1,5 @@
.#.* .#.*
*.kdev4 *.kdev4
*.ttf
.ccls-cache .ccls-cache
.kdev4 .kdev4

View file

@ -1,3 +0,0 @@
# UUI
Simple and efficient C++ GUI toolkit

View file

@ -1,21 +0,0 @@
* button
* scroll
* Text wrap
* Style
* Text Edition
* projected vertex/raw vertex mode (projection on GPU)
* negative absolute position (from right/bottom)
* VAO/VBO in windows (batched)
* pool/wait mode mechanism
* better font rendering : signed distance
* Rich text component : parsing html? making list of struct of texts (with style information for the rendering)

View file

@ -1,9 +1,8 @@
#pragma once #pragma once
// clang-format off // clang-format off
#define GLAD_GL_IMPLEMENTATION
#include "glad/glad.h" #include "glad/glad.h"
#define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#define GLM_FORCE_RADIANS #define GLM_FORCE_RADIANS
@ -12,8 +11,3 @@
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
// clang-format off // clang-format off
namespace GlConfig
{
constexpr unsigned int FONT_TEXTURE_UNIT = GL_TEXTURE0;
}

View file

@ -3,39 +3,17 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "uui/types.hpp" #include "window.hpp"
namespace uui namespace uui
{ {
class Window;
class Application class Application
{ {
public: public:
#ifdef DEBUG
constexpr static bool debug_mode = true;
#else
constexpr static bool debug_mode = false;
#endif
enum Implementaion
{
OPENGL
};
virtual void run() = 0; virtual void run() = 0;
virtual void create_window(int width, int height, const std::string& title, InitFunction<Window> init) = 0; // virtual std::weak_ptr<Window> add_window(int width, int height, const std::string& title) = 0;
virtual std::shared_ptr<Window> get_window(std::size_t index [[maybe_unused]]) const = 0;
virtual ~Application() {};
protected: protected:
static std::shared_ptr<Application> current_application; static bool application_created;
bool initialized;
virtual void init() = 0;
virtual void deinit() = 0;
friend std::shared_ptr<Application> create_application(Application::Implementaion implementation);
}; };
std::shared_ptr<Application> create_application(Application::Implementaion implementation);
} // namespace uui } // namespace uui

View file

@ -1,45 +1,31 @@
#pragma once #pragma once
#include <array> #include <array>
#include <memory> #include <variant>
#include "uui/types.hpp"
#include "uui/window.hpp"
namespace uui namespace uui
{ {
class Container;
class Component class Component
{ {
public: public:
virtual void set_background_color(float r, float g, float b, float a = 1.0f) = 0; Component(
const std::variant<int, float> x, const std::variant<int, float> y, const std::variant<int, float> width,
ComponentType type() { return _type; } const std::variant<int, float> height):
uui::position_t x() { return _position_x; } position_x(x),
uui::position_t y() { return _position_y; } position_y(y), size_width(width), size_height(height)
uui::size_t width() { return _width; } {
uui::size_t height() { return _height; } background_color = {0.0f, 0.0f, 0.0f, 0.0f};
}
protected:
ComponentType _type = ComponentType::UNASSIGNED;
std::shared_ptr<Window> _window;
std::size_t _window_index;
std::shared_ptr<Container> _parent;
std::size_t _parent_index;
uui::position_t _position_x;
uui::position_t _position_y;
uui::size_t _width;
uui::size_t _height;
bool _coord_all_relative;
std::array<float, 4> _background_color;
bool _initialized = false;
virtual void render() = 0; virtual void render() = 0;
protected:
std::variant<int, float> position_x;
std::variant<int, float> position_y;
std::variant<int, float> size_width;
std::variant<int, float> size_height;
std::array<float, 4> background_color;
}; };
} // namespace uui } // namespace uui

8
include/uui/config.hpp Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include "graphic_context.hpp"
namespace Config
{
constexpr unsigned int FONT_TEXTURE_UNIT = GL_TEXTURE0;
}

View file

@ -1,12 +0,0 @@
#pragma once
#include "uui/component.hpp"
#include "uui/container_interface.hpp"
#include "uui/types.hpp"
namespace uui
{
class Container: virtual public Component, virtual public ContainerInterface
{};
} // namespace uui

View file

@ -1,22 +0,0 @@
#pragma once
#include <memory>
#include <tuple>
#include "uui/types.hpp"
namespace uui
{
class Component;
class ContainerInterface
{
public:
virtual std::tuple<int, int> get_child_position(const std::size_t child_index [[maybe_unused]]) const = 0;
protected:
virtual std::size_t push_child(std::shared_ptr<Component> child) = 0;
virtual std::shared_ptr<Component> get_child(std::size_t index) const = 0;
virtual void remove_child(std::size_t index) = 0;
};
} // namespace uui

View file

@ -1,16 +0,0 @@
#pragma once
#include <string>
#include <tuple>
#include "uui/stack.hpp"
namespace uui
{
class Flex: virtual public Stack
{
protected:
virtual std::tuple<int, int> get_child_position(const std::size_t child_index) const = 0;
};
} // namespace uui

View file

@ -1,56 +0,0 @@
#pragma once
#include <string>
#include <tuple>
#include <vector>
#include <ft2build.h>
#include FT_FREETYPE_H
namespace uui
{
class Window;
class FontManager
{
friend class Window;
public:
struct character_info
{
float advance_x; // advance.x
float advance_y; // advance.y
float bitmap_width; // bitmap.width;
float bitmap_height; // bitmap.rows;
float bitmap_left; // bitmap_left;
float bitmap_top; // bitmap_top;
float texture_x; // x offset of glyph in texture coordinates
float texture_y; // y offset of glyph in texture coordinates
};
struct Font
{
character_info char_infos[256];
unsigned int atlas_texture;
unsigned int atlas_width;
unsigned int atlas_height;
};
std::vector<Font> fonts;
virtual void render_text(
const std::string& text, Font& font, float x, float y, float scale_x, float scale_y,
const std::tuple<float, float, float, float>& text_color) = 0;
virtual std::tuple<int, int> get_text_size(const std::string& text, Font& font, float scale_x, float scale_y) = 0;
protected:
static constexpr int ATLAS_MAX_WIDTH = 1024;
bool initialized;
FT_Library ft;
virtual const Font& init_font(const std::string& font_path, unsigned int font_size) = 0;
};
} // namespace uui

View file

@ -1,22 +0,0 @@
#pragma once
#include <string>
#include <tuple>
#include "uui/component.hpp"
namespace uui
{
class Label: virtual public Component
{
protected:
std::size_t font_index;
std::string text;
std::tuple<float, float, float, float> text_color;
int text_width;
int text_height;
};
} // namespace uui

View file

@ -2,32 +2,89 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <variant>
#include <vector> #include <vector>
#include "graphic_context.hpp" #include "graphic_context.hpp"
#include "uui/application.hpp" #include "uui/opengl/font_manager.hpp"
#include "uui/types.hpp"
namespace uui namespace uui
{ {
class GlWindow; class GlWindow;
class GlApplication final: virtual public Application class GlApplication
{ {
friend class GlWindow; friend class GlWindow;
public: public:
#ifdef DEBUG
constexpr static bool debug_mode = true;
#else
constexpr static bool debug_mode = false;
#endif
std::vector<std::shared_ptr<GlWindow>> windows; std::vector<std::shared_ptr<GlWindow>> windows;
GlApplication(); GlApplication();
virtual ~GlApplication() final; ~GlApplication();
void run() final; void run();
void create_window(int width, int height, const std::string& title, InitFunction<Window> init) final; std::shared_ptr<GlWindow> create_window(int width, int height, const std::string& title);
std::shared_ptr<Window> get_window(std::size_t index) const final; std::shared_ptr<GlWindow> get_window(size_t index) const;
private:
static GlApplication* application_pointer;
};
class GlLabel;
class GlComponent;
class GlWindow
{
friend class GlApplication;
friend class GlComponent;
friend class GlLabel;
public:
std::string title;
std::vector<std::shared_ptr<GlComponent>> components;
GlWindow(const GlWindow&) = delete;
GlWindow(GlWindow&&) = delete;
~GlWindow();
std::shared_ptr<GlComponent> create_component(
const std::variant<int, float> x, const std::variant<int, float> y, const std::variant<int, float> width,
const std::variant<int, float> height);
std::shared_ptr<GlLabel> create_label(
const std::variant<int, float> x, const std::variant<int, float> y, const std::string& text,
const std::tuple<float, float, float, float>& text_color);
protected: protected:
void init() final; GlApplication* app;
void deinit() final;
GlFontManager font_manager;
int width;
int height;
bool render_needed;
bool resize_needed;
bool iconified;
size_t index;
bool initialized;
GLFWwindow* glfw_window;
GLuint gl_program;
GlWindow(GlApplication* app, size_t index, int width, int height, const std::string& title);
void init();
void deinit();
void render();
static void glfw_resize_callback(GLFWwindow* window, int width, int height);
static void glfw_iconify_callback(GLFWwindow* window, int iconified);
static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
}; };
} // namespace uui } // namespace uui

View file

@ -1,27 +0,0 @@
#pragma once
#include <memory>
#include <string>
#include <tuple>
#include "uui/opengl/component.hpp"
namespace uui
{
class GlButton: public GlComponent
{
friend class GlWindow;
protected:
GlButton(
std::shared_ptr<GlWindow> window, std::size_t window_index, std::shared_ptr<GlContainer> parent,
std::size_t parent_index, const position_t x, const position_t y, const Direction direction);
GlButton(
std::shared_ptr<GlWindow> window, std::size_t window_index, const position_t x, const position_t y,
const Direction direction): GlButton(window, window_index, window, window_index, x, y, direction)
{}
virtual std::tuple<int, int> get_child_position(const std::size_t child_index) const;
};
} // namespace uui

View file

@ -2,50 +2,49 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <variant>
#include "uui/component.hpp" #include "graphic_context.hpp"
#include "uui/opengl/graphic_context.hpp" #include "window.hpp"
#include "uui/opengl/window.hpp"
#include "uui/types.hpp"
namespace uui namespace uui
{ {
class GlContainer; class GlComponent
class GlFlex;
class GlStack;
class GlComponent: public std::enable_shared_from_this<GlComponent>, virtual public Component
{ {
friend class GlContainer;
friend class GlWindow; friend class GlWindow;
friend class GlFlex;
friend class GlStack;
public: public:
virtual ~GlComponent(); GlComponent(const GlComponent&) = delete;
GlComponent(GlComponent&&) = delete;
~GlComponent();
void set_background_color(float r, float g, float b, float a = 1.0f) final; void set_background_color(float r, float g, float b, float a = 1.0f);
protected: protected:
std::shared_ptr<GlWindow> gl_window; std::shared_ptr<GlWindow> window;
std::variant<int, float> position_x;
std::variant<int, float> position_y;
std::variant<int, float> size_width;
std::variant<int, float> size_height;
bool coord_all_relative;
std::array<float, 4> background_color;
bool initialized;
GLuint gl_vbo; GLuint gl_vbo;
GLuint gl_vao; GLuint gl_vao;
GLuint gl_ebo; GLuint gl_ebo;
GlComponent( GlComponent(
std::shared_ptr<GlWindow> window, std::size_t window_index, std::shared_ptr<GlContainer> parent, std::shared_ptr<GlWindow> window, const std::variant<int, float> x, const std::variant<int, float> y,
std::size_t parent_index, const ComponentParams& params); const std::variant<int, float> width, const std::variant<int, float> height);
GlComponent(std::shared_ptr<GlWindow> window, std::size_t window_index, const ComponentParams& params):
GlComponent(window, window_index, nullptr, 0, params)
{}
GlComponent(const GlComponent&) = delete;
GlComponent(GlComponent&&) = default;
std::shared_ptr<GlComponent> getptr() { return shared_from_this(); }
virtual void render();
virtual void init(); virtual void init();
virtual void set_vbo_data(); virtual void set_vbo_data();
virtual void deinit(); virtual void deinit();
virtual void render();
virtual void on_resize(); virtual void on_resize();
}; };

View file

@ -1,18 +0,0 @@
#pragma once
#include <cstdlib>
#include <iostream>
#include <memory>
#include <vector>
#include "uui/container.hpp"
#include "uui/opengl/component.hpp"
#include "uui/opengl/container_interface.hpp"
namespace uui
{
class GlContainer: virtual public Container, virtual public GlContainerInterface
{};
} // namespace uui

View file

@ -1,28 +0,0 @@
#pragma once
#include <memory>
#include <tuple>
#include "uui/component.hpp"
#include "uui/container_interface.hpp"
#include "uui/types.hpp"
namespace uui
{
class GlComponent;
class GlContainerInterface: virtual public ContainerInterface
{
public:
virtual std::tuple<int, int> get_child_position(const std::size_t child_index [[maybe_unused]]) const override;
protected:
virtual std::size_t push_child(std::shared_ptr<Component> child) final;
std::size_t push_child(std::shared_ptr<GlComponent> child);
virtual std::shared_ptr<Component> get_child(std::size_t index) const final;
virtual void remove_child(std::size_t index) final;
virtual ~GlContainerInterface();
std::vector<std::shared_ptr<GlComponent>> components;
};
} // namespace uui

View file

@ -1,29 +0,0 @@
#pragma once
#include <memory>
#include <string>
#include <tuple>
#include "uui/flex.hpp"
#include "uui/opengl/container.hpp"
#include "uui/opengl/stack.hpp"
#include "uui/opengl/window.hpp"
namespace uui
{
class GlFlex: virtual public GlStack, virtual public Flex
{
friend class GlWindow;
protected:
GlFlex(
std::shared_ptr<GlWindow> window, std::size_t window_index, std::shared_ptr<GlContainer> parent,
std::size_t parent_index, const StackParams& params);
GlFlex(std::shared_ptr<GlWindow> window, std::size_t window_index, const StackParams& params):
GlFlex(window, window_index, nullptr, 0, params)
{}
std::tuple<int, int> get_child_position(const std::size_t child_index) const override;
};
} // namespace uui

View file

@ -5,32 +5,64 @@
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#include "uui/font_manager.hpp" #include <ft2build.h>
#include "uui/opengl/graphic_context.hpp" #include FT_FREETYPE_H
#include "graphic_context.hpp"
namespace uui namespace uui
{ {
class GlWindow; class GlWindow;
class GlFontManager final: public FontManager class GlFontManager
{ {
friend class GlWindow; friend class GlWindow;
public: public:
struct character_info
{
float advance_x; // advance.x
float advance_y; // advance.y
float bitmap_width; // bitmap.width;
float bitmap_height; // bitmap.rows;
float bitmap_left; // bitmap_left;
float bitmap_top; // bitmap_top;
float texture_x; // x offset of glyph in texture coordinates
float texture_y; // y offset of glyph in texture coordinates
};
struct Font
{
character_info char_infos[256];
GLuint atlas_texture;
unsigned int atlas_width;
unsigned int atlas_height;
};
std::vector<Font> fonts;
GlFontManager(); GlFontManager();
~GlFontManager(); ~GlFontManager();
void render_text( void render_text(
const std::string& text, Font& font, float x, float y, float scale_x, float scale_y, const std::string& text, Font& font, float x, float y, float scale_x, float scale_y,
const std::tuple<float, float, float, float>& text_color) final; const std::tuple<float, float, float, float>& text_color);
std::tuple<int, int> get_text_size(const std::string& text, Font& font, float scale_x, float scale_y) final; std::tuple<int, int> get_text_size(const std::string& text, Font& font, float scale_x, float scale_y);
private: private:
static constexpr int ATLAS_MAX_WIDTH = 1024;
bool initialized;
FT_Library ft;
GLuint gl_program; GLuint gl_program;
GLuint gl_vao; GLuint gl_vao;
GLuint gl_vbo; GLuint gl_vbo;
void init(); void init();
void deinit(); void deinit();
const Font& init_font(const std::string& font_path, unsigned int font_size); const Font& init_font(const std::string& font_path, size_t font_size);
}; };
} // namespace uui } // namespace uui

View file

@ -3,20 +3,18 @@
#include <string> #include <string>
#include <tuple> #include <tuple>
#include "uui/label.hpp"
#include "uui/opengl/component.hpp" #include "uui/opengl/component.hpp"
#include "uui/opengl/container.hpp"
#include "uui/opengl/window.hpp"
namespace uui namespace uui
{ {
class GlFlex; class GlLabel: public GlComponent
class GlStack;
class GlLabel final: virtual public GlComponent, virtual public Label
{ {
friend class GlWindow; friend class GlWindow;
friend class GlFlex;
friend class GlStack; size_t font_index;
float get_width() const;
float get_height() const;
protected: protected:
std::string text; std::string text;
@ -26,13 +24,10 @@ protected:
int text_height; int text_height;
GlLabel( GlLabel(
std::shared_ptr<GlWindow> window, std::size_t window_index, std::shared_ptr<GlContainer> parent, std::shared_ptr<GlWindow> window, const std::variant<int, float> x, const std::variant<int, float> y, const std::string& text,
std::size_t parent_index, const LabelParams& params); const std::tuple<float, float, float, float>& text_color);
GlLabel(std::shared_ptr<GlWindow> window, std::size_t window_index, const LabelParams& params):
GlLabel(window, window_index, nullptr, 0, params)
{}
void render() final; void render();
}; };
} // namespace uui } // namespace uui

View file

@ -1,32 +0,0 @@
#pragma once
#include <memory>
#include <string>
#include <tuple>
#include "uui/opengl/component.hpp"
#include "uui/opengl/container.hpp"
#include "uui/stack.hpp"
namespace uui
{
class GlStack: virtual public GlComponent, virtual public GlContainer, virtual public Stack
{
friend class GlWindow;
public:
void create_component(const StackComponentParams& params, InitFunction<Component> init) override;
void create_label(const StackLabelParams& params, InitFunction<Label> init) override;
protected:
GlStack(
std::shared_ptr<GlWindow> window, std::size_t window_index, std::shared_ptr<GlContainer> parent,
std::size_t parent_index, const StackParams& params);
GlStack(std::shared_ptr<GlWindow> window, std::size_t window_index, const StackParams& params):
GlStack(window, window_index, nullptr, 0, params)
{}
std::tuple<int, int> get_child_position(const std::size_t child_index) const override;
};
} // namespace uui

View file

@ -1,56 +1,3 @@
#pragma once #pragma once
#include "uui/opengl/application.hpp" #include "uui/opengl/application.hpp"
#include "uui/opengl/container_interface.hpp"
#include "uui/opengl/font_manager.hpp"
#include "uui/types.hpp"
#include "uui/window.hpp"
namespace uui
{
class GlComponent;
class GlContainer;
class GlFlex;
class GlLabel;
class GlStack;
class GlWindow:
public std::enable_shared_from_this<GlWindow>,
virtual public Window,
virtual public GlContainerInterface
{
friend class GlApplication;
friend class GlComponent;
friend class GlFlex;
friend class GlLabel;
friend class GlStack;
public:
GlWindow(const GlWindow&) = delete;
GlWindow(GlWindow&&) = delete;
~GlWindow();
void create_component(const ComponentParams& params, InitFunction<Component> init) final;
void create_label(const LabelParams& params, InitFunction<Label> init) final;
void create_flex(const StackParams& params, InitFunction<Flex> init) final;
void create_stack(const StackParams& params, InitFunction<Stack> init) final;
protected:
void render() final;
std::shared_ptr<GlFontManager> gl_font_manager;
GLFWwindow* glfw_window;
GLuint gl_program;
GlWindow(std::shared_ptr<Application> app, int width, int height, const std::string& title);
std::shared_ptr<GlWindow> getptr() { return shared_from_this(); }
void init();
void deinit();
static void glfw_resize_callback(GLFWwindow* window, int width, int height);
static void glfw_iconify_callback(GLFWwindow* window, int iconified);
static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
// static void glfw_mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
};
} // namespace uui

View file

@ -1,25 +0,0 @@
#pragma once
#include <string>
#include <tuple>
#include "uui/component.hpp"
#include "uui/label.hpp"
namespace uui
{
class Stack: virtual public Component
{
public:
virtual void create_component(const StackComponentParams& params, InitFunction<Component> init) = 0;
virtual void create_label(const StackLabelParams& params, InitFunction<Label> init) = 0;
protected:
Direction direction;
int content_width;
int content_height;
virtual std::tuple<int, int> get_child_position(const std::size_t child_index) const = 0;
};
} // namespace uui

View file

@ -1,46 +0,0 @@
#pragma once
#include <memory>
#include <optional>
#include <tuple>
#include "types.hpp"
namespace uui
{
struct Style
{
enum Position
{
RELATIVE,
ABSOLUTE
};
enum Alignment
{
START,
CENTER,
END
};
struct AbsolutePostion
{
std::optional<position_t> left;
std::optional<position_t> right;
std::optional<position_t> top;
std::optional<position_t> bottom;
};
// Layout
Position position;
Alignment horizontal_alignment;
Alignment vertical_alignment;
std::optional<uui::size_t> width;
std::optional<uui::size_t> height;
std::optional<uui::size_t> margin;
std::optional<uui::size_t> padding;
// For absolute positioning
std::unique_ptr<AbsolutePostion> absolute_position;
// Color
std::optional<std::tuple<float, float, float, float>> background_color;
};
} // namespace uui

View file

@ -1,67 +0,0 @@
#pragma once
#include <functional>
#include <tuple>
#include <variant>
namespace uui
{
namespace Config
{
constexpr int MOUSE_GRID_WIDTH = 20;
constexpr int MOUSE_GRID_HEIGHT = 20;
}; // namespace Config
template<typename T> using InitFunction = const std::function<void(T&)>&;
typedef std::variant<int, float> position_t;
typedef std::variant<int, float> size_t;
typedef std::tuple<float, float, float, float> color_t;
enum class ComponentType
{
UNASSIGNED,
COMPONENT,
LABEL,
FLEX,
STACK,
WINDOW
};
enum class Direction
{
HORIZONTAL,
VERTICAL
};
struct ComponentParams
{
uui::position_t x;
uui::position_t y;
uui::size_t width;
uui::size_t height;
};
struct LabelParams
{
uui::position_t x;
uui::position_t y;
const std::string& text;
const uui::color_t& text_color;
};
struct StackParams
{
const uui::position_t x;
const uui::position_t y;
const uui::Direction direction;
};
struct StackComponentParams
{
uui::size_t width;
uui::size_t height;
};
struct StackLabelParams
{
const std::string& text;
const uui::color_t& text_color;
};
} // namespace uui

View file

@ -1,9 +0,0 @@
#pragma once
#include "uui/application.hpp"
#include "uui/component.hpp"
#include "uui/flex.hpp"
#include "uui/label.hpp"
#include "uui/stack.hpp"
#include "uui/types.hpp"
#include "uui/window.hpp"

View file

@ -1,52 +1,24 @@
#pragma once #pragma once
#include <array>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include "uui/application.hpp" #include "graphic_context.hpp"
#include "uui/container_interface.hpp" #include "uui/component.hpp"
#include "uui/font_manager.hpp"
#include "uui/types.hpp"
namespace uui namespace uui
{ {
class Component; class Window
class Label;
class Flex;
class Stack;
class Window: virtual public ContainerInterface
{ {
friend class Component;
public: public:
std::shared_ptr<FontManager> font_manager; std::string title;
virtual void create_component(const ComponentParams& params, InitFunction<Component> init) = 0; virtual void add_component(const Component& box) = 0;
virtual void create_label(const LabelParams& params, InitFunction<Label> init) = 0;
virtual void create_flex(const StackParams& params, InitFunction<Flex> init) = 0;
virtual void create_stack(const StackParams& params, InitFunction<Stack> init) = 0;
const std::string& title() { return _title; }
int width() { return _width; };
int height() { return _height; };
protected: protected:
ComponentType _type = ComponentType::UNASSIGNED; GLFWwindow* glfw_window;
std::shared_ptr<Application> _app; virtual void draw() = 0;
bool _initialized;
std::string _title;
int _width;
int _height;
bool _render_needed;
bool _resize_needed;
bool _iconified;
std::array<std::array<std::vector<std::shared_ptr<Component>>, Config::MOUSE_GRID_HEIGHT>, Config::MOUSE_GRID_WIDTH>
_grid_click;
virtual void render() = 0;
}; };
} // namespace uui } // namespace uui

44
make.py
View file

@ -1,38 +1,50 @@
#! python3 #! python3
import os
from pathlib import Path from pathlib import Path
import shutil import shutil
from umake.umake import get_hash, make, Config from umake import get_hash, make
class Config:
CC = 'g++'
APPS = ['test/example_gl', 'test/benchmark_text']
IGNORE_APPS = []
JOB_COUNT = int(os.cpu_count() * 0.8)
BIN_DIR = Path('bin')
INCLUDE_DIR = Path('include')
OBJECT_DIR = Path('obj')
SOURCE_DIR = Path('src')
COMMON_FLAGS = '-std=c++17 -fno-semantic-interposition'
COMMON_DEBUG_FLAGS = '-g -DDEBUG'
COMMON_RELEASE_FLAGS = '-O2 -flto'
COMPILE_FLAGS = f'-Wall -I{INCLUDE_DIR} `pkg-config --cflags glfw3 vulkan gl x11 freetype2`'
LINK_FLAGS = '-lpthread -ldl `pkg-config --libs glfw3 vulkan gl x11 freetype2`'
PRE_COMPILE_FUNCTION = None
CPP_SOURCES = [filepath for filepath in SOURCE_DIR.rglob('*.cpp') if not filepath.name.startswith('.')]
def main(): def main():
config = Config()
def pre_compile(): def pre_compile():
# Copying OpenGL shaders # Copying OpenGL shaders
src_opengl_shader_path = config.source_dir / 'uui' / 'opengl' / 'shaders' src_opengl_shader_path = Config.SOURCE_DIR / 'uui' / 'opengl' / 'shaders'
for shader_path in ( for shader_path in (
list(src_opengl_shader_path.rglob('*.vert')) list(src_opengl_shader_path.rglob('*.vert'))
+ list(src_opengl_shader_path.rglob('*.frag'))): + list(src_opengl_shader_path.rglob('*.frag'))):
out_path = config.bin_dir / shader_path.relative_to(config.source_dir) out_path = Config.BIN_DIR / shader_path.relative_to(Config.SOURCE_DIR)
if out_path.exists() and get_hash(shader_path) == get_hash(out_path): if out_path.exists() and get_hash(shader_path) == get_hash(out_path):
continue continue
if not out_path.parent.exists(): if not out_path.parent.exists():
out_path.parent.mkdir(parents=True) out_path.parent.mkdir(parents=True)
shutil.copy(shader_path, out_path) shutil.copy(shader_path, out_path)
Config.PRE_COMPILE_FUNCTION = pre_compile
config.apps = [str(p.relative_to(Path('src')))[:-4] for p in (config.source_dir / 'test').rglob('*.cpp')] make(Config)
config.watch = True
config.common_flags = '-std=c++20 -fno-semantic-interposition'
config.common_debug_flags = '-g -Og -DDEBUG'
config.common_release_flags = '-O2 -flto=auto'
config.compile_flags = f'-Wall -Wextra -Wpedantic -Wconversion -I{config.include_dir} `pkg-config --cflags glfw3 gl x11 freetype2`'
config.link_flags = '-lpthread -ldl `pkg-config --libs glfw3 gl freetype2`'
config.pre_compile_function = pre_compile
make(config)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -1,7 +1,7 @@
MAKE_PATH="." MAKE_PATH="."
UMAKE_PATH="umake" UMAKE_PATH="umake"
.PHONY: all watch debug debug_watch clean lint .PHONY: all clean
all: all:
@PYTHONPATH=$(UMAKE_PATH) python $(MAKE_PATH)/make.py @PYTHONPATH=$(UMAKE_PATH) python $(MAKE_PATH)/make.py
@ -11,6 +11,3 @@ debug:
clean: clean:
@PYTHONPATH=$(UMAKE_PATH) python $(MAKE_PATH)/make.py --clean @PYTHONPATH=$(UMAKE_PATH) python $(MAKE_PATH)/make.py --clean
lint:
@clang-format --dry-run --Werror include/uui/*.hpp include/uui/**/*.hpp src/uui/*.cpp src/uui/**/*.cpp src/test/*.cpp

View file

@ -1,5 +1,6 @@
# UUI : micro UI Toolkit # UUI : micro UI Toolkit
* C++ + Vulkan/OpenGL * C++ + Vulkan/OpenGL
* Python binding * Python binding
@ -8,10 +9,6 @@
* Let custom rendering * Let custom rendering
* Canvas for easy drawing
* Style/Config watch option : real-time update on file change
## Technical ## Technical
@ -30,4 +27,4 @@
## Layout / Style ## Layout / Style
* CSS subset * Constraint based? padding/margin?

View file

@ -1,6 +1,8 @@
#include <iostream> #include <iostream>
#include "uui/uui.hpp" #include "uui/opengl/application.hpp"
#include "uui/opengl/component.hpp"
#include "uui/opengl/label.hpp"
using namespace std; using namespace std;
@ -8,12 +10,12 @@ int main()
{ {
try try
{ {
auto app = uui::create_application(uui::Application::OPENGL); uui::GlApplication app;
app->create_window(800, 600, "OpenGl!", [](uui::Window& window) { // uui::GlApplication app2; // exception : application already created
for(int i = 0; i < 100; i += 1) auto window = app.create_window(800, 600, "OpenGl!");
window.create_label({4 * i, 4 * i, "Hello World!", {1.0f, 1.0f, 1.0f, 0.5f}}, nullptr); for(int i = 0; i < 100; i += 1)
}); window->create_label(4*i, 4*i, "Hello World!", {1.0f, 1.0f, 1.0f, 0.5f});
app->run(); app.run();
} }
catch(const std::exception& error) catch(const std::exception& error)
{ {

View file

@ -1,6 +1,8 @@
#include <iostream> #include <iostream>
#include "uui/uui.hpp" #include "uui/opengl/application.hpp"
#include "uui/opengl/component.hpp"
#include "uui/opengl/label.hpp"
using namespace std; using namespace std;
@ -10,94 +12,36 @@ int main()
{ {
cout << "Starting example 1" << endl; cout << "Starting example 1" << endl;
{ {
auto app = uui::create_application(uui::Application::OPENGL); uui::GlApplication app;
// auto app2 = uui::create_application(uui::Application::OPENGL); // exception : application already created // uui::GlApplication app2; // exception : application already created
app->create_window(800, 600, "OpenGl!", [](uui::Window& window) { auto window = app.create_window(800, 600, "OpenGl!");
window.create_component({.x = 0, .y = 100, .width = 0.5f, .height = 50}, [](uui::Component& component) { auto comp = window->create_component(0, 100, 0.5f, 50);
component.set_background_color(0.8f, 0.1f, 0.5f); comp->set_background_color(0.8f, 0.1f, 0.5f);
}); comp = window->create_component(0.25f, 50, 0.4f, 150);
comp->set_background_color(0.3f, 0.8f, 0.4f, 0.5f);
window.create_component( auto label = window->create_label(50, 50, "Hello World!", {0.5f, 1.0f, 0.5f, 1.0f});
{.x = 0.25f, .y = 50, .width = 0.4f, .height = 150}, label->set_background_color(0.1f, 0.2f, 0.5f, 0.8f);
[](uui::Component& component) { component.set_background_color(0.3f, 0.8f, 0.4f, 0.5f); }); label = window->create_label(0.5f, 0.5f, "Hello World!", {1.0f, 1.0f, 1.0f, 0.5f});
label->set_background_color(0.5f, 0.5f, 0.1f);
window.create_label( label = window->create_label(0.75f, 0.75f, "Hello World!", {1.0f, 1.0f, 1.0f, 0.1f});
{.x = 50, .y = 50, .text = "Hello World!", .text_color = {0.5f, 1.0f, 0.5f, 1.0f}}, app.run();
[](uui::Label& label) { label.set_background_color(0.1f, 0.2f, 0.5f, 0.8f); });
window.create_label({0.5f, 0.5f, "Hello World!", {1.0f, 1.0f, 1.0f, 0.5f}}, [](uui::Label& label) {
label.set_background_color(0.5f, 0.5f, 0.1f);
});
window.create_label({0.75f, 0.75f, "Hello World!", {1.0f, 1.0f, 1.0f, 0.1f}}, {});
window.create_flex({200, 0.6f, uui::Direction::HORIZONTAL}, [](uui::Flex& flex) {
flex.create_component({.width = 100, .height = 50}, [](uui::Component& component) {
component.set_background_color(0.2f, 0.75f, 0.25f);
});
flex.create_label({.text = "test", .text_color = {0.8f, 0.2f, 0.2f, 1.0f}}, {});
flex.create_component({100, 20}, [](uui::Component& component) {
component.set_background_color(0.2f, 0.25f, 0.75f);
});
});
window.create_flex({50, 400, uui::Direction::VERTICAL}, [](uui::Flex& flex) {
flex.create_component({50, 100}, [](uui::Component& component) {
component.set_background_color(0.2f, 0.75f, 0.25f);
});
flex.create_label({"test", {0.8f, 0.2f, 0.2f, 1.0f}}, {});
flex.create_component({100, 20}, [](uui::Component& component) {
component.set_background_color(0.2f, 0.25f, 0.75f);
});
});
});
app->create_window(800, 600, "OpenGl 2", [](uui::Window& window) {
window.create_stack(
{.x = 200, .y = 0.6f, .direction = uui::Direction::HORIZONTAL}, [](uui::Stack& stack) {
stack.create_component({.width = 100, .height = 50}, [](uui::Component& component) {
component.set_background_color(0.2f, 0.75f, 0.25f);
});
stack.create_label({.text = "test", .text_color = {0.8f, 0.2f, 0.2f, 1.0f}}, {});
stack.create_component({.width = 100, .height = 20}, [](uui::Component& component) {
component.set_background_color(0.2f, 0.25f, 0.75f);
});
});
window.create_stack({.x = 50, .y = 400, .direction = uui::Direction::VERTICAL}, [](uui::Stack& stack) {
stack.create_component({.width = 100, .height = 50}, [](uui::Component& component) {
component.set_background_color(0.2f, 0.75f, 0.25f);
});
stack.create_label({.text = "test", .text_color = {0.8f, 0.2f, 0.2f, 1.0f}}, {});
stack.create_component({.width = 100, .height = 20}, [](uui::Component& component) {
component.set_background_color(0.2f, 0.25f, 0.75f);
});
});
});
app->run();
} }
cout << "\nStarting example 2" << endl; // cout << "\nStarting example 2" << endl;
{ // {
auto app = uui::create_application(uui::Application::OPENGL); // uui::GlApplication app;
app->create_window(800, 600, "OpenGl!", [](uui::Window& window) { // auto window_1 = app.create_window(800, 600, "OpenGl!");
window.create_component({0.25f, 0.25f, 0.5f, 0.5f}, [](uui::Component& component) { // auto comp = window_1->create_component(0.25f, 0.25f, 0.5f, 0.5f);
component.set_background_color(0.8f, 0.1f, 0.5f); // comp->set_background_color(0.8f, 0.1f, 0.5f);
}); // comp = window_1->create_component(0.75f, 0.75f, 0.25f, 0.25f);
window.create_component({0.75f, 0.75f, 0.25f, 0.25f}, [](uui::Component& component) { // comp->set_background_color(0.2f, 0.1f, 0.5f);
component.set_background_color(0.2f, 0.1f, 0.5f);
});
});
app->create_window(600, 600, "OpenGL 2!", [](uui::Window& window) { // auto window_2 = app.create_window(600, 600, "OpenGL 2!");
window.create_component({0, 0.5f, 100, 0.5f}, [](uui::Component& component) { // comp = window_2->create_component(0, 0.5f, 100, 0.5f);
component.set_background_color(0.2f, 0.5f, 0.3f); // comp->set_background_color(0.2f, 0.5f, 0.3f);
}); // auto label = window_2->create_label(50, 50, "Hello World!", {0.5f, 1.0f, 0.5f, 1.0f});
window.create_label({50, 50, "Hello World!", {0.5f, 1.0f, 0.5f, 1.0f}}, [](uui::Label& label) { // label->set_background_color(0.1f, 0.2f, 0.5f);
label.set_background_color(0.1f, 0.2f, 0.5f); // app.run();
}); // }
});
app->run();
}
} }
catch(const std::exception& error) catch(const std::exception& error)
{ {

View file

@ -1,15 +0,0 @@
#include "uui/uui.hpp"
int main()
{
auto app = uui::create_application(uui::Application::OPENGL);
app->create_window(800, 600, "UUI sample", [](uui::Window& window) {
window.create_component({.x = 0, .y = 0, .width = 200, .height = 100}, [](uui::Component& component) {
component.set_background_color(1.0f, 0.f, 0.f, 0.5f);
});
window.create_label(
{.x = 0.5f, .y = 0.5f, .text = "Hello world!", .text_color = {0.8f, 0.8f, 0.8f, 1.0f}}, nullptr);
});
app->run();
return 0;
}

View file

@ -1,20 +1,3 @@
#include "uui/application.hpp" #include "uui/application.hpp"
#include <stdexcept> bool uui::Application::application_created = false;
#include "uui/opengl/application.hpp"
std::shared_ptr<uui::Application> uui::Application::current_application;
std::shared_ptr<uui::Application> uui::create_application(uui::Application::Implementaion implementation)
{
switch(implementation)
{
case uui::Application::Implementaion::OPENGL:
if(uui::Application::current_application != nullptr)
throw std::runtime_error("Application error: the application already created");
std::shared_ptr<uui::Application> new_application(new uui::GlApplication());
uui::Application::current_application = new_application;
return new_application;
}
}

View file

@ -3,35 +3,17 @@
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include "uui/opengl/window.hpp" uui::GlApplication* uui::GlApplication::application_pointer = nullptr;
uui::GlApplication::GlApplication() uui::GlApplication::GlApplication()
{ {
if(application_pointer != nullptr)
throw std::runtime_error("GlApplication error: the application already created");
if constexpr(debug_mode) if constexpr(debug_mode)
std::cout << "Creating the GlApplication in debug mode" << std::endl; std::cout << "Creating the GlApplication in debug mode" << std::endl;
else else
std::cout << "Creating the GlApplication in release mode" << std::endl; std::cout << "Creating the GlApplication in release mode" << std::endl;
initialized = false;
init();
}
uui::GlApplication::~GlApplication()
{
if constexpr(debug_mode)
std::cout << "Destroying the GlApplication" << std::endl;
if(initialized)
deinit();
}
void uui::GlApplication::init()
{
if constexpr(debug_mode)
std::cout << "Initialize the GlApplication" << std::endl;
// Init GLFW // Init GLFW
// Avoiding libdecor would be better
// glfwInitHint(GLFW_WAYLAND_LIBDECOR, GLFW_WAYLAND_DISABLE_LIBDECOR);
glfwInit(); glfwInit();
// Set all the required options for GLFW // Set all the required options for GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
@ -41,24 +23,22 @@ void uui::GlApplication::init()
if constexpr(uui::GlApplication::debug_mode) if constexpr(uui::GlApplication::debug_mode)
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
initialized = true; application_pointer = this;
} }
void uui::GlApplication::deinit() uui::GlApplication::~GlApplication()
{ {
if constexpr(debug_mode) if constexpr(debug_mode)
std::cout << "Deinit the GlApplication" << std::endl; std::cout << "Destroying the GlApplication" << std::endl;
windows.clear(); windows.clear();
glfwTerminate(); glfwTerminate();
initialized = false; application_pointer = nullptr;
} }
void uui::GlApplication::run() void uui::GlApplication::run()
{ {
if constexpr(debug_mode) if constexpr(debug_mode)
std::cout << "Starting the GlApplication" << std::endl; std::cout << "Starting the GlApplication" << std::endl;
if(!initialized)
init();
auto start_time = std::chrono::high_resolution_clock::now(); auto start_time = std::chrono::high_resolution_clock::now();
auto end_time = start_time; auto end_time = start_time;
@ -71,7 +51,7 @@ void uui::GlApplication::run()
if constexpr(debug_mode) if constexpr(debug_mode)
{ {
end_time = std::chrono::high_resolution_clock::now(); end_time = std::chrono::high_resolution_clock::now();
render_duration = std::chrono::duration<float, std::milli>(end_time - start_time).count(); render_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
// std::cout << "Frame " << frame_count << ", duration: " << render_duration << std::endl; // std::cout << "Frame " << frame_count << ", duration: " << render_duration << std::endl;
if(frame_count > 0.0f && render_duration > 500.0f) if(frame_count > 0.0f && render_duration > 500.0f)
{ {
@ -95,8 +75,6 @@ void uui::GlApplication::run()
glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window); glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window);
glfwSwapInterval(1); glfwSwapInterval(1);
} }
if constexpr(debug_mode)
std::cout << "\nGlApplication closing GlWindow : " << window->title() << std::endl;
window->deinit(); window->deinit();
windows.erase(it); windows.erase(it);
it -= 1; it -= 1;
@ -107,7 +85,7 @@ void uui::GlApplication::run()
window->render(); window->render();
else else
{ {
if(window->_render_needed && !window->_iconified) if(window->render_needed && !window->iconified)
window->render(); window->render();
} }
} }
@ -117,12 +95,11 @@ void uui::GlApplication::run()
} }
if constexpr(debug_mode) if constexpr(debug_mode)
std::cout << "Ending the GlApplication" << std::endl; std::cout << "Ending the GlApplication" << std::endl;
current_application = nullptr;
} }
void uui::GlApplication::create_window(int width, int height, const std::string& title, uui::InitFunction<Window> init) std::shared_ptr<uui::GlWindow> uui::GlApplication::create_window(int width, int height, const std::string& title)
{ {
auto window = std::shared_ptr<uui::GlWindow>(new uui::GlWindow(current_application, width, height, title)); std::shared_ptr<uui::GlWindow> window(new uui::GlWindow(this, windows.size(), width, height, title));
window->init(); window->init();
windows.push_back(window); windows.push_back(window);
glfwSwapInterval(1); glfwSwapInterval(1);
@ -131,12 +108,10 @@ void uui::GlApplication::create_window(int width, int height, const std::string&
glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window); glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window);
glfwSwapInterval(0); glfwSwapInterval(0);
} }
return window;
if(window != nullptr && init != nullptr)
init(*window);
} }
std::shared_ptr<uui::Window> uui::GlApplication::get_window(std::size_t index) const std::shared_ptr<uui::GlWindow> uui::GlApplication::get_window(size_t index) const
{ {
if(index > windows.size()) if(index > windows.size())
throw std::runtime_error("Application doesn't have window at given index"); throw std::runtime_error("Application doesn't have window at given index");

View file

@ -3,62 +3,46 @@
#include <iostream> #include <iostream>
#include "uui/opengl/application.hpp" #include "uui/opengl/application.hpp"
#include "uui/opengl/container.hpp"
#include "uui/opengl/gl_utils.hpp" #include "uui/opengl/gl_utils.hpp"
uui::GlComponent::GlComponent( uui::GlComponent::GlComponent(
std::shared_ptr<uui::GlWindow> window, std::size_t window_index, std::shared_ptr<uui::GlContainer> parent, std::shared_ptr<GlWindow> window, const std::variant<int, float> x, const std::variant<int, float> y,
std::size_t parent_index, const ComponentParams& params) const std::variant<int, float> width, const std::variant<int, float> height):
window(window),
position_x(x), position_y(y), size_width(width), size_height(height), initialized(false)
{ {
if constexpr(uui::Application::debug_mode) if constexpr(uui::GlApplication::debug_mode)
std::cout << "Creating a GlComponent " << parent_index << std::endl; std::cout << "Creating a GlBox" << std::endl;
_type = ComponentType::COMPONENT; coord_all_relative = true;
auto parse_coords = [&](std::variant<int, float>& value) {
gl_window = window;
this->_window = std::static_pointer_cast<uui::Window>(window);
this->_window_index = window_index;
this->_parent = std::static_pointer_cast<uui::Container>(parent);
this->_parent_index = parent_index;
_initialized = false;
_position_x = params.x;
_position_y = params.y;
_width = params.width;
_height = params.height;
_coord_all_relative = true;
auto parse_coords = [&](position_t& value) {
if(value.index() == 0) if(value.index() == 0)
{ {
if(std::get<0>(value) == 0) if(std::get<0>(value) == 0)
value = 0.0f; value = 0.0f;
else else
_coord_all_relative = false; coord_all_relative = false;
} }
}; };
parse_coords(_position_x); parse_coords(position_x);
parse_coords(_position_y); parse_coords(position_y);
parse_coords(_width); parse_coords(size_width);
parse_coords(_height); parse_coords(size_height);
_background_color = {0.0f, 0.0f, 0.0f, 0.0f}; background_color = {0.0f, 0.0f, 0.0f, 0.0f};
} }
uui::GlComponent::~GlComponent() uui::GlComponent::~GlComponent()
{ {
if constexpr(uui::GlApplication::debug_mode) if constexpr(uui::GlApplication::debug_mode)
std::cout << "Destructor GlComponent " << _parent_index << std::endl; std::cout << "Closing a GlBox" << std::endl;
if(_initialized) if(initialized)
deinit(); deinit();
// if(parent != window)
// parent->remove_child(0); // TODO
} }
void uui::GlComponent::set_background_color(float r, float g, float b, float a /*=0.0f*/) void uui::GlComponent::set_background_color(float r, float g, float b, float a /*=0.0f*/)
{ {
_background_color = {r, g, b, a}; background_color = {r, g, b, a};
glBindVertexArray(gl_vao); glBindVertexArray(gl_vao);
set_vbo_data(); set_vbo_data();
glBindVertexArray(0); // Optional : for safety glBindVertexArray(0); // Optional : for safety
@ -66,8 +50,8 @@ void uui::GlComponent::set_background_color(float r, float g, float b, float a /
void uui::GlComponent::init() void uui::GlComponent::init()
{ {
if(_initialized) if(initialized)
throw std::runtime_error("GlComponent error : calling init while already initialized"); throw std::runtime_error("GlBox error : calling init while already initialized");
glGenVertexArrays(1, &gl_vao); glGenVertexArrays(1, &gl_vao);
glGenBuffers(1, &gl_vbo); glGenBuffers(1, &gl_vbo);
@ -80,8 +64,8 @@ void uui::GlComponent::init()
set_vbo_data(); set_vbo_data();
unsigned int indices[] = { unsigned int indices[] = {
0, 1, 3, // first triangle 0, 1, 3, // first triangle
1, 2, 3 // second triangle 1, 2, 3 // second triangle
}; };
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_ebo);
if constexpr(uui::GlApplication::debug_mode) if constexpr(uui::GlApplication::debug_mode)
@ -94,73 +78,65 @@ void uui::GlComponent::init()
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0); glBindVertexArray(0);
_initialized = true; initialized = true;
} }
void uui::GlComponent::set_vbo_data() void uui::GlComponent::set_vbo_data()
{ {
float vert_x = _position_x.index() == 1 float vert_x =
? std::get<1>(_position_x) position_x.index() == 1 ? std::get<1>(position_x) : static_cast<float>(std::get<0>(position_x)) / static_cast<float>(window->width);
: static_cast<float>(std::get<0>(_position_x)) / static_cast<float>(_window->width()); float vert_y =
float vert_y = _position_y.index() == 1 position_y.index() == 1 ? std::get<1>(position_y) : static_cast<float>(std::get<0>(position_y)) / static_cast<float>(window->height);
? std::get<1>(_position_y) float vert_w =
: static_cast<float>(std::get<0>(_position_y)) / static_cast<float>(_window->height()); size_width.index() == 1 ? std::get<1>(size_width) : static_cast<float>(std::get<0>(size_width)) / static_cast<float>(window->width);
float vert_w = _width.index() == 1 ? std::get<1>(_width) float vert_h = size_height.index() == 1 ? std::get<1>(size_height)
: static_cast<float>(std::get<0>(_width)) / static_cast<float>(_window->width()); : static_cast<float>(std::get<0>(size_height)) / static_cast<float>(window->height);
float vert_h = _height.index() == 1
? std::get<1>(_height)
: static_cast<float>(std::get<0>(_height)) / static_cast<float>(_window->height());
float x_min = (2.0f * vert_x) - 1.0f; float x_min = (2.0f * vert_x) - 1.0f;
float x_max = x_min + (2.0f * vert_w); float x_max = x_min + (2.0f * vert_w);
float y_min = (-2.0f * vert_y) + 1.0f; float y_min = (-2.0f * vert_y) + 1.0f;
float y_max = y_min - (2.0f * vert_h); float y_max = y_min - (2.0f * vert_h);
std::cout << "Sending vbo data with color: " << background_color[0] << ", " << background_color[1] << ", " << background_color[2] << ", "
<< background_color[3] << std::endl;
// clang-format off // clang-format off
float vertices[] = float vertices[] = {
{ x_max, y_min, background_color[0] , background_color[1], background_color[2], background_color[3], // top right
x_max, y_min, _background_color[0], _background_color[1], _background_color[2], _background_color[3], // top right x_max, y_max, background_color[0] , background_color[1], background_color[2], background_color[3], // bottom right
x_max, y_max, _background_color[0], _background_color[1], _background_color[2], _background_color[3], // bottom right x_min, y_max, background_color[0] , background_color[1], background_color[2], background_color[3], // bottom left
x_min, y_max, _background_color[0], _background_color[1], _background_color[2], _background_color[3], // bottom left x_min, y_min, background_color[0] , background_color[1], background_color[2], background_color[3] // top left
x_min, y_min, _background_color[0], _background_color[1], _background_color[2], _background_color[3] // top left
}; };
// clang-format on // clang-format on
glBindBuffer(GL_ARRAY_BUFFER, gl_vbo); glBindBuffer(GL_ARRAY_BUFFER, gl_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer( glVertexAttribPointer(
0, // index 0, // index
2, // size 2, // size
GL_FLOAT, // type GL_FLOAT, // type
GL_FALSE, // enable normalization, GL_FALSE, // enable normalization,
6 * sizeof(float), // stride 6 * sizeof(float), // stride
(void*)0 // offset (void*)0 // offset
); );
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer( glVertexAttribPointer(
1, // index 1, // index
4, // size 4, // size
GL_FLOAT, // type GL_FLOAT, // type
GL_FALSE, // enable normalization, GL_FALSE, // enable normalization,
6 * sizeof(float), // stride 6 * sizeof(float), // stride
(void*)(2 * sizeof(float)) // offset (void*)(2 * sizeof(float)) // offset
); );
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
} }
void uui::GlComponent::deinit() void uui::GlComponent::deinit()
{ {
if constexpr(uui::GlApplication::debug_mode) if(!initialized)
std::cout << "Deinit GlComponent " << _parent_index << std::endl; throw std::runtime_error("GlBox error : calling deinit while not initialized");
if(!_initialized)
throw std::runtime_error("GlComponent error : calling deinit while not initialized");
glDeleteVertexArrays(1, &gl_vao); glDeleteVertexArrays(1, &gl_vao);
glDeleteBuffers(1, &gl_vbo); glDeleteBuffers(1, &gl_vbo);
glDeleteBuffers(1, &gl_ebo); glDeleteBuffers(1, &gl_ebo);
initialized = false;
_window = nullptr;
_parent = nullptr;
_initialized = false;
} }
void uui::GlComponent::render() void uui::GlComponent::render()
@ -171,12 +147,8 @@ void uui::GlComponent::render()
void uui::GlComponent::on_resize() void uui::GlComponent::on_resize()
{ {
bool is_in_stack = if(!coord_all_relative)
_parent != nullptr && (_parent->type() == ComponentType::FLEX || _parent->type() == ComponentType::STACK);
if(!_coord_all_relative || is_in_stack)
{ {
if(is_in_stack)
std::tie(_position_x, _position_y) = _parent->get_child_position(_parent_index);
glBindVertexArray(gl_vao); glBindVertexArray(gl_vao);
set_vbo_data(); set_vbo_data();
glBindVertexArray(0); // Optional : for safety glBindVertexArray(0); // Optional : for safety

View file

@ -1,38 +0,0 @@
#include "uui/opengl/container_interface.hpp"
#include <iostream>
#include "uui/opengl/component.hpp"
std::size_t uui::GlContainerInterface::push_child(std::shared_ptr<uui::Component> child [[maybe_unused]])
{
throw std::runtime_error("GlContainerInterface error : should only push GlComponent child, not Component");
}
std::size_t uui::GlContainerInterface::push_child(std::shared_ptr<uui::GlComponent> child)
{
components.push_back(child);
return components.size() - 1;
}
std::shared_ptr<uui::Component> uui::GlContainerInterface::get_child(std::size_t index) const
{
return components.at(index);
}
void uui::GlContainerInterface::remove_child(std::size_t index)
{
components.at(index) = nullptr;
};
std::tuple<int, int> uui::GlContainerInterface::get_child_position(const std::size_t child_index [[maybe_unused]]) const
{
return {0, 0};
}
uui::GlContainerInterface::~GlContainerInterface()
{
if constexpr(uui::Application::debug_mode)
std::cout << "Destroying GlContainerInterface" << std::endl;
components.clear();
}

View file

@ -1,124 +0,0 @@
#include "uui/opengl/flex.hpp"
#include <iostream>
#include "uui/opengl/gl_utils.hpp"
uui::GlFlex::GlFlex(
std::shared_ptr<uui::GlWindow> window, std::size_t window_index, std::shared_ptr<uui::GlContainer> parent,
std::size_t parent_index, const StackParams& params):
GlComponent(window, window_index, parent, parent_index, {params.x, params.y, 0.0f, 0.0f}),
GlStack(window, window_index, parent, parent_index, params)
{
if constexpr(uui::GlApplication::debug_mode)
std::cout << "Creating a GlFlex " << parent_index << std::endl;
_type = ComponentType::FLEX;
_coord_all_relative = false;
}
std::tuple<int, int> uui::GlFlex::get_child_position(const std::size_t child_index) const
{
const int initial_x = _position_x.index() == 0
? std::get<0>(_position_x)
: static_cast<int>(std::get<1>(_position_x) * static_cast<float>(_window->width()));
const int initial_y = _position_y.index() == 0
? std::get<0>(_position_y)
: static_cast<int>(std::get<1>(_position_y) * static_cast<float>(_window->height()));
if(child_index == 0)
return {initial_x, initial_y};
if(child_index >= components.size())
throw std::runtime_error("GlStack error: child_index greater than children count");
auto get_child_size = [&](std::size_t index) -> std::tuple<int, int> {
int width = 0;
int height = 0;
if(components[index] != nullptr)
{
auto& component = components[index];
if(component->width().index() == 1)
width = static_cast<int>(std::get<1>(component->width()) * static_cast<float>(_window->width()));
else
width = std::get<0>(component->width());
if(component->height().index() == 1)
height = static_cast<int>(std::get<1>(component->height()) * static_cast<float>(_window->height()));
else
height = std::get<0>(component->height());
}
return {width, height};
};
int x = initial_x;
int y = initial_y;
if(direction == Direction::HORIZONTAL)
{
int child_width;
int child_height;
int max_height = 0;
std::tie(child_width, child_height) = get_child_size(0);
if(child_height > max_height)
max_height = child_height;
x += child_width;
for(std::size_t index = 1; index < child_index; index += 1)
{
std::tie(child_width, child_height) = get_child_size(index);
if(child_height > max_height)
max_height = child_height;
if(x != initial_x && x + child_width > _window->width())
{
x = initial_x + child_width;
y += max_height;
max_height = child_height;
}
else
x += child_width;
}
if(components[child_index] != nullptr)
{
std::tie(child_width, child_height) = get_child_size(child_index);
if(x != initial_x && x + child_width > _window->width())
{
x = initial_x;
y += max_height;
}
}
}
else
{
int child_width;
int child_height;
int max_width = 0;
std::tie(child_width, child_height) = get_child_size(0);
if(child_width > max_width)
max_width = child_width;
y += child_height;
for(std::size_t index = 1; index < child_index; index += 1)
{
std::tie(child_width, child_height) = get_child_size(index);
if(child_width > max_width)
max_width = child_width;
if(y != initial_y && y + child_height > _window->height())
{
y = initial_y + child_height;
x += max_width;
max_width = child_width;
}
else
y += child_height;
}
if(components[child_index] != nullptr)
{
std::tie(child_width, child_height) = get_child_size(child_index);
if(y != initial_y && y + child_height > _window->height())
{
y = initial_y;
x += max_width;
}
}
}
return {x, y};
}

View file

@ -6,15 +6,12 @@
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include "uui/config.hpp"
#include "uui/opengl/application.hpp" #include "uui/opengl/application.hpp"
#include "uui/opengl/gl_utils.hpp" #include "uui/opengl/gl_utils.hpp"
#include "uui/shader.hpp" #include "uui/shader.hpp"
#include "uui/types.hpp"
uui::GlFontManager::GlFontManager() uui::GlFontManager::GlFontManager(): initialized(false) {}
{
initialized = false;
}
uui::GlFontManager::~GlFontManager() uui::GlFontManager::~GlFontManager()
{ {
@ -28,7 +25,7 @@ void uui::GlFontManager::init()
throw std::runtime_error("GlFontManager error : calling init while initialized"); throw std::runtime_error("GlFontManager error : calling init while initialized");
if constexpr(uui::GlApplication::debug_mode) if constexpr(uui::GlApplication::debug_mode)
std::cout << "Init GlFontManager" << std::endl; std::cout << "Init glFontManager" << std::endl;
if(FT_Init_FreeType(&ft)) if(FT_Init_FreeType(&ft))
throw std::runtime_error("ERROR::FREETYPE: Could not init FreeType Library"); throw std::runtime_error("ERROR::FREETYPE: Could not init FreeType Library");
@ -120,9 +117,6 @@ void uui::GlFontManager::deinit()
if(!initialized) if(!initialized)
throw std::runtime_error("GlFontManager error : calling deinit while not initialized"); throw std::runtime_error("GlFontManager error : calling deinit while not initialized");
if constexpr(uui::GlApplication::debug_mode)
std::cout << "Deinit GlFontManager" << std::endl;
for(const auto& font: fonts) glDeleteTextures(1, &font.atlas_texture); for(const auto& font: fonts) glDeleteTextures(1, &font.atlas_texture);
glDeleteBuffers(1, &gl_vbo); glDeleteBuffers(1, &gl_vbo);
glDeleteBuffers(1, &gl_vao); glDeleteBuffers(1, &gl_vao);
@ -131,7 +125,7 @@ void uui::GlFontManager::deinit()
initialized = false; initialized = false;
} }
const uui::GlFontManager::Font& uui::GlFontManager::init_font(const std::string& font_path, unsigned int font_size) const uui::GlFontManager::Font& uui::GlFontManager::init_font(const std::string& font_path, size_t font_size)
{ {
fonts.emplace_back(); fonts.emplace_back();
auto& font = fonts.back(); auto& font = fonts.back();
@ -173,7 +167,7 @@ const uui::GlFontManager::Font& uui::GlFontManager::init_font(const std::string&
glLinkProgram(gl_program); glLinkProgram(gl_program);
// Create a texture that will be used to hold all ASCII glyphs // Create a texture that will be used to hold all ASCII glyphs
glActiveTexture(GlConfig::FONT_TEXTURE_UNIT); glActiveTexture(Config::FONT_TEXTURE_UNIT);
glGenTextures(1, &font.atlas_texture); glGenTextures(1, &font.atlas_texture);
glBindTexture(GL_TEXTURE_2D, font.atlas_texture); glBindTexture(GL_TEXTURE_2D, font.atlas_texture);
@ -212,8 +206,7 @@ const uui::GlFontManager::Font& uui::GlFontManager::init_font(const std::string&
} }
glTexSubImage2D( glTexSubImage2D(
GL_TEXTURE_2D, 0, offset_x, offset_y, glyph->bitmap.width, glyph->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, GL_TEXTURE_2D, 0, offset_x, offset_y, glyph->bitmap.width, glyph->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, glyph->bitmap.buffer);
glyph->bitmap.buffer);
font.char_infos[i].advance_x = glyph->advance.x >> 6; font.char_infos[i].advance_x = glyph->advance.x >> 6;
font.char_infos[i].advance_y = glyph->advance.y >> 6; font.char_infos[i].advance_y = glyph->advance.y >> 6;
@ -235,13 +228,13 @@ const uui::GlFontManager::Font& uui::GlFontManager::init_font(const std::string&
} }
std::tuple<int, int> uui::GlFontManager::get_text_size( std::tuple<int, int> uui::GlFontManager::get_text_size(
const std::string& text, uui::GlFontManager::Font& font, float scale_x, float scale_y) const std::string& text, uui::GlFontManager::Font& font, float scale_x, float scale_y)
{ {
float width = 0.0f; float width = 0.0f;
float height = 0.0f; float height = 0.0f;
for(auto current_char: text) for(auto current_char: text)
{ {
const auto& char_info = font.char_infos[static_cast<std::size_t>(current_char)]; const auto& char_info = font.char_infos[static_cast<size_t>(current_char)];
width += char_info.advance_x * scale_x; width += char_info.advance_x * scale_x;
// height = std::max(height, char_info.bitmap_top + char_info.bitmap_height * scale_y); // height = std::max(height, char_info.bitmap_top + char_info.bitmap_height * scale_y);
height = std::max(height, roundf(char_info.bitmap_height * scale_y)); height = std::max(height, roundf(char_info.bitmap_height * scale_y));
@ -250,14 +243,14 @@ std::tuple<int, int> uui::GlFontManager::get_text_size(
} }
void uui::GlFontManager::render_text( void uui::GlFontManager::render_text(
const std::string& text, uui::GlFontManager::Font& font, float x, float y, float scale_x, float scale_y, const std::string& text, uui::GlFontManager::Font& font, float x, float y, float scale_x, float scale_y,
const std::tuple<float, float, float, float>& text_color) const std::tuple<float, float, float, float>& text_color)
{ {
GLuint gl_prev_program; GLuint gl_prev_program;
glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)(&gl_prev_program)); glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)(&gl_prev_program));
glUseProgram(gl_program); glUseProgram(gl_program);
glActiveTexture(GlConfig::FONT_TEXTURE_UNIT); glActiveTexture(Config::FONT_TEXTURE_UNIT);
auto [color_r, color_g, color_b, color_a] = text_color; auto [color_r, color_g, color_b, color_a] = text_color;
glUniform4f(glGetUniformLocation(gl_program, "textColor"), color_r, color_g, color_b, color_a); glUniform4f(glGetUniformLocation(gl_program, "textColor"), color_r, color_g, color_b, color_a);
glBindVertexArray(gl_vao); glBindVertexArray(gl_vao);
@ -275,7 +268,7 @@ void uui::GlFontManager::render_text(
float out_base_y = y; float out_base_y = y;
for(auto current_char: text) for(auto current_char: text)
{ {
const auto& char_info = font.char_infos[static_cast<std::size_t>(current_char)]; const auto& char_info = font.char_infos[static_cast<size_t>(current_char)];
// Calculate the vertex and texture coordinates // Calculate the vertex and texture coordinates
float char_x = out_base_x + char_info.bitmap_left * scale_x; float char_x = out_base_x + char_info.bitmap_left * scale_x;
float char_y = out_base_y - char_info.bitmap_top * scale_y; float char_y = out_base_y - char_info.bitmap_top * scale_y;
@ -291,16 +284,15 @@ void uui::GlFontManager::render_text(
continue; continue;
// clang-format off // clang-format off
float current_vertex[24] = float current_vertex[24] = {
{ char_x, char_y, char_info.texture_x, char_info.texture_y, // top_left
char_x, char_y, char_info.texture_x, char_info.texture_y, // top_left char_x + w, char_y, char_info.texture_x + char_info.bitmap_width / font.atlas_width, char_info.texture_y, // top-right
char_x + w, char_y, char_info.texture_x + char_info.bitmap_width / font.atlas_width, char_info.texture_y, // top-right char_x, char_y + h, char_info.texture_x, char_info.texture_y + char_info.bitmap_height / font.atlas_height, // bottom-right
char_x, char_y + h, char_info.texture_x, char_info.texture_y + char_info.bitmap_height / font.atlas_height, // bottom-right char_x + w, char_y, char_info.texture_x + char_info.bitmap_width / font.atlas_width, char_info.texture_y, // top-right
char_x + w, char_y, char_info.texture_x + char_info.bitmap_width / font.atlas_width, char_info.texture_y, // top-right char_x, char_y + h, char_info.texture_x, char_info.texture_y + char_info.bitmap_height / font.atlas_height, // bottom-left
char_x, char_y + h, char_info.texture_x, char_info.texture_y + char_info.bitmap_height / font.atlas_height, // bottom-left char_x + w, char_y + h, char_info.texture_x + char_info.bitmap_width / font.atlas_width,
char_x + w, char_y + h, char_info.texture_x + char_info.bitmap_width / font.atlas_width, char_info.texture_y + char_info.bitmap_height / font.atlas_height // bottom-right
char_info.texture_y + char_info.bitmap_height / font.atlas_height // bottom-right };
};
std::memcpy(vertices.data() + (char_count * 24), current_vertex, 24 * sizeof(float)); std::memcpy(vertices.data() + (char_count * 24), current_vertex, 24 * sizeof(float));
// clang-format on // clang-format on
char_count += 1; char_count += 1;

View file

@ -2,39 +2,34 @@
#include <iostream> #include <iostream>
#include "uui/opengl/font_manager.hpp"
#include "uui/opengl/gl_utils.hpp" #include "uui/opengl/gl_utils.hpp"
uui::GlLabel::GlLabel( uui::GlLabel::GlLabel(
std::shared_ptr<uui::GlWindow> window, std::size_t window_index, std::shared_ptr<uui::GlContainer> parent, std::shared_ptr<uui::GlWindow> window, const std::variant<int, float> x, const std::variant<int, float> y, const std::string& text,
std::size_t parent_index, const LabelParams& params): const std::tuple<float, float, float, float>& text_color):
GlComponent(window, window_index, parent, parent_index, {params.x, params.y, 0.0f, 0.0f}), text(params.text), GlComponent(window, x, y, 0.0f, 0.0f),
text_color(params.text_color) text(text), text_color(text_color)
{ {
if constexpr(uui::Application::debug_mode) if constexpr(uui::GlApplication::debug_mode)
std::cout << "Creating GlLabel " << parent_index << std::endl; std::cout << "Creating a GlLabel" << std::endl;
_type = ComponentType::LABEL;
font_index = 0; font_index = 0;
std::tie(text_width, text_height) = std::tie(text_width, text_height) = window->font_manager.get_text_size(text, window->font_manager.fonts[font_index], 1.0f, 1.0f);
window->font_manager->get_text_size(text, window->font_manager->fonts[font_index], 1.0f, 1.0f); size_width = text_width;
_width = text_width; size_height = text_height;
_height = text_height; coord_all_relative = false;
_coord_all_relative = false;
} }
void uui::GlLabel::render() void uui::GlLabel::render()
{ {
float text_x = _position_x.index() == 1 ? std::get<1>(_position_x) * static_cast<float>(_window->width()) float text_x =
: static_cast<float>(std::get<0>(_position_x)); position_x.index() == 1 ? std::get<1>(position_x) * static_cast<float>(window->width) : static_cast<float>(std::get<0>(position_x));
float text_y = _position_y.index() == 1 ? std::get<1>(_position_y) * static_cast<float>(_window->height()) float text_y =
: static_cast<float>(std::get<0>(_position_y)); position_y.index() == 1 ? std::get<1>(position_y) * static_cast<float>(window->height) : static_cast<float>(std::get<0>(position_y));
text_y += static_cast<float>(text_height) - 1; text_y += static_cast<float>(text_height) - 1;
glBindVertexArray(gl_vao); glBindVertexArray(gl_vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0);
_window->font_manager->render_text( window->font_manager.render_text(text.c_str(), window->font_manager.fonts.front(), text_x, text_y, 1.0f, 1.0f, text_color);
text.c_str(), _window->font_manager->fonts.front(), text_x, text_y, 1.0f, 1.0f, text_color);
glBindVertexArray(0); glBindVertexArray(0);
} }

View file

@ -1,101 +0,0 @@
#include "uui/opengl/stack.hpp"
#include <iostream>
#include "uui/opengl/gl_utils.hpp"
#include "uui/opengl/label.hpp"
uui::GlStack::GlStack(
std::shared_ptr<uui::GlWindow> window, std::size_t window_index, std::shared_ptr<uui::GlContainer> parent,
std::size_t parent_index, const StackParams& params):
GlComponent(window, window_index, parent, parent_index, {params.x, params.y, 0.0f, 0.0f})
{
if constexpr(uui::GlApplication::debug_mode)
std::cout << "Creating GlStack " << parent_index << std::endl;
_type = ComponentType::STACK;
direction = params.direction;
_coord_all_relative = false;
}
void uui::GlStack::create_component(const StackComponentParams& params, uui::InitFunction<uui::Component> init)
{
if(!_initialized)
throw std::runtime_error("GlWindow error : cannot create component while not initialized");
glfwMakeContextCurrent(gl_window->glfw_window);
std::shared_ptr<uui::GlComponent> component(new uui::GlComponent(
gl_window, gl_window->components.size(), std::dynamic_pointer_cast<uui::GlContainer>(shared_from_this()),
components.size(), {0, 0, params.width, params.height}));
push_child(component);
component->init();
std::tie(component->_position_x, component->_position_y) = get_child_position(components.size() - 1);
gl_window->components.push_back(component);
if(component != nullptr)
init(*component);
}
void uui::GlStack::create_label(const StackLabelParams& params, uui::InitFunction<uui::Label> init)
{
if(!_initialized)
throw std::runtime_error("GlWindow error : cannot create component while not initialized");
glfwMakeContextCurrent(gl_window->glfw_window);
std::shared_ptr<uui::GlLabel> label(new uui::GlLabel(
gl_window, gl_window->components.size(), std::dynamic_pointer_cast<uui::GlContainer>(shared_from_this()),
components.size(), {0, 0, params.text, params.text_color}));
push_child(std::static_pointer_cast<uui::GlComponent>(label));
label->init();
std::tie(label->_position_x, label->_position_y) = get_child_position(components.size() - 1);
gl_window->components.push_back(label);
if(label != nullptr && init != nullptr)
init(*label);
}
std::tuple<int, int> uui::GlStack::get_child_position(const std::size_t child_index) const
{
int x = _position_x.index() == 0
? std::get<0>(_position_x)
: static_cast<int>(std::get<1>(_position_x) * static_cast<float>(_window->width()));
int y = _position_y.index() == 0
? std::get<0>(_position_y)
: static_cast<int>(std::get<1>(_position_y) * static_cast<float>(_window->height()));
if(child_index == 0)
return {x, y};
if(child_index >= components.size())
throw std::runtime_error("GlStack error: child_index greater than children count");
if(direction == Direction::HORIZONTAL)
{
for(std::size_t index = 0; index < child_index; index += 1)
if(components[index] != nullptr)
{
auto& component = components[index];
if(component->width().index() == 1)
x += static_cast<int>(std::get<1>(component->width()) * static_cast<float>(_window->width()));
else
x += std::get<0>(component->width());
}
}
else
{
for(std::size_t index = 0; index < child_index; index += 1)
{
if(components[index] != nullptr)
{
auto& component = components[index];
if(component->height().index() == 1)
y += static_cast<int>(std::get<1>(component->height()) * static_cast<float>(_window->height()));
else
y += std::get<0>(component->height());
}
}
}
return {x, y};
}

View file

@ -3,15 +3,12 @@
#include <iostream> #include <iostream>
#include "uui/opengl/component.hpp" #include "uui/opengl/component.hpp"
#include "uui/opengl/flex.hpp"
#include "uui/opengl/gl_utils.hpp" #include "uui/opengl/gl_utils.hpp"
#include "uui/opengl/label.hpp" #include "uui/opengl/label.hpp"
#include "uui/opengl/stack.hpp"
#include "uui/shader.hpp" #include "uui/shader.hpp"
static void APIENTRY glDebugOutput( static void APIENTRY
GLenum source, GLenum type, unsigned int id, GLenum severity, GLsizei length [[maybe_unused]], const char* message, glDebugOutput(GLenum source, GLenum type, unsigned int id, GLenum severity, GLsizei length, const char* message, const void* userParam)
const void* userParam [[maybe_unused]])
{ {
// ignore non-significant error/warning codes // ignore non-significant error/warning codes
if(id == 131169 || id == 131185 || id == 131218 || id == 131204) if(id == 131169 || id == 131185 || id == 131218 || id == 131204)
@ -60,77 +57,55 @@ void uui::GlWindow::glfw_resize_callback(GLFWwindow* window, int width, int heig
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
auto gl_window = reinterpret_cast<uui::GlWindow*>(glfwGetWindowUserPointer(window)); auto gl_window = reinterpret_cast<uui::GlWindow*>(glfwGetWindowUserPointer(window));
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
gl_window->_width = width; gl_window->width = width;
gl_window->_height = height; gl_window->height = height;
gl_window->_render_needed = true; gl_window->render_needed = true;
gl_window->_resize_needed = true; gl_window->resize_needed = true;
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(width), static_cast<float>(height), 0.0f); glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(width), static_cast<float>(height), 0.0f);
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glUseProgram(gl_window->gl_font_manager->gl_program); glUseProgram(gl_window->font_manager.gl_program);
glUniformMatrix4fv( glUniformMatrix4fv(glGetUniformLocation(gl_window->font_manager.gl_program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glGetUniformLocation(gl_window->gl_font_manager->gl_program, "projection"), 1, GL_FALSE,
glm::value_ptr(projection));
} }
void uui::GlWindow::glfw_iconify_callback(GLFWwindow* window, int iconified) void uui::GlWindow::glfw_iconify_callback(GLFWwindow* window, int iconified)
{ {
auto gl_window = reinterpret_cast<uui::GlWindow*>(glfwGetWindowUserPointer(window)); auto gl_window = reinterpret_cast<uui::GlWindow*>(glfwGetWindowUserPointer(window));
gl_window->_iconified = iconified; gl_window->iconified = iconified;
} }
void uui::GlWindow::glfw_key_callback( void uui::GlWindow::glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
GLFWwindow* window, int key, int scancode [[maybe_unused]], int action, int mods [[maybe_unused]])
{ {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, true); glfwSetWindowShouldClose(window, true);
} }
// void uui::GlWindow::glfw_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) uui::GlWindow::GlWindow(uui::GlApplication* app, size_t index, int width, int height, const std::string& title):
// { app(app), width(width), height(height), render_needed(true), resize_needed(false), iconified(false), index(index), initialized(false)
// if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
// {}
// }
uui::GlWindow::GlWindow(std::shared_ptr<uui::Application> app, int width, int height, const std::string& title)
{ {
_type = ComponentType::WINDOW; if constexpr(uui::GlApplication::debug_mode)
std::cout << "Creating a GlWindow" << std::endl;
_app = app; this->title = title;
_initialized = false;
_title = title;
_width = width;
_height = height;
_render_needed = true;
_resize_needed = false;
_iconified = false;
if constexpr(uui::Application::debug_mode)
std::cout << "Creating GlWindow : " << title << std::endl;
} }
uui::GlWindow::~GlWindow() uui::GlWindow::~GlWindow()
{ {
if constexpr(uui::Application::debug_mode) if constexpr(uui::GlApplication::debug_mode)
std::cout << "Destructor GlWindow : " << _title << std::endl; std::cout << "Closing a GlWindow" << std::endl;
if(_initialized) if(initialized)
{ {
if constexpr(uui::Application::debug_mode) if constexpr(uui::GlApplication::debug_mode)
std::cout << "Destructor-deinit GlWindow : " << _title << std::endl; std::cout << "Destructor-deinit a GlWindow" << std::endl;
deinit(); deinit();
} }
} }
void uui::GlWindow::init() void uui::GlWindow::init()
{ {
if(_initialized) if(initialized)
throw std::runtime_error("GlWindow error : calling init while already initialized"); throw std::runtime_error("GlWindow error : calling init while already initialized");
gl_font_manager = std::make_shared<uui::GlFontManager>(); glfw_window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
font_manager = std::static_pointer_cast<uui::FontManager>(gl_font_manager);
glfw_window = glfwCreateWindow(_width, _height, _title.c_str(), NULL, NULL);
if(glfw_window == NULL) if(glfw_window == NULL)
throw std::runtime_error("GLWindow : failed to create GLFW window"); throw std::runtime_error("GLWindow : failed to create GLFW window");
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
@ -226,35 +201,31 @@ void uui::GlWindow::init()
glDeleteShader(vertex_shader); glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader); glDeleteShader(fragment_shader);
gl_font_manager->init(); font_manager.init();
glUseProgram(gl_font_manager->gl_program); glUseProgram(font_manager.gl_program);
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(_width), static_cast<float>(_height), 0.0f); glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(width), static_cast<float>(height), 0.0f);
glUniformMatrix4fv( glUniformMatrix4fv(glGetUniformLocation(font_manager.gl_program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glGetUniformLocation(gl_font_manager->gl_program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUseProgram(gl_program); glUseProgram(gl_program);
_initialized = true; initialized = true;
} }
void uui::GlWindow::deinit() void uui::GlWindow::deinit()
{ {
if(!_initialized) if(!initialized)
throw std::runtime_error("GlWindow error : calling deinit while not initialized"); throw std::runtime_error("GlWindow error : calling deinit while not initialized");
if constexpr(uui::GlApplication::debug_mode) if constexpr(uui::GlApplication::debug_mode)
std::cout << "Deinit GlWindow : " << _title << std::endl; std::cout << "Deinit a GlWindow" << std::endl;
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
glDeleteProgram(gl_program); glDeleteProgram(gl_program);
for(auto& gl_component: components) gl_component->deinit(); for(auto& component: components) component->deinit();
components.clear(); components.clear();
gl_font_manager->deinit(); font_manager.deinit();
glfwDestroyWindow(glfw_window); glfwDestroyWindow(glfw_window);
_app = nullptr; initialized = false;
font_manager = nullptr;
gl_font_manager = nullptr;
_initialized = false;
} }
void uui::GlWindow::render() void uui::GlWindow::render()
@ -264,69 +235,41 @@ void uui::GlWindow::render()
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(gl_program); glUseProgram(gl_program);
if(_resize_needed) if(resize_needed)
{ {
for(auto& component: components) component->on_resize(); for(auto& component: components) component->on_resize();
_resize_needed = false; resize_needed = false;
} }
for(auto& component: components) component->render(); for(auto& component: components) component->render();
glfwSwapBuffers(glfw_window); glfwSwapBuffers(glfw_window);
_render_needed = false; render_needed = false;
} }
void uui::GlWindow::create_component(const uui::ComponentParams& params, uui::InitFunction<Component> init) std::shared_ptr<uui::GlComponent> uui::GlWindow::create_component(
const std::variant<int, float> x, const std::variant<int, float> y, const std::variant<int, float> width,
const std::variant<int, float> height)
{ {
if(!_initialized) if(!initialized)
throw std::runtime_error("GlWindow error : cannot create component while not initialized"); throw std::runtime_error("GlWindow error : cannot create component while not initialized");
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
std::shared_ptr<uui::GlComponent> component(new uui::GlComponent(shared_from_this(), components.size(), params)); std::shared_ptr<uui::GlComponent> component(new uui::GlComponent(app->get_window(index), x, y, width, height));
push_child(component);
component->init(); component->init();
components.push_back(component);
if(component != nullptr && init != nullptr) return component;
init(*component);
} }
void uui::GlWindow::create_label(const LabelParams& params, uui::InitFunction<Label> init) std::shared_ptr<uui::GlLabel> uui::GlWindow::create_label(
const std::variant<int, float> x, const std::variant<int, float> y, const std::string& text,
const std::tuple<float, float, float, float>& text_color)
{ {
if(!_initialized) if(!initialized)
throw std::runtime_error("GlWindow error : cannot create label while not initialized"); throw std::runtime_error("GlWindow error : cannot create component while not initialized");
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
std::shared_ptr<uui::GlLabel> label(new uui::GlLabel(shared_from_this(), components.size(), params)); std::shared_ptr<uui::GlLabel> label(new uui::GlLabel(app->get_window(index), x, y, text, text_color));
push_child(std::static_pointer_cast<uui::GlComponent>(label));
label->init(); label->init();
components.push_back(label);
if(label != nullptr && init != nullptr) return label;
init(*label);
}
void uui::GlWindow::create_flex(const StackParams& params, uui::InitFunction<Flex> init)
{
if(!_initialized)
throw std::runtime_error("GlWindow error : cannot create flex while not initialized");
glfwMakeContextCurrent(glfw_window);
std::shared_ptr<uui::GlFlex> flex(new uui::GlFlex(shared_from_this(), components.size(), params));
push_child(std::static_pointer_cast<uui::GlComponent>(flex));
flex->init();
if(flex != nullptr && init != nullptr)
init(*flex);
}
void uui::GlWindow::create_stack(const StackParams& params, uui::InitFunction<Stack> init)
{
if(!_initialized)
throw std::runtime_error("GlWindow error : cannot create stack while not initialized");
glfwMakeContextCurrent(glfw_window);
std::shared_ptr<uui::GlStack> stack(new uui::GlStack(shared_from_this(), components.size(), params));
push_child(std::static_pointer_cast<uui::GlComponent>(stack));
stack->init();
if(stack != nullptr && init != nullptr)
init(*stack);
} }

View file

@ -1,7 +1,7 @@
#include "uui/shader.hpp" #include "uui/shader.hpp"
#include <fstream> #include <fstream>
#include <ios>
std::vector<char> uui::readFile(const std::string& filename) std::vector<char> uui::readFile(const std::string& filename)
{ {
@ -10,10 +10,10 @@ std::vector<char> uui::readFile(const std::string& filename)
if(!file.is_open()) if(!file.is_open())
throw std::runtime_error("failed to open file!"); throw std::runtime_error("failed to open file!");
std::size_t fileSize = static_cast<std::size_t>(file.tellg()); size_t fileSize = (size_t)file.tellg();
std::vector<char> buffer(fileSize); std::vector<char> buffer(fileSize);
file.seekg(0); file.seekg(0);
file.read(buffer.data(), static_cast<std::streamsize>(fileSize)); file.read(buffer.data(), fileSize);
file.close(); file.close();
return buffer; return buffer;

2
umake

@ -1 +1 @@
Subproject commit 933dea2b9e9da0b03489ea9dca3cd597fdd2d09e Subproject commit f5965cc91e7eb27d1def78113301e7ec28fad54a