Compare commits
3 Commits
ee4ea4ae0a
...
5ebd609507
Author | SHA1 | Date | |
---|---|---|---|
5ebd609507 | |||
b38fa1b68b | |||
41258cda5b |
@ -1,5 +1,5 @@
|
||||
|
||||
#include "raid/raid.hpp"
|
||||
#include "raid/application.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
@ -5,6 +5,7 @@ src_files = Split("""
|
||||
main.cpp
|
||||
|
||||
application.cpp
|
||||
frames/data_table.cpp
|
||||
""")
|
||||
|
||||
prog_app = env.UnityProgram(
|
||||
|
@ -13,6 +13,7 @@ bool Application::init()
|
||||
setMainWindowFlags(raid::DEFAULT_MAIN_WINDOW_FLAGS | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking);
|
||||
setMainWindowStyle(ImGuiStyleVar_WindowPadding, ImVec2());
|
||||
setMainWindowStyle(ImGuiStyleVar_WindowBorderSize, 0.f);
|
||||
std::ranges::fill(mFrameOpen, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -35,14 +36,35 @@ void Application::render()
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Frames"))
|
||||
{
|
||||
for (std::size_t idx = 0; idx < NUM_FRAMES; ++idx) {
|
||||
ImGui::MenuItem(FRAMES[idx].title, nullptr, &mFrameOpen[idx]);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Debug"))
|
||||
{
|
||||
ImGui::MenuItem("ImGui Metrics", nullptr, &mShowMetrics);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
ImGui::Text("hi");
|
||||
|
||||
ImGui::ShowMetricsWindow();
|
||||
ImGui::Begin("Test");
|
||||
ImGui::Text("Test Content");
|
||||
ImGui::End();
|
||||
const ImGuiID dockID = ImGui::GetID(this);
|
||||
ImGui::DockSpace(dockID);
|
||||
|
||||
if (mShowMetrics) {
|
||||
ImGui::ShowMetricsWindow(&mShowMetrics);
|
||||
}
|
||||
|
||||
for (std::size_t idx = 0; idx < NUM_FRAMES; ++idx)
|
||||
{
|
||||
ImGui::SetNextWindowDockID(dockID, ImGuiCond_FirstUseEver);
|
||||
if (mFrameOpen[idx]) {
|
||||
FRAMES[idx].render(mFrameOpen[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Application::getFolderName()
|
||||
|
@ -4,12 +4,28 @@
|
||||
#if !defined(RAID_TEST_APPLICATION_HPP_INCLUDED)
|
||||
#define RAID_TEST_APPLICATION_HPP_INCLUDED 1
|
||||
|
||||
#include <array>
|
||||
#include "raid/raid.hpp"
|
||||
#include "./frames/data_table.hpp"
|
||||
|
||||
namespace raid_test
|
||||
{
|
||||
class Application : public raid::Application
|
||||
{
|
||||
private:
|
||||
struct Frame
|
||||
{
|
||||
using render_fn_t = void (*)(bool& open);
|
||||
const char* title;
|
||||
render_fn_t render;
|
||||
};
|
||||
static constexpr Frame FRAMES[] = {
|
||||
{.title = DATA_TABLE_TITLE, .render = &renderDataTable}
|
||||
};
|
||||
static constexpr std::size_t NUM_FRAMES = sizeof(FRAMES) / sizeof(FRAMES[0]);
|
||||
|
||||
bool mShowMetrics = false;
|
||||
std::array<bool, NUM_FRAMES> mFrameOpen{};
|
||||
protected:
|
||||
bool init() override;
|
||||
void configureImgui() override;
|
||||
|
89
private/raid_test/frames/data_table.cpp
Normal file
89
private/raid_test/frames/data_table.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
#include "raid_test/frames/data_table.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
#include <imgui.h>
|
||||
#include "raid/imraid.hpp"
|
||||
|
||||
namespace raid_test
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const std::array FIRST_NAMES = {
|
||||
"Emma", "Hannah", "Mia", "Leonie", "Lina", "Marie", "Sophia", "Charlotte", "Paula", "Greta", "Frieda", "Ella", "Freia",
|
||||
"Leon", "Paul", "Maximilian", "Ben", "Lukas", "Finn", "Fiete", "Felix", "Moritz", "Jakob", "Tim", "Emil", "Theo",
|
||||
"James", "Mary", "Michael", "Patricia", "John", "Jennifer", "Robert", "Linda", "David", "Elizabeth", "William",
|
||||
"Barbara", "Richard", "Susan", "Joseph", "Jessica", "Thomas", "Karen", "Christopher", "Sarah"
|
||||
};
|
||||
const std::array LAST_NAMES = {
|
||||
"Müller", "Schmidt", "Schneider", "Fischer", "Meyer", "Weber", "Hofmann", "Wagner", "Becker", "Schulz", "Schäfer",
|
||||
"Koch", "Bauer", "Richter", "Klein", "Schröder", "Wolf", "Neumann", "Schwarz", "Schmitz", "Smith", "Johnson",
|
||||
"Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodríguez", "Martínez", "Hernández", "López", "Gonzalez",
|
||||
"Wilson", "Anderson", "Thomas", "Taylor", "Moore", "Jackson", "Martin"
|
||||
};
|
||||
|
||||
constexpr int MIN_AGE = 18;
|
||||
constexpr int MAX_AGE = 120;
|
||||
constexpr double HEIGHT_MEAN = 1.75;
|
||||
constexpr double HEIGHT_STDDEV = 0.1;
|
||||
constexpr std::size_t NUM_PEOPLE = 5000;
|
||||
|
||||
struct Person
|
||||
{
|
||||
const char* firstName;
|
||||
const char* lastName;
|
||||
int age;
|
||||
double height;
|
||||
};
|
||||
|
||||
using rand_int_t = std::mt19937::result_type;
|
||||
|
||||
std::mt19937 gRandom(std::random_device{}());
|
||||
std::uniform_int_distribution<rand_int_t> gFirstNameDistribution(0, static_cast<rand_int_t>(FIRST_NAMES.size()-1));
|
||||
std::uniform_int_distribution<rand_int_t> gLastNameDistribution(0, static_cast<rand_int_t>(LAST_NAMES.size()-1));
|
||||
std::uniform_int_distribution<rand_int_t> gAgeDistribution(static_cast<rand_int_t>(MIN_AGE), static_cast<rand_int_t>(MAX_AGE));
|
||||
std::normal_distribution gHeightDistribution(HEIGHT_MEAN, HEIGHT_STDDEV);
|
||||
|
||||
[[nodiscard]]
|
||||
Person randomPerson()
|
||||
{
|
||||
return {
|
||||
.firstName = FIRST_NAMES[gFirstNameDistribution(gRandom)],
|
||||
.lastName = LAST_NAMES[gLastNameDistribution(gRandom)],
|
||||
.age = static_cast<int>(gAgeDistribution(gRandom)),
|
||||
.height = gHeightDistribution(gRandom)
|
||||
};
|
||||
}
|
||||
|
||||
const std::array<Person, NUM_PEOPLE> PEOPLE = []()
|
||||
{
|
||||
std::array<Person, NUM_PEOPLE> result;
|
||||
std::ranges::generate(result, randomPerson);
|
||||
return result;
|
||||
}();
|
||||
|
||||
const std::array DATA_TABLE_COLUMNS = {
|
||||
ImRaid::MakeStringColumn("First Name", &Person::firstName),
|
||||
ImRaid::MakeStringColumn("Last Name", &Person::lastName),
|
||||
ImRaid::MakeColumn("Age", "%d years", &Person::age),
|
||||
ImRaid::MakeColumn("Height", "%.2f m", &Person::height)
|
||||
};
|
||||
const ImRaid::DataTableOptions<Person> DATA_TABLE_OPTIONS = {
|
||||
.columns = DATA_TABLE_COLUMNS
|
||||
};
|
||||
ImRaid::DataTableState gDataTableState;
|
||||
}
|
||||
void renderDataTable(bool& open)
|
||||
{
|
||||
if (!ImGui::Begin(DATA_TABLE_TITLE, &open))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImRaid::DataTable("people", DATA_TABLE_OPTIONS, PEOPLE, gDataTableState);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
} // namespace raid_test
|
14
private/raid_test/frames/data_table.hpp
Normal file
14
private/raid_test/frames/data_table.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(RAID_TEST_FRAMES_DATA_TABLE_HPP_INCLUDED)
|
||||
#define RAID_TEST_FRAMES_DATA_TABLE_HPP_INCLUDED 1
|
||||
|
||||
namespace raid_test
|
||||
{
|
||||
inline constexpr const char* DATA_TABLE_TITLE = "Data Table";
|
||||
|
||||
void renderDataTable(bool& open);
|
||||
} // namespace raid_test
|
||||
|
||||
#endif // !defined(RAID_TEST_FRAMES_DATA_TABLE_HPP_INCLUDED)
|
251
public/raid/application.hpp
Normal file
251
public/raid/application.hpp
Normal file
@ -0,0 +1,251 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(RAID_APPLICATION_HPP_INCLUDED)
|
||||
#define RAID_APPLICATION_HPP_INCLUDED 1
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <variant>
|
||||
#include <fmt/format.h>
|
||||
#include <imgui.h>
|
||||
#include <mijin/async/coroutine.hpp>
|
||||
#include <mijin/util/bitflags.hpp>
|
||||
#include <mijin/virtual_filesystem/memory.hpp>
|
||||
#include <mijin/virtual_filesystem/stacked.hpp>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#include "./internal/opengl.hpp"
|
||||
#include "./internal/vulkan.hpp"
|
||||
|
||||
namespace raid
|
||||
{
|
||||
inline constexpr int ERR_INIT_FAILED = 100;
|
||||
inline constexpr ImGuiWindowFlags DEFAULT_MAIN_WINDOW_FLAGS = 0
|
||||
| ImGuiWindowFlags_NoBackground
|
||||
| ImGuiWindowFlags_NoDecoration
|
||||
| ImGuiWindowFlags_NoBringToFrontOnFocus
|
||||
| ImGuiWindowFlags_NoNav;
|
||||
inline constexpr const char* DEFAULT_FONT_PATH = "/data/fonts/NotoSans-Regular.ttf";
|
||||
|
||||
enum class MessageSeverity : unsigned char
|
||||
{
|
||||
INFO,
|
||||
WARNING,
|
||||
ERROR
|
||||
};
|
||||
|
||||
struct Message
|
||||
{
|
||||
MessageSeverity severity;
|
||||
const char* text;
|
||||
};
|
||||
|
||||
struct FontFlags : mijin::BitFlags<FontFlags>
|
||||
{
|
||||
bool pixelSnapH : 1 = false;
|
||||
};
|
||||
|
||||
struct FontConfig
|
||||
{
|
||||
fs::path path;
|
||||
std::vector<std::pair<ImWchar, ImWchar>> glyphRanges;
|
||||
float size = 20.f;
|
||||
FontFlags flags;
|
||||
};
|
||||
|
||||
struct ApplicationFlags : mijin::BitFlags<ApplicationFlags>
|
||||
{
|
||||
/**
|
||||
* (Linux only) prefer X11 even when on Wayland. Required for multi-viewport support, but currently really buggy.
|
||||
* \see https://github.com/ocornut/imgui/issues/8609
|
||||
* \see https://github.com/ocornut/imgui/issues/8587
|
||||
*/
|
||||
bool x11OnWayland : 1 = false;
|
||||
};
|
||||
|
||||
enum class GraphicsAPI : std::uint8_t
|
||||
{
|
||||
OPENGL,
|
||||
VULKAN
|
||||
};
|
||||
|
||||
struct ApplicationConfig
|
||||
{
|
||||
ApplicationFlags flags = {};
|
||||
GraphicsAPI graphicsApi = GraphicsAPI::OPENGL;
|
||||
};
|
||||
|
||||
class Application : private MixinOpenGLApplication, MixinVulkanApplication
|
||||
{
|
||||
private:
|
||||
SDL_Window* mWindow = nullptr;
|
||||
|
||||
mijin::StackedFileSystemAdapter mFS;
|
||||
mijin::MemoryFileSystemAdapter* mMemoryFS = nullptr;
|
||||
mijin::SimpleTaskLoop mTaskLoop;
|
||||
std::unordered_map<fs::path, ImTextureID> mTextures;
|
||||
|
||||
bool mRunning = true;
|
||||
ImGuiWindowFlags mMainWindowFlags = DEFAULT_MAIN_WINDOW_FLAGS;
|
||||
std::unordered_map<ImGuiStyleVar, std::variant<float, ImVec2>> mMainWindowStyles;
|
||||
const ApplicationConfig mConfig;
|
||||
|
||||
union
|
||||
{
|
||||
OpenGLData gl;
|
||||
VulkanData vk;
|
||||
};
|
||||
public:
|
||||
explicit Application(ApplicationConfig config = {}) noexcept : mConfig(config) {}
|
||||
virtual ~Application() = default;
|
||||
|
||||
[[nodiscard]]
|
||||
const ApplicationConfig& getConfig() const noexcept { return mConfig; }
|
||||
|
||||
[[nodiscard]]
|
||||
mijin::StackedFileSystemAdapter& getFS() { return mFS; }
|
||||
|
||||
[[nodiscard]]
|
||||
mijin::MemoryFileSystemAdapter& getMemoryFS()
|
||||
{
|
||||
MIJIN_ASSERT_FATAL(mMemoryFS != nullptr, "Memory FS has not been initialized yet.");
|
||||
return *mMemoryFS;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
mijin::SimpleTaskLoop& getLoop() { return mTaskLoop; }
|
||||
|
||||
[[nodiscard]]
|
||||
ImGuiWindowFlags getMainWindowFlags() const { return mMainWindowFlags; }
|
||||
|
||||
void setMainWindowFlags(ImGuiWindowFlags flags) { mMainWindowFlags = flags; }
|
||||
void setMainWindowStyle(ImGuiStyleVar variable, std::variant<float, ImVec2> value) { mMainWindowStyles.emplace(variable, value); }
|
||||
void unsetMainWindowStyle(ImGuiStyleVar variable) { mMainWindowStyles.erase(variable); }
|
||||
void requestQuit() { mRunning = false; }
|
||||
|
||||
[[nodiscard]]
|
||||
int run(int argc, char* argv[]);
|
||||
|
||||
[[nodiscard]]
|
||||
bool loadFonts(std::span<const FontConfig> fonts);
|
||||
|
||||
[[nodiscard]]
|
||||
bool loadFont(const FontConfig& font)
|
||||
{
|
||||
return loadFonts({&font, 1});
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ImTextureID getOrLoadTexture(fs::path path);
|
||||
|
||||
void destroyTexture(ImTextureID texture);
|
||||
|
||||
protected:
|
||||
virtual void render() = 0;
|
||||
virtual std::string getFolderName() = 0;
|
||||
virtual std::string getWindowTitle() = 0;
|
||||
virtual void configureImgui();
|
||||
virtual std::vector<FontConfig> getDefaultFonts();
|
||||
virtual void initMemoryFS();
|
||||
virtual void handleMessage(const Message& message);
|
||||
virtual void handleSDLEvent(const SDL_Event& event);
|
||||
virtual void handleSDLError(const char* message);
|
||||
|
||||
void msgInfo(const char* text)
|
||||
{
|
||||
handleMessage({
|
||||
.severity = MessageSeverity::INFO,
|
||||
.text = text
|
||||
});
|
||||
}
|
||||
void msgWarning(const char* text)
|
||||
{
|
||||
handleMessage({
|
||||
.severity = MessageSeverity::WARNING,
|
||||
.text = text
|
||||
});
|
||||
}
|
||||
void msgError(const char* text)
|
||||
{
|
||||
handleMessage({
|
||||
.severity = MessageSeverity::ERROR,
|
||||
.text = text
|
||||
});
|
||||
}
|
||||
void msgInfo(const std::string& text)
|
||||
{
|
||||
msgInfo(text.c_str());
|
||||
}
|
||||
void msgWarning(const std::string& text)
|
||||
{
|
||||
msgWarning(text.c_str());
|
||||
}
|
||||
void msgError(const std::string& text)
|
||||
{
|
||||
msgError(text.c_str());
|
||||
}
|
||||
template<typename TArg, typename... TArgs>
|
||||
void msgInfo(fmt::format_string<TArg, TArgs...> format, TArg&& arg, TArgs&&... args)
|
||||
{
|
||||
std::string text = fmt::format(format, std::forward<TArg>(arg), std::forward<TArgs>(args)...);
|
||||
msgInfo(text);
|
||||
}
|
||||
template<typename TArg, typename... TArgs>
|
||||
void msgWarning(fmt::format_string<TArg, TArgs...> format, TArg&& arg, TArgs&&... args)
|
||||
{
|
||||
std::string text = fmt::format(format, std::forward<TArg>(arg), std::forward<TArgs>(args)...);
|
||||
msgWarning(text);
|
||||
}
|
||||
template<typename TArg, typename... TArgs>
|
||||
void msgError(fmt::format_string<TArg, TArgs...> format, TArg&& arg, TArgs&&... args)
|
||||
{
|
||||
std::string text = fmt::format(format, std::forward<TArg>(arg), std::forward<TArgs>(args)...);
|
||||
msgError(text);
|
||||
}
|
||||
virtual bool init();
|
||||
virtual void cleanup();
|
||||
private:
|
||||
bool initSDL();
|
||||
bool initOpenGL();
|
||||
bool initVulkan();
|
||||
bool initImGui();
|
||||
void handleSDLEvents();
|
||||
void loadImGuiConfig();
|
||||
void saveImGuiConfig();
|
||||
};
|
||||
|
||||
using render_cb_t = std::function<void()>;
|
||||
struct QuickAppOptions
|
||||
{
|
||||
struct
|
||||
{
|
||||
render_cb_t render;
|
||||
} callbacks;
|
||||
std::string folderName = "raid";
|
||||
std::string windowTitle = "RAID";
|
||||
ImGuiWindowFlags mainWindowFlags = DEFAULT_MAIN_WINDOW_FLAGS;
|
||||
};
|
||||
|
||||
class QuickApp : public Application
|
||||
{
|
||||
private:
|
||||
render_cb_t mRenderCallback;
|
||||
std::string mFolderName;
|
||||
std::string mWindowTitle;
|
||||
public:
|
||||
explicit QuickApp(ApplicationConfig config = {}) noexcept : Application(config) {}
|
||||
|
||||
void preInit(QuickAppOptions options);
|
||||
void render() override;
|
||||
std::string getFolderName() override;
|
||||
std::string getWindowTitle() override;
|
||||
|
||||
static QuickApp& get();
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
int runQuick(int argc, char* argv[], QuickAppOptions options);
|
||||
} // namespace raid
|
||||
|
||||
#endif // !defined(RAID_APPLICATION_HPP_INCLUDED)
|
@ -114,7 +114,7 @@ inline void DataTable(const char* strId, const DataTableOptions<TObject>& option
|
||||
sortSpecs->SpecsDirty = false;
|
||||
|
||||
const ImGuiTableColumnSortSpecs& specs = *sortSpecs->Specs;
|
||||
state.dirty |= (specs.ColumnIndex != state.sortColumn);
|
||||
state.dirty |= (specs.ColumnIndex != static_cast<ImS16>(state.sortColumn));
|
||||
state.sortColumn = specs.ColumnIndex;
|
||||
state.sortDescending = specs.SortDirection == ImGuiSortDirection_Descending;
|
||||
}
|
||||
@ -154,6 +154,36 @@ inline void DataTable(const char* strId, const DataTableOptions<TObject>& option
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
template<typename TObject>
|
||||
inline DataTableColumn<TObject> MakeStringColumn(const char* header, const char* TObject::* member)
|
||||
{
|
||||
return {
|
||||
.header = header,
|
||||
.renderer = [member](const auto& args) { ImGui::TextUnformatted(args.object.*member); },
|
||||
.comparator = [member](const TObject& left, const TObject& right) { return std::string_view(left.*member) < std::string_view(right.*member); }
|
||||
};
|
||||
}
|
||||
|
||||
template<typename TObject>
|
||||
inline DataTableColumn<TObject> MakeStringColumn(const char* header, std::string TObject::* member)
|
||||
{
|
||||
return {
|
||||
.header = header,
|
||||
.renderer = [member](const auto& args) { ImGui::TextUnformatted((args.object.*member).c_str()); },
|
||||
.comparator = [member](const TObject& left, const TObject& right) { return left.*member < right.*member; }
|
||||
};
|
||||
}
|
||||
|
||||
template<typename TObject, typename TMember>
|
||||
inline DataTableColumn<TObject> MakeColumn(const char* header, const char* fmt, TMember TObject::* member)
|
||||
{
|
||||
return {
|
||||
.header = header,
|
||||
.renderer = [fmt, member](const auto& args) { ImGui::Text(fmt, args.object.*member); },
|
||||
.comparator = [member](const TObject& left, const TObject& right) { return left.*member < right.*member; }
|
||||
};
|
||||
}
|
||||
} // namespace ImRaid
|
||||
|
||||
#endif // !defined(RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED)
|
||||
|
@ -4,248 +4,6 @@
|
||||
#if !defined(RAID_PUBLIC_RAID_RAID_HPP_INCLUDED)
|
||||
#define RAID_PUBLIC_RAID_RAID_HPP_INCLUDED 1
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <variant>
|
||||
#include <fmt/format.h>
|
||||
#include <imgui.h>
|
||||
#include <mijin/async/coroutine.hpp>
|
||||
#include <mijin/util/bitflags.hpp>
|
||||
#include <mijin/virtual_filesystem/memory.hpp>
|
||||
#include <mijin/virtual_filesystem/stacked.hpp>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#include "./internal/opengl.hpp"
|
||||
#include "./internal/vulkan.hpp"
|
||||
|
||||
namespace raid
|
||||
{
|
||||
inline constexpr int ERR_INIT_FAILED = 100;
|
||||
inline constexpr ImGuiWindowFlags DEFAULT_MAIN_WINDOW_FLAGS = 0
|
||||
| ImGuiWindowFlags_NoBackground
|
||||
| ImGuiWindowFlags_NoDecoration
|
||||
| ImGuiWindowFlags_NoBringToFrontOnFocus
|
||||
| ImGuiWindowFlags_NoNav;
|
||||
inline constexpr const char* DEFAULT_FONT_PATH = "/data/fonts/NotoSans-Regular.ttf";
|
||||
|
||||
enum class MessageSeverity : unsigned char
|
||||
{
|
||||
INFO,
|
||||
WARNING,
|
||||
ERROR
|
||||
};
|
||||
|
||||
struct Message
|
||||
{
|
||||
MessageSeverity severity;
|
||||
const char* text;
|
||||
};
|
||||
|
||||
struct FontFlags : mijin::BitFlags<FontFlags>
|
||||
{
|
||||
bool pixelSnapH : 1 = false;
|
||||
};
|
||||
|
||||
struct FontConfig
|
||||
{
|
||||
fs::path path;
|
||||
std::vector<std::pair<ImWchar, ImWchar>> glyphRanges;
|
||||
float size = 20.f;
|
||||
FontFlags flags;
|
||||
};
|
||||
|
||||
struct ApplicationFlags : mijin::BitFlags<ApplicationFlags>
|
||||
{
|
||||
/**
|
||||
* (Linux only) prefer X11 even when on Wayland. Required for multi-viewport support, but currently really buggy.
|
||||
* \see https://github.com/ocornut/imgui/issues/8609
|
||||
* \see https://github.com/ocornut/imgui/issues/8587
|
||||
*/
|
||||
bool x11OnWayland : 1 = false;
|
||||
};
|
||||
|
||||
enum class GraphicsAPI : std::uint8_t
|
||||
{
|
||||
OPENGL,
|
||||
VULKAN
|
||||
};
|
||||
|
||||
struct ApplicationConfig
|
||||
{
|
||||
ApplicationFlags flags = {};
|
||||
GraphicsAPI graphicsApi = GraphicsAPI::OPENGL;
|
||||
};
|
||||
|
||||
class Application : private MixinOpenGLApplication, MixinVulkanApplication
|
||||
{
|
||||
private:
|
||||
SDL_Window* mWindow = nullptr;
|
||||
|
||||
mijin::StackedFileSystemAdapter mFS;
|
||||
mijin::MemoryFileSystemAdapter* mMemoryFS = nullptr;
|
||||
mijin::SimpleTaskLoop mTaskLoop;
|
||||
std::unordered_map<fs::path, ImTextureID> mTextures;
|
||||
|
||||
bool mRunning = true;
|
||||
ImGuiWindowFlags mMainWindowFlags = DEFAULT_MAIN_WINDOW_FLAGS;
|
||||
std::unordered_map<ImGuiStyleVar, std::variant<float, ImVec2>> mMainWindowStyles;
|
||||
const ApplicationConfig mConfig;
|
||||
|
||||
union
|
||||
{
|
||||
OpenGLData gl;
|
||||
VulkanData vk;
|
||||
};
|
||||
public:
|
||||
explicit Application(ApplicationConfig config = {}) noexcept : mConfig(config) {}
|
||||
virtual ~Application() = default;
|
||||
|
||||
[[nodiscard]]
|
||||
const ApplicationConfig& getConfig() const noexcept { return mConfig; }
|
||||
|
||||
[[nodiscard]]
|
||||
mijin::StackedFileSystemAdapter& getFS() { return mFS; }
|
||||
|
||||
[[nodiscard]]
|
||||
mijin::MemoryFileSystemAdapter& getMemoryFS()
|
||||
{
|
||||
MIJIN_ASSERT_FATAL(mMemoryFS != nullptr, "Memory FS has not been initialized yet.");
|
||||
return *mMemoryFS;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
mijin::SimpleTaskLoop& getLoop() { return mTaskLoop; }
|
||||
|
||||
[[nodiscard]]
|
||||
ImGuiWindowFlags getMainWindowFlags() const { return mMainWindowFlags; }
|
||||
|
||||
void setMainWindowFlags(ImGuiWindowFlags flags) { mMainWindowFlags = flags; }
|
||||
void setMainWindowStyle(ImGuiStyleVar variable, std::variant<float, ImVec2> value) { mMainWindowStyles.emplace(variable, value); }
|
||||
void unsetMainWindowStyle(ImGuiStyleVar variable) { mMainWindowStyles.erase(variable); }
|
||||
void requestQuit() { mRunning = false; }
|
||||
|
||||
[[nodiscard]]
|
||||
int run(int argc, char* argv[]);
|
||||
|
||||
[[nodiscard]]
|
||||
bool loadFonts(std::span<const FontConfig> fonts);
|
||||
|
||||
[[nodiscard]]
|
||||
bool loadFont(const FontConfig& font)
|
||||
{
|
||||
return loadFonts({&font, 1});
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ImTextureID getOrLoadTexture(fs::path path);
|
||||
|
||||
void destroyTexture(ImTextureID texture);
|
||||
|
||||
protected:
|
||||
virtual void render() = 0;
|
||||
virtual std::string getFolderName() = 0;
|
||||
virtual std::string getWindowTitle() = 0;
|
||||
virtual void configureImgui();
|
||||
virtual std::vector<FontConfig> getDefaultFonts();
|
||||
virtual void initMemoryFS();
|
||||
virtual void handleMessage(const Message& message);
|
||||
virtual void handleSDLEvent(const SDL_Event& event);
|
||||
virtual void handleSDLError(const char* message);
|
||||
|
||||
void msgInfo(const char* text)
|
||||
{
|
||||
handleMessage({
|
||||
.severity = MessageSeverity::INFO,
|
||||
.text = text
|
||||
});
|
||||
}
|
||||
void msgWarning(const char* text)
|
||||
{
|
||||
handleMessage({
|
||||
.severity = MessageSeverity::WARNING,
|
||||
.text = text
|
||||
});
|
||||
}
|
||||
void msgError(const char* text)
|
||||
{
|
||||
handleMessage({
|
||||
.severity = MessageSeverity::ERROR,
|
||||
.text = text
|
||||
});
|
||||
}
|
||||
void msgInfo(const std::string& text)
|
||||
{
|
||||
msgInfo(text.c_str());
|
||||
}
|
||||
void msgWarning(const std::string& text)
|
||||
{
|
||||
msgWarning(text.c_str());
|
||||
}
|
||||
void msgError(const std::string& text)
|
||||
{
|
||||
msgError(text.c_str());
|
||||
}
|
||||
template<typename TArg, typename... TArgs>
|
||||
void msgInfo(fmt::format_string<TArg, TArgs...> format, TArg&& arg, TArgs&&... args)
|
||||
{
|
||||
std::string text = fmt::format(format, std::forward<TArg>(arg), std::forward<TArgs>(args)...);
|
||||
msgInfo(text);
|
||||
}
|
||||
template<typename TArg, typename... TArgs>
|
||||
void msgWarning(fmt::format_string<TArg, TArgs...> format, TArg&& arg, TArgs&&... args)
|
||||
{
|
||||
std::string text = fmt::format(format, std::forward<TArg>(arg), std::forward<TArgs>(args)...);
|
||||
msgWarning(text);
|
||||
}
|
||||
template<typename TArg, typename... TArgs>
|
||||
void msgError(fmt::format_string<TArg, TArgs...> format, TArg&& arg, TArgs&&... args)
|
||||
{
|
||||
std::string text = fmt::format(format, std::forward<TArg>(arg), std::forward<TArgs>(args)...);
|
||||
msgError(text);
|
||||
}
|
||||
virtual bool init();
|
||||
virtual void cleanup();
|
||||
private:
|
||||
bool initSDL();
|
||||
bool initOpenGL();
|
||||
bool initVulkan();
|
||||
bool initImGui();
|
||||
void handleSDLEvents();
|
||||
void loadImGuiConfig();
|
||||
void saveImGuiConfig();
|
||||
};
|
||||
|
||||
using render_cb_t = std::function<void()>;
|
||||
struct QuickAppOptions
|
||||
{
|
||||
struct
|
||||
{
|
||||
render_cb_t render;
|
||||
} callbacks;
|
||||
std::string folderName = "raid";
|
||||
std::string windowTitle = "RAID";
|
||||
ImGuiWindowFlags mainWindowFlags = DEFAULT_MAIN_WINDOW_FLAGS;
|
||||
};
|
||||
|
||||
class QuickApp : public Application
|
||||
{
|
||||
private:
|
||||
render_cb_t mRenderCallback;
|
||||
std::string mFolderName;
|
||||
std::string mWindowTitle;
|
||||
public:
|
||||
explicit QuickApp(ApplicationConfig config = {}) noexcept : Application(config) {}
|
||||
|
||||
void preInit(QuickAppOptions options);
|
||||
void render() override;
|
||||
std::string getFolderName() override;
|
||||
std::string getWindowTitle() override;
|
||||
|
||||
static QuickApp& get();
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
int runQuick(int argc, char* argv[], QuickAppOptions options);
|
||||
} // namespace raid
|
||||
#include "./application.hpp"
|
||||
|
||||
#endif // !defined(RAID_PUBLIC_RAID_RAID_HPP_INCLUDED)
|
||||
|
Loading…
x
Reference in New Issue
Block a user