@@ -51,7 +51,7 @@ private: | |||
float deactivate_timer_ = DEACTIVATE_INTERVAL; | |||
struct Visuals { | |||
RaiiPtr<SDL_Texture> texture_ = makeRaiiPtr<SDL_Texture>(nullptr, SDL_DestroyTexture); | |||
CPtr<SDL_Texture, SDL_DestroyTexture> texture_; | |||
}; | |||
std::unique_ptr<Visuals> visuals_; | |||
}; |
@@ -23,7 +23,7 @@ public: | |||
private: | |||
SDL_Texture *tex_; | |||
RaiiPtr<SDL_Surface> surf_ = makeRaiiPtr<SDL_Surface>(nullptr, SDL_FreeSurface); | |||
CPtr<SDL_Surface, SDL_FreeSurface> surf_; | |||
}; | |||
class TexColorMod: NonCopyable { |
@@ -1,3 +1,4 @@ | |||
#pragma once | |||
#include <optional> | |||
@@ -19,37 +20,25 @@ protected: | |||
NonCopyable &operator=(const NonCopyable &) = delete; | |||
}; | |||
template<typename T, typename Del = void (*)(T *)> | |||
using RaiiPtr = std::unique_ptr<T, Del>; | |||
// Take a deleter function, turn it into a class with an operator() for unique_ptr | |||
template<typename T, void (*Func)(T *)> | |||
class CPtrDeleter { | |||
public: | |||
void operator()(T *ptr) { Func(ptr); } | |||
}; | |||
template<typename T, typename Del> | |||
RaiiPtr<T, Del> makeRaiiPtr(T *val, Del d) { | |||
return std::unique_ptr<T, Del>(val, d); | |||
} | |||
// This is just a bit nicer to use than using unique_ptr directly | |||
template<typename T, void (*Func)(T *)> | |||
using CPtr = std::unique_ptr<T, CPtrDeleter<T, Func>>; | |||
template<typename Func> | |||
// Take a function, run it when the object goes out of scope | |||
template<void (*Func)()> | |||
class Deferred: NonCopyable { | |||
public: | |||
Deferred(Func func): func_(func) {} | |||
Deferred(Deferred &&def) noexcept: func_(def.func_) { def.active_ = false; } | |||
~Deferred() { if (active_) func_(); } | |||
Deferred &operator=(Deferred &&def) noexcept { | |||
func_ = def.func_; | |||
def.active_ = false; | |||
return *this; | |||
} | |||
private: | |||
Func func_; | |||
bool active_ = true; | |||
Deferred() = default; | |||
~Deferred() { Func(); } | |||
}; | |||
template<typename Func> | |||
Deferred<Func> makeDeferred(Func func) { | |||
return Deferred(func); | |||
} | |||
// Calling begin/end is stupid... | |||
template<typename T> | |||
auto callBegin(T &v) { |
@@ -8,7 +8,7 @@ | |||
namespace Swan { | |||
void PerfCounter::render() { | |||
Deferred win([]{ ImGui::End(); }); | |||
Deferred<ImGui::End> win; | |||
if (!ImGui::Begin("Perf Stats")) | |||
return; | |||
@@ -67,40 +67,37 @@ int main(int argc, char **argv) { | |||
} | |||
sdlassert(SDL_Init(SDL_INIT_VIDEO) >= 0, "Could not initialize SDL"); | |||
auto sdl = makeDeferred([] { SDL_Quit(); }); | |||
Deferred<SDL_Quit> sdl; | |||
int imgflags = IMG_INIT_PNG; | |||
imgassert(IMG_Init(imgflags) == imgflags, "Could not initialize SDL_Image"); | |||
auto sdl_image = makeDeferred([] { IMG_Quit(); }); | |||
Deferred<IMG_Quit> sdl_image; | |||
// Create the window | |||
auto window = makeRaiiPtr( | |||
CPtr<SDL_Window, SDL_DestroyWindow> window( | |||
SDL_CreateWindow( | |||
"Project: SWAN", | |||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, | |||
(int)(640 * gui_scale), (int)(480 * gui_scale), winflags), | |||
SDL_DestroyWindow); | |||
(int)(640 * gui_scale), (int)(480 * gui_scale), winflags)); | |||
// Load and display application icon | |||
auto icon = makeRaiiPtr( | |||
IMG_Load("assets/icon.png"), | |||
SDL_FreeSurface); | |||
CPtr<SDL_Surface, SDL_FreeSurface> icon( | |||
IMG_Load("assets/icon.png")); | |||
sdlassert(icon, "Could not load icon"); | |||
SDL_SetWindowIcon(window.get(), icon.get()); | |||
auto renderer = makeRaiiPtr( | |||
SDL_CreateRenderer(window.get(), -1, renderflags), | |||
SDL_DestroyRenderer); | |||
CPtr<SDL_Renderer, SDL_DestroyRenderer> renderer( | |||
SDL_CreateRenderer(window.get(), -1, renderflags)); | |||
sdlassert(renderer, "Could not create renderer"); | |||
Win win(window.get(), renderer.get(), gui_scale); | |||
// Init ImGUI and ImGUI_SDL | |||
IMGUI_CHECKVERSION(); | |||
ImGui::CreateContext(); | |||
auto imgui = makeDeferred([] { ImGui::DestroyContext(); }); | |||
CPtr<ImGuiContext, ImGui::DestroyContext> context( | |||
ImGui::CreateContext()); | |||
ImGuiSDL::Initialize(renderer.get(), (int)win.getPixSize().x, (int)win.getPixSize().y); | |||
auto imgui_sdl = makeDeferred([] { ImGuiSDL::Deinitialize(); }); | |||
Deferred<ImGuiSDL::Deinitialize> imgui_sdl; | |||
info << "Initialized with window size " << win.getPixSize(); | |||
// ImGuiIO is to glue SDL and ImGUI together |