232 lines
4.1 KiB
C++
232 lines
4.1 KiB
C++
#pragma once
|
|
|
|
#include <vector>
|
|
#include <SFML/Graphics.hpp>
|
|
#include <nlohmann/json.hpp>
|
|
#include <spdlog/spdlog.h>
|
|
|
|
namespace cigus {
|
|
using json = nlohmann::json;
|
|
|
|
template<typename T> class Ref;
|
|
template<typename T> class OriginRef;
|
|
template<typename T> class MutRef;
|
|
template<typename T> class ConstRef;
|
|
|
|
template<typename T>
|
|
class Ref {
|
|
protected:
|
|
T *ptr = nullptr;
|
|
|
|
public:
|
|
virtual ~Ref() {}
|
|
Ref() = delete;
|
|
Ref(const Ref &other) = delete;
|
|
Ref(Ref &&other) = delete;
|
|
|
|
Ref(const OriginRef<T>& ptr) : ptr(ptr.ptr) {
|
|
}
|
|
|
|
Ref(T* ptr) : ptr(ptr)
|
|
{
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
public:
|
|
explicit RenderCall(const sf::RenderStates& states, sf::Drawable *ptr) : drawable(ptr), states(states) {
|
|
drawable.check();
|
|
}
|
|
|
|
void draw(sf::RenderTarget &target, const sf::RenderStates &states) const {
|
|
target.draw(*drawable, states);
|
|
}
|
|
|
|
MutRef<sf::Drawable> operator->() {
|
|
drawable.check();
|
|
return drawable.mut();
|
|
}
|
|
};
|
|
|
|
class View {
|
|
std::vector<RenderCall> m_RenderCalls;
|
|
|
|
protected:
|
|
void Rectangle(const float x, const float y, sf::Color color = sf::Color::White) {
|
|
auto shape = new sf::RectangleShape(sf::Vector2f(x, y));
|
|
shape->setFillColor(color);
|
|
m_RenderCalls.emplace_back(sf::RenderStates(), shape);
|
|
}
|
|
|
|
public:
|
|
virtual ~View() = default;
|
|
|
|
[[nodiscard]] const std::vector<RenderCall> &renderCalls() const {
|
|
return m_RenderCalls;
|
|
}
|
|
|
|
virtual bool update()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void draw() {
|
|
if (!m_RenderCalls.empty())
|
|
{
|
|
m_RenderCalls.clear();
|
|
}
|
|
body();
|
|
}
|
|
virtual void body() = 0;
|
|
};
|
|
|
|
class Renderer {
|
|
public:
|
|
explicit Renderer(const MutRef<View> &_view) : view(_view) { view->body(); }
|
|
|
|
MutRef<View> view;
|
|
|
|
void update() {
|
|
if (view->update())
|
|
view->draw();
|
|
}
|
|
|
|
void render(sf::RenderTarget &target, const sf::RenderStates &states) const {
|
|
for (const auto &renderCall: view->renderCalls()) {
|
|
renderCall.draw(target, states);
|
|
}
|
|
}
|
|
};
|
|
}
|