Initial implementation.
This commit is contained in:
parent
1aa4656eb0
commit
f51dd5b437
66
.clang-format
Normal file
66
.clang-format
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Generated from CLion C/C++ Code Style settings
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: None
|
||||||
|
AlignOperands: Align
|
||||||
|
AllowAllArgumentsOnNextLine: false
|
||||||
|
AllowAllConstructorInitializersOnNextLine: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: Always
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: Always
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: true
|
||||||
|
AfterControlStatement: Always
|
||||||
|
AfterEnum: true
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: true
|
||||||
|
AfterUnion: true
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: true
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: false
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
ColumnLimit: 0
|
||||||
|
CompactNamespaces: false
|
||||||
|
ContinuationIndentWidth: 8
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 4
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: false
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 0
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
10
SConstruct
10
SConstruct
@ -1,10 +1,14 @@
|
|||||||
config = {
|
config = {
|
||||||
'PROJECT_NAME': 'spp_template'
|
'PROJECT_NAME': 'RAID Framework',
|
||||||
|
'CXX_NO_EXCEPTIONS': True
|
||||||
}
|
}
|
||||||
env = SConscript('external/scons-plus-plus/SConscript', exports = ['config'])
|
env = SConscript('external/scons-plus-plus/SConscript', exports = ['config'])
|
||||||
env.Append(CPPPATH = [Dir('private'), Dir('public')])
|
env.Append(CPPPATH = [Dir('private'), Dir('public')])
|
||||||
|
|
||||||
# app
|
# library
|
||||||
env = env.Module('private/spp_template/SModule')
|
env = env.Module('private/raid/SModule')
|
||||||
|
|
||||||
|
# test app
|
||||||
|
env = env.Module('private/raid_test/SModule')
|
||||||
|
|
||||||
env.Finalize()
|
env.Finalize()
|
||||||
|
2
external/scons-plus-plus
vendored
2
external/scons-plus-plus
vendored
@ -1 +1 @@
|
|||||||
Subproject commit c883f3c1c777357957e30fc44cf987e8bb62c818
|
Subproject commit c994752c3244fdf9835b1d3a5238094d2a799855
|
31
private/raid/SModule
Normal file
31
private/raid/SModule
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
src_files = Split("""
|
||||||
|
application.cpp
|
||||||
|
""")
|
||||||
|
|
||||||
|
lib_raid = env.UnityStaticLibrary(
|
||||||
|
name = 'RAID',
|
||||||
|
target = env['LIB_DIR'] + '/raid',
|
||||||
|
source = src_files,
|
||||||
|
dependencies = {
|
||||||
|
'fmt': {},
|
||||||
|
'mijin': {},
|
||||||
|
'imgui': {
|
||||||
|
'options': {
|
||||||
|
'docking': True,
|
||||||
|
'backends': [
|
||||||
|
'sdl3',
|
||||||
|
'opengl3'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'SDL': {
|
||||||
|
'min': (3,0,0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
env.Default(lib_raid)
|
||||||
|
|
||||||
|
Return('env')
|
240
private/raid/application.cpp
Normal file
240
private/raid/application.cpp
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
|
||||||
|
#include "raid/raid.hpp"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <fmt/base.h>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <mijin/debug/assert.hpp>
|
||||||
|
#include <mijin/util/scope_guard.hpp>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <backends/imgui_impl_opengl3.h>
|
||||||
|
#include <backends/imgui_impl_sdl3.h>
|
||||||
|
|
||||||
|
namespace raid
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr int GL_COLOR_BUFFER_BIT = 0x00004000;
|
||||||
|
const char* IMGUI_GLSL_VERSION = "#version 130";
|
||||||
|
}
|
||||||
|
|
||||||
|
int Application::run(int argc, char** argv)
|
||||||
|
{
|
||||||
|
(void) argc;
|
||||||
|
(void) argv;
|
||||||
|
|
||||||
|
MIJIN_SCOPE_EXIT {
|
||||||
|
cleanup();
|
||||||
|
};
|
||||||
|
if (!initSDL())
|
||||||
|
{
|
||||||
|
return ERR_INIT_FAILED;
|
||||||
|
}
|
||||||
|
if (!initGL())
|
||||||
|
{
|
||||||
|
return ERR_INIT_FAILED;
|
||||||
|
}
|
||||||
|
if (!initImGui())
|
||||||
|
{
|
||||||
|
return ERR_INIT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (mRunning)
|
||||||
|
{
|
||||||
|
handleSDLEvents();
|
||||||
|
|
||||||
|
if (SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MINIMIZED)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
|
ImGui_ImplSDL3_NewFrame();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos({0, 0});
|
||||||
|
ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize);
|
||||||
|
|
||||||
|
ImGui::Begin("##main", nullptr, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration);
|
||||||
|
render();
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
ImGui::Render();
|
||||||
|
|
||||||
|
glClearColor(0.3f, 0.3f, 0.3f, 1.f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
|
SDL_GL_SwapWindow(mWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::handleMessage(const Message& message)
|
||||||
|
{
|
||||||
|
switch (message.severity)
|
||||||
|
{
|
||||||
|
case MessageSeverity::INFO:
|
||||||
|
fmt::print("INFO: {}", message.text);
|
||||||
|
break;
|
||||||
|
case MessageSeverity::WARNING:
|
||||||
|
fmt::print("WARNING: {}", message.text);
|
||||||
|
break;
|
||||||
|
case MessageSeverity::ERROR:
|
||||||
|
fmt::print(stderr, "ERROR: {}", message.text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::handleSDLEvent(const SDL_Event& event)
|
||||||
|
{
|
||||||
|
switch (event.type)
|
||||||
|
{
|
||||||
|
case SDL_EVENT_QUIT:
|
||||||
|
mRunning = false;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::initSDL()
|
||||||
|
{
|
||||||
|
if (!SDL_Init(0))
|
||||||
|
{
|
||||||
|
msgError("Error initializing SDL: {}.", SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GL attributes must be set before window creation
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
|
||||||
|
// TODO: not sure if these really make sense, but they are in the example
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||||
|
|
||||||
|
const SDL_WindowFlags WINDOW_FLAGS = 0
|
||||||
|
| SDL_WINDOW_OPENGL
|
||||||
|
| SDL_WINDOW_RESIZABLE
|
||||||
|
| SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||||
|
mWindow = SDL_CreateWindow(
|
||||||
|
/* title = */ "RAID",
|
||||||
|
/* w = */ 1280,
|
||||||
|
/* h = */ 720,
|
||||||
|
/* flags = */ WINDOW_FLAGS
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::initGL()
|
||||||
|
{
|
||||||
|
mGLContext = SDL_GL_CreateContext(mWindow);
|
||||||
|
if (mWindow == nullptr)
|
||||||
|
{
|
||||||
|
msgError("Error creating SDL window: {}.", SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SDL_GL_MakeCurrent(mWindow, mGLContext);
|
||||||
|
SDL_GL_SetSwapInterval(1); // enable vsync, at least for now
|
||||||
|
|
||||||
|
glClear = reinterpret_cast<glClear_fn_t>(SDL_GL_GetProcAddress("glClear"));
|
||||||
|
glClearColor = reinterpret_cast<glClearColor_fn_t>(SDL_GL_GetProcAddress("glClearColor"));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::initImGui()
|
||||||
|
{
|
||||||
|
IMGUI_CHECKVERSION(); // not exactly useful when using static libs, but won't hurt
|
||||||
|
|
||||||
|
if (ImGui::CreateContext() == nullptr)
|
||||||
|
{
|
||||||
|
msgError("Error initializing ImGui context.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiIO& imguiIO = ImGui::GetIO();
|
||||||
|
imguiIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
|
imguiIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||||
|
|
||||||
|
// default style
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
|
// init the backends
|
||||||
|
if (!ImGui_ImplSDL3_InitForOpenGL(mWindow, mGLContext))
|
||||||
|
{
|
||||||
|
msgError("Error initializing ImGui SDL3 backend.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ImGui_ImplOpenGL3_Init(IMGUI_GLSL_VERSION))
|
||||||
|
{
|
||||||
|
msgError("Error initializing ImGui OpenGL3 backend.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init font
|
||||||
|
imguiIO.Fonts->AddFontDefault();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::cleanup()
|
||||||
|
{
|
||||||
|
if (ImGui::GetCurrentContext() != nullptr)
|
||||||
|
{
|
||||||
|
const ImGuiIO& imguiIO = ImGui::GetIO();
|
||||||
|
if (imguiIO.BackendRendererUserData != nullptr)
|
||||||
|
{
|
||||||
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
|
}
|
||||||
|
if (imguiIO.BackendPlatformUserData != nullptr)
|
||||||
|
{
|
||||||
|
ImGui_ImplSDL3_Shutdown();
|
||||||
|
}
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
}
|
||||||
|
if (mGLContext != nullptr)
|
||||||
|
{
|
||||||
|
SDL_GL_DestroyContext(mGLContext);
|
||||||
|
}
|
||||||
|
if (mWindow != nullptr)
|
||||||
|
{
|
||||||
|
SDL_DestroyWindow(mWindow);
|
||||||
|
}
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::handleSDLEvents()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
handleSDLEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickApp::init(QuickAppOptions options)
|
||||||
|
{
|
||||||
|
MIJIN_ASSERT_FATAL(options.callbacks.render, "Missing render callback.");
|
||||||
|
mOptions = std::move(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickApp::render()
|
||||||
|
{
|
||||||
|
mOptions.callbacks.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
int runQuick(int argc, char* argv[], QuickAppOptions options)
|
||||||
|
{
|
||||||
|
QuickApp app;
|
||||||
|
app.init(std::move(options));
|
||||||
|
return app.run(argc, argv);
|
||||||
|
}
|
||||||
|
}
|
@ -6,11 +6,12 @@ src_files = Split("""
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
prog_app = env.UnityProgram(
|
prog_app = env.UnityProgram(
|
||||||
name = 'Template',
|
name = 'Test App',
|
||||||
target = env['BIN_DIR'] + '/spp_template',
|
target = env['BIN_DIR'] + '/raid_test',
|
||||||
source = src_files,
|
source = src_files,
|
||||||
dependencies = {
|
dependencies = {
|
||||||
'mijin': {}
|
'mijin': {},
|
||||||
|
'RAID': {}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
env.Default(prog_app)
|
env.Default(prog_app)
|
21
private/raid_test/main.cpp
Normal file
21
private/raid_test/main.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
#include "raid/raid.hpp"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void render()
|
||||||
|
{
|
||||||
|
ImGui::Text("hi");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
return raid::runQuick(argc, argv, {
|
||||||
|
.callbacks = {
|
||||||
|
.render = &render
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
int main(int, char**)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
133
public/raid/raid.hpp
Normal file
133
public/raid/raid.hpp
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(RAID_PUBLIC_RAID_RAID_HPP_INCLUDED)
|
||||||
|
#define RAID_PUBLIC_RAID_RAID_HPP_INCLUDED 1
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
namespace raid
|
||||||
|
{
|
||||||
|
inline constexpr int ERR_INIT_FAILED = 100;
|
||||||
|
|
||||||
|
enum class MessageSeverity : unsigned char
|
||||||
|
{
|
||||||
|
INFO,
|
||||||
|
WARNING,
|
||||||
|
ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Message
|
||||||
|
{
|
||||||
|
MessageSeverity severity;
|
||||||
|
const char* text;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Application
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool mRunning = true;
|
||||||
|
SDL_Window* mWindow = nullptr;
|
||||||
|
SDL_GLContext mGLContext = nullptr;
|
||||||
|
|
||||||
|
using glClear_fn_t = void (*)(std::uint32_t);
|
||||||
|
using glClearColor_fn_t = void (*)(float, float, float, float);
|
||||||
|
|
||||||
|
glClear_fn_t glClear;
|
||||||
|
glClearColor_fn_t glClearColor;
|
||||||
|
public:
|
||||||
|
virtual ~Application() = default;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
int run(int argc, char* argv[]);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void render() = 0;
|
||||||
|
virtual void handleMessage(const Message& message);
|
||||||
|
virtual void handleSDLEvent(const SDL_Event& event);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool initSDL();
|
||||||
|
bool initGL();
|
||||||
|
bool initImGui();
|
||||||
|
void cleanup();
|
||||||
|
void handleSDLEvents();
|
||||||
|
};
|
||||||
|
|
||||||
|
using render_cb_t = std::function<void()>;
|
||||||
|
struct QuickAppOptions
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
render_cb_t render;
|
||||||
|
} callbacks;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuickApp : public Application
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
QuickAppOptions mOptions;
|
||||||
|
public:
|
||||||
|
void init(QuickAppOptions options);
|
||||||
|
void render() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
int runQuick(int argc, char* argv[], QuickAppOptions options);
|
||||||
|
} // namespace raid
|
||||||
|
|
||||||
|
#endif // !defined(RAID_PUBLIC_RAID_RAID_HPP_INCLUDED)
|
Loading…
x
Reference in New Issue
Block a user