Replacing Ref-System with unique_ptr<T>
Adding code Goals to README.md
This commit is contained in:
parent
1bc396c4b2
commit
bdf5b25b28
3 changed files with 198 additions and 187 deletions
40
README.md
40
README.md
|
@ -1,2 +1,40 @@
|
||||||
# cigus
|
# cigui
|
||||||
|
|
||||||
|
# Goal
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <cigui.hpp>
|
||||||
|
|
||||||
|
struct ContentView : public cig::View {
|
||||||
|
void body() {
|
||||||
|
cig::VStack(
|
||||||
|
cig::SystemIcon("globe.fill"),
|
||||||
|
cig::Text("Welcome to Cigui")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SettingsView : public cig::View {
|
||||||
|
void body() {
|
||||||
|
cig::Tabbed(
|
||||||
|
cig::Tab(
|
||||||
|
|
||||||
|
).tag("Tab 1"),
|
||||||
|
cig::Tab(
|
||||||
|
cig::VStack(
|
||||||
|
cig::Text("Other Tab")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MainApp : public cig::App {
|
||||||
|
void body() {
|
||||||
|
cig::WindowGroup()(
|
||||||
|
cig::ViewWindow(new ContentView()),
|
||||||
|
cig::SettingsWindow(new SettingsView())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
344
cigus.hpp
344
cigus.hpp
|
@ -5,228 +5,200 @@
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
namespace cigus {
|
|
||||||
|
#define TYPEDEF_VECTOR(NAME, T, N, s) typedef NAME<T> vec##N##s;
|
||||||
|
|
||||||
|
#define TYPEDEF_VECTORS(NAME, N) \
|
||||||
|
typedef NAME<float> vec##N##; \
|
||||||
|
TYPEDEF_VECTOR(NAME, float, N, f) \
|
||||||
|
TYPEDEF_VECTOR(NAME, double, N, d) \
|
||||||
|
TYPEDEF_VECTOR(NAME, long double, N, ld) \
|
||||||
|
TYPEDEF_VECTOR(NAME, size_t, N, sz) \
|
||||||
|
TYPEDEF_VECTOR(NAME, int, N, i) \
|
||||||
|
TYPEDEF_VECTOR(NAME, unsigned int, N, u) \
|
||||||
|
TYPEDEF_VECTOR(NAME, short, N, s) \
|
||||||
|
TYPEDEF_VECTOR(NAME, unsigned short, N, us) \
|
||||||
|
TYPEDEF_VECTOR(NAME, long, N, l) \
|
||||||
|
TYPEDEF_VECTOR(NAME, unsigned long, N, ul) \
|
||||||
|
TYPEDEF_VECTOR(NAME, long long, N, ll) \
|
||||||
|
TYPEDEF_VECTOR(NAME, unsigned long long, N, ull)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace UI
|
||||||
|
{
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
template<typename T> class Ref;
|
template<typename T>
|
||||||
template<typename T> class OriginRef;
|
union Vector2 {
|
||||||
template<typename T> class MutRef;
|
struct { T x, y; };
|
||||||
template<typename T> class ConstRef;
|
struct { T a, b; };
|
||||||
|
};
|
||||||
|
|
||||||
|
TYPEDEF_VECTORS(Vector2, 2)
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Ref {
|
union Vector3 {
|
||||||
protected:
|
struct { T x, y, z; };
|
||||||
T *ptr = nullptr;
|
struct { T r, g, b; };
|
||||||
|
};
|
||||||
|
TYPEDEF_VECTORS(Vector3, 3)
|
||||||
|
|
||||||
public:
|
template<typename T>
|
||||||
virtual ~Ref() {}
|
union Vector4 {
|
||||||
Ref() = delete;
|
struct { T x, y, z, w; };
|
||||||
Ref(const Ref &other) = delete;
|
struct { T r, g, b, a; };
|
||||||
Ref(Ref &&other) = delete;
|
struct { T left, top, right, bottom; };
|
||||||
|
};
|
||||||
|
TYPEDEF_VECTORS(Vector4, 4)
|
||||||
|
|
||||||
Ref(const OriginRef<T>& ptr) : ptr(ptr.ptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref(T* ptr) : ptr(ptr)
|
|
||||||
|
class RenderCall
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<sf::Drawable> drawable;
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool operator!() const {
|
|
||||||
return ptr == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void check() const {
|
|
||||||
assert(ptr != nullptr || "Dereferencing null pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const T &operator*() const {
|
|
||||||
check();
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const T *operator->() const {
|
|
||||||
check();
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Ref Null()
|
|
||||||
{
|
|
||||||
return Ref(nullptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class OriginRef final : public MutRef<T> {
|
|
||||||
public:
|
|
||||||
friend class Ref<T>;
|
|
||||||
|
|
||||||
template<typename G, typename... Args>
|
|
||||||
OriginRef(Args... args) : Ref<T>(new G(std::forward<Args>(args)...)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
OriginRef(T* ptr) : MutRef<T>(ptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~OriginRef() override {
|
|
||||||
if (this->ptr != nullptr) {
|
|
||||||
delete this->ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] MutRef<T> mut() {
|
|
||||||
return MutRef<T>(this->ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] ConstRef<T> immute() const {
|
|
||||||
return ConstRef<T>(this->ptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class MutRef : public Ref<T> {
|
|
||||||
protected:
|
|
||||||
using Ref<T>::ptr;
|
|
||||||
public:
|
|
||||||
friend class Ref<T>;
|
|
||||||
|
|
||||||
using Ref<T>::check;
|
|
||||||
using Ref<T>::operator*;
|
|
||||||
using Ref<T>::operator->;
|
|
||||||
|
|
||||||
MutRef(const OriginRef<T>& other) : Ref<T>(other.ptr) {}
|
|
||||||
|
|
||||||
MutRef(T* ptr) : Ref<T>(ptr) {}
|
|
||||||
|
|
||||||
MutRef(const MutRef &other) : Ref<T>(other.ptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
MutRef(MutRef &&other) noexcept : Ref<T>(other.ptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
MutRef &operator=(MutRef &&other) noexcept {
|
|
||||||
if (this->ptr != other.ptr) {
|
|
||||||
ptr = other.ptr;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
T &operator*() {
|
|
||||||
check();
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
T *operator->() {
|
|
||||||
check();
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class ConstRef : public Ref<T>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
using Ref<T>::ptr;
|
|
||||||
using Ref<T>::check;
|
|
||||||
public:
|
|
||||||
friend class Ref<T>;
|
|
||||||
|
|
||||||
ConstRef(const OriginRef<T> other) : Ref<T>(other.ptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstRef(const MutRef<T> other) : Ref<T>(other.ptr) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class NullRef
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
friend class Ref<T>;
|
|
||||||
|
|
||||||
NullRef(const NullRef &other) = delete;
|
|
||||||
NullRef(NullRef &&other) = delete;
|
|
||||||
|
|
||||||
NullRef &operator=(NullRef &&other) = delete;
|
|
||||||
|
|
||||||
NullRef() : Ref<T>(nullptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
T *ptr = nullptr;
|
|
||||||
|
|
||||||
bool operator!() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace cigus::UI {
|
|
||||||
class RenderCall {
|
|
||||||
OriginRef<sf::Drawable> drawable;
|
|
||||||
sf::RenderStates states;
|
sf::RenderStates states;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RenderCall(const sf::RenderStates& states, sf::Drawable *ptr) : drawable(ptr), states(states) {
|
explicit RenderCall(const sf::RenderStates& states, sf::Drawable* ptr) : drawable(ptr), states(states)
|
||||||
drawable.check();
|
{
|
||||||
|
if (!drawable) { throw std::runtime_error("RenderCall::RenderCall(): Drawable is null"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(sf::RenderTarget &target, const sf::RenderStates &states) const {
|
void draw(sf::RenderTarget& target, const sf::RenderStates& states) const { target.draw(*drawable, states); }
|
||||||
target.draw(*drawable, states);
|
|
||||||
}
|
|
||||||
|
|
||||||
MutRef<sf::Drawable> operator->() {
|
|
||||||
drawable.check();
|
|
||||||
return drawable.mut();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class View {
|
enum class LayoutSizes : uint8_t
|
||||||
std::vector<RenderCall> m_RenderCalls;
|
{
|
||||||
|
None = 0,
|
||||||
|
Min,
|
||||||
|
Max,
|
||||||
|
Fixed,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LayoutAlignment : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Top,
|
||||||
|
Bottom,
|
||||||
|
Center,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LayoutDirection : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
LeftToRight,
|
||||||
|
RightToLeft,
|
||||||
|
TopToBottom,
|
||||||
|
BottomToTop,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LayoutPosition : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Absolute,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Top,
|
||||||
|
Bottom,
|
||||||
|
Center,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Layout
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
LayoutSizes rule = LayoutSizes::None;
|
||||||
|
vec2f minSize = {0.f, 0.f};
|
||||||
|
vec2f maxSize = {0.f, 0.f};
|
||||||
|
} size;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
LayoutAlignment rule = LayoutAlignment::None;
|
||||||
|
vec4f padding = {0.f, 0.f, 0.f, 0.f};
|
||||||
|
vec4f margin = {0.f, 0.f, 0.f, 0.f};
|
||||||
|
} alignment;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
LayoutDirection rule = LayoutDirection::None;
|
||||||
|
vec2f spacing = {0.f, 0.f};
|
||||||
|
} direction;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
LayoutPosition rule = LayoutPosition::None;
|
||||||
|
vec2f position = {0.f, 0.f};
|
||||||
|
} position;
|
||||||
|
};
|
||||||
|
|
||||||
|
class View
|
||||||
|
{
|
||||||
protected:
|
protected:
|
||||||
void Rectangle(const float x, const float y, sf::Color color = sf::Color::White) {
|
std::vector<RenderCall> m_RenderCalls;
|
||||||
auto shape = new sf::RectangleShape(sf::Vector2f(x, y));
|
Layout m_Layout;
|
||||||
shape->setFillColor(color);
|
|
||||||
m_RenderCalls.emplace_back(sf::RenderStates(), shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~View() = default;
|
virtual ~View() = default;
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<RenderCall> &renderCalls() const {
|
[[nodiscard]] const std::vector<RenderCall>& renderCalls() const { return m_RenderCalls; }
|
||||||
return m_RenderCalls;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool update()
|
virtual bool update() { return false; }
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw() {
|
void draw()
|
||||||
if (!m_RenderCalls.empty())
|
|
||||||
{
|
{
|
||||||
m_RenderCalls.clear();
|
if (!m_RenderCalls.empty()) { m_RenderCalls.clear(); }
|
||||||
}
|
|
||||||
body();
|
body();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void body() = 0;
|
virtual void body() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Renderer {
|
class Rectangle : public View
|
||||||
|
{
|
||||||
|
|
||||||
|
vec2f m_Size;
|
||||||
|
sf::Color m_Color;
|
||||||
|
sf::Color m_BorderColor;
|
||||||
|
float m_BorderThickness = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void setBorderColor(const sf::Color& color) { m_BorderColor = color; }
|
||||||
|
void setBorderThickness(float thickness) { m_BorderThickness = thickness; }
|
||||||
|
void setColor(const sf::Color& color) { m_Color = color; }
|
||||||
|
void setSize(const vec2f& size) { m_Size = size; }
|
||||||
|
|
||||||
|
void body() override
|
||||||
|
{
|
||||||
|
auto m_Shape = new sf::RectangleShape(sf::Vector2f{m_Size.x, m_Size.y});
|
||||||
|
m_Shape->setFillColor(m_Color);
|
||||||
|
if (m_BorderThickness > 0)
|
||||||
|
{
|
||||||
|
m_Shape->setOutlineThickness(m_BorderThickness);
|
||||||
|
m_Shape->setOutlineColor(m_BorderColor);
|
||||||
|
}
|
||||||
|
m_RenderCalls.emplace_back(sf::RenderStates(), m_Shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle(const vec2f& size) : m_Size(size) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Renderer
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit Renderer(const MutRef<View> &_view) : view(_view) { view->body(); }
|
explicit Renderer(View* _view) : view(_view) { view->body(); }
|
||||||
|
|
||||||
MutRef<View> view;
|
std::unique_ptr<View> view;
|
||||||
|
|
||||||
void update() {
|
void update() const
|
||||||
|
{
|
||||||
if (view->update())
|
if (view->update())
|
||||||
view->draw();
|
view->draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void render(sf::RenderTarget &target, const sf::RenderStates &states) const {
|
void render(sf::RenderTarget& target, const sf::RenderStates& states) const
|
||||||
for (const auto &renderCall: view->renderCalls()) {
|
{
|
||||||
renderCall.draw(target, states);
|
for (const auto& renderCall : view->renderCalls()) { renderCall.draw(target, states); }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@ public:
|
||||||
|
|
||||||
void body() override {
|
void body() override {
|
||||||
std::cout << "Body\n";
|
std::cout << "Body\n";
|
||||||
//Rectangle(100, 100, sf::Color(250,250,250));
|
Rectangle(400,400, sf::Color(20,20,120));
|
||||||
|
Rectangle(100, 100, sf::Color(250,250,250));
|
||||||
Rectangle(10,20, sf::Color(120,120,120));
|
Rectangle(10,20, sf::Color(120,120,120));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -27,8 +28,8 @@ int main(int argc, char** argv) {
|
||||||
sf::RenderWindow window(sf::VideoMode({800, 600}), "Hello World!");
|
sf::RenderWindow window(sf::VideoMode({800, 600}), "Hello World!");
|
||||||
window.setFramerateLimit(60);
|
window.setFramerateLimit(60);
|
||||||
|
|
||||||
cigus::OriginRef<UI::View> view = cigus::OriginRef<UI::View>(new NewView);
|
const auto view = new NewView();
|
||||||
UI::Renderer renderer(view);
|
const UI::Renderer renderer(view);
|
||||||
|
|
||||||
while (window.isOpen()) {
|
while (window.isOpen()) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue