SDL3pp
A slim C++ wrapper for SDL3
Loading...
Searching...
No Matches
SDL3pp_init.h
1#ifndef SDL3PP_INIT_H_
2#define SDL3PP_INIT_H_
3
4#include <atomic>
5#include <SDL3/SDL_init.h>
6#include "SDL3pp_callbackWrapper.h"
7#include "SDL3pp_error.h"
8#include "SDL3pp_log.h"
9#include "SDL3pp_stdinc.h"
10
15namespace SDL {
16
66using InitFlags = Uint32;
67
80{};
81
83 SDL_INIT_AUDIO;
84
88constexpr InitFlags INIT_VIDEO = SDL_INIT_VIDEO;
89
94constexpr InitFlags INIT_JOYSTICK = SDL_INIT_JOYSTICK;
95
96constexpr InitFlags INIT_HAPTIC = SDL_INIT_HAPTIC;
97
99 SDL_INIT_GAMEPAD;
100
101constexpr InitFlags INIT_EVENTS = SDL_INIT_EVENTS;
102
104 SDL_INIT_SENSOR;
105
107 SDL_INIT_CAMERA;
108
110
138using AppResult = SDL_AppResult;
139
143constexpr AppResult APP_CONTINUE = SDL_APP_CONTINUE;
144
148constexpr AppResult APP_SUCCESS = SDL_APP_SUCCESS;
149
153constexpr AppResult APP_FAILURE = SDL_APP_FAILURE;
154
156
180using AppInit_func = SDL_AppInit_func;
181
195using AppIterate_func = SDL_AppIterate_func;
196
211using AppEvent_func = SDL_AppEvent_func;
212
225using AppQuit_func = SDL_AppQuit_func;
226
228
283inline void InitSubSystem(InitFlags flags) { CheckError(SDL_Init(flags)); }
284
345template<class FLAG0, class FLAG1, class... FLAGS>
346inline void InitSubSystem(FLAG0 flag0, FLAG1 flag1, FLAGS... flags)
347{
348 InitSubSystem(flag0);
349 InitSubSystem(flag1, flags...);
350}
351
411template<class FLAG, class... FLAGS>
412inline void InitSubSystem(FLAG flag0, FLAG flag1, FLAGS... flags)
413{
414 return InitSubSystem(flag0 | flag1, flags...);
415}
416
431inline void QuitSubSystem(InitFlags flags) { SDL_QuitSubSystem(flags); }
432
449template<class FLAG0, class FLAG1, class... FLAGS>
450inline void QuitSubSystem(FLAG0 flag0, FLAG1 flag1, FLAGS... flags)
451{
452 if (!QuitSubSystem(flag0)) return;
453 QuitSubSystem(flag1, flags...);
454}
455
471template<class FLAG, class... FLAGS>
472inline void QuitSubSystem(FLAG flag0, FLAG flag1, FLAGS... flags)
473{
474 QuitSubSystem(flag0 | flag1, flags...);
475}
476
489inline bool WasInit(InitFlags flags) { return SDL_WasInit(flags) == flags; }
490
502template<class FLAG0, class FLAG1, class... FLAGS>
503inline bool WasInit(FLAG0 flag0, FLAG1 flag1, FLAGS... flags)
504{
505 if (WasInit(flag0)) return WasInit(flag1, flags...);
506 return false;
507}
508
519template<class FLAG, class... FLAGS>
520inline bool WasInit(FLAG flag0, FLAG flag1, FLAGS... flags)
521{
522 return WasInit(flag0 | flag1, flags...);
523}
524
541inline void Quit() { SDL_Quit(); }
542
554class SDL
555{
556 bool m_active = false;
557
558 bool updateActive(bool active);
559
560public:
571 template<class... FLAGS>
572 SDL(FLAGS... flags)
573 {
574 if (updateActive(true)) {
575 try {
576 InitSubSystem(flags...);
577 } catch (...) {
578 updateActive(false);
579 throw;
580 }
581 }
582 }
583
589 constexpr SDL() = default;
590
591 // Copy ctor
592 SDL(const SDL& other) = delete;
593
595 constexpr SDL(SDL&& other)
596 : m_active(other.m_active)
597 {
598 other.m_active = false;
599 }
600
601 // Dtor
602 ~SDL() { reset(); }
603
606 {
607 std::swap(m_active, rhs.m_active);
608 return *this;
609 }
610
618 bool release()
619 {
620 bool wasActive = m_active;
621 if (wasActive) { updateActive(false); }
622 return wasActive;
623 }
624
630 bool reset()
631 {
632 if (release()) Quit();
633 return false;
634 }
635
637 operator bool() const { return m_active; }
638};
639
658inline bool IsMainThread() { return SDL_IsMainThread(); }
659
674using MainThreadCallback = SDL_MainThreadCallback;
675
683using MainThreadCB = std::function<void()>;
684
686
711 void* userdata,
712 bool wait_complete)
713{
714 CheckError(SDL_RunOnMainThread(callback, userdata, wait_complete));
715}
716
742inline void RunOnMainThread(MainThreadCB callback, bool wait_complete)
743{
744 using Wrapper = CallbackWrapper<MainThreadCB>;
745 void* wrapped = Wrapper::Wrap(std::move(callback));
746 try {
747 RunOnMainThread(&Wrapper::CallOnce, wrapped, wait_complete);
748 } catch (...) {
749 Wrapper::release(wrapped);
750 throw;
751 }
752}
753
789inline void SetAppMetadata(StringParam appname,
790 StringParam appversion,
791 StringParam appidentifier)
792{
793 CheckError(SDL_SetAppMetadata(appname, appversion, appidentifier));
794}
795
857{
858 CheckError(SDL_SetAppMetadataProperty(name, value));
859}
860
861namespace prop::appMetaData {
862
863constexpr auto NAME_STRING = SDL_PROP_APP_METADATA_NAME_STRING;
864
865constexpr auto VERSION_STRING = SDL_PROP_APP_METADATA_VERSION_STRING;
866
867constexpr auto IDENTIFIER_STRING = SDL_PROP_APP_METADATA_IDENTIFIER_STRING;
868
869constexpr auto CREATOR_STRING = SDL_PROP_APP_METADATA_CREATOR_STRING;
870
871constexpr auto COPYRIGHT_STRING = SDL_PROP_APP_METADATA_COPYRIGHT_STRING;
872
873constexpr auto URL_STRING = SDL_PROP_APP_METADATA_URL_STRING;
874
875constexpr auto TYPE_STRING = SDL_PROP_APP_METADATA_TYPE_STRING;
876
877} // namespace prop::appMetaData
878
900inline const char* GetAppMetadataProperty(StringParam name)
901{
902 return SDL_GetAppMetadataProperty(name);
903}
904
905#pragma region impl
906
907#ifndef SDL3PP_APPCLASS_LOG_PRIORITY
911#define SDL3PP_APPCLASS_LOG_PRIORITY LOG_PRIORITY_CRITICAL
912#endif // SDL3PP_APPCLASS_LOG_PRIORITY
913
917using AppArgs = std::span<char const* const>;
918
931template<class T>
932inline AppResult DefaultCreateClass(T** state, AppArgs args)
933{
934 static_assert(std::is_default_constructible_v<T>);
935 *state = new T{};
936 return APP_CONTINUE;
937}
938
939template<class T>
940 requires std::convertible_to<AppArgs, T>
941inline AppResult DefaultCreateClass(T** state, AppArgs args)
942{
943 *state = new T{args};
944 return APP_CONTINUE;
945}
947
949template<class T>
950concept HasInitFunction = requires(T** state) {
951 { T::Init(state, AppArgs{}) } -> std::convertible_to<AppResult>;
952};
953
967template<class T>
968inline AppResult InitClass(T** state, AppArgs args)
969{
970 try {
971 return DefaultCreateClass(state, args);
972 } catch (std::exception& e) {
974 e.what());
975 } catch (...) {
976 }
977 return APP_FAILURE;
978}
979
980template<HasInitFunction T>
981inline AppResult InitClass(T** state, AppArgs args)
982{
983 *state = nullptr;
984 try {
985 AppResult result = T::Init(state, args);
986 if (*state == nullptr && result != APP_FAILURE) return APP_SUCCESS;
987 return result;
988 } catch (std::exception& e) {
990 e.what());
991 } catch (...) {
992 }
993 return APP_FAILURE;
994}
996
998template<class T>
999concept HasIterateFunction = requires(T* state) { state->Iterate(); };
1000
1008template<HasIterateFunction T>
1009inline AppResult IterateClass(T* state)
1010{
1011 try {
1012 return state->Iterate();
1013 } catch (std::exception& e) {
1015 e.what());
1016 } catch (...) {
1017 }
1018 return APP_FAILURE;
1019}
1020
1022template<class T>
1024 requires(T* state, const SDL_Event& event) { state->Event(event); };
1025
1034template<class T>
1035inline AppResult DefaultEventClass(T* state, const SDL_Event& event)
1036{
1037 if (event.type == SDL_EVENT_QUIT) return APP_SUCCESS;
1038 return APP_CONTINUE;
1039}
1040
1050template<class T>
1051inline AppResult EventClass(T* state, const SDL_Event& event)
1052{
1053 try {
1054 return DefaultEventClass(state, event);
1055 } catch (std::exception& e) {
1057 e.what());
1058 } catch (...) {
1059 }
1060 return APP_FAILURE;
1061}
1062
1063template<HasEventFunction T>
1064inline AppResult EventClass(T* state, const SDL_Event& event)
1065{
1066 try {
1067 return state->Event(event);
1068 } catch (std::exception& e) {
1070 e.what());
1071 } catch (...) {
1072 }
1073 return APP_FAILURE;
1074}
1075
1077
1084template<class T>
1085inline void DefaultClassDestroy(T* state)
1086{
1087 delete state;
1088}
1089
1091template<class T>
1093 requires(T* state, AppResult result) { T::Quit(state, result); };
1094
1107template<class T>
1108inline void QuitClass(T* state, AppResult result)
1109{
1110 DefaultClassDestroy(state);
1111}
1112
1113template<HasQuitFunction T>
1114inline void QuitClass(T* state, AppResult result)
1115{
1116 T::Quit(state, result);
1117}
1119
1121
1122inline bool SDL::updateActive(bool active)
1123{
1124 static std::atomic_bool currentlyInitd{false};
1125 bool result = !currentlyInitd.exchange(active);
1126 if (active && !result) {
1128 "Can not initialize, there is already an active instance");
1129 } else
1130 m_active = active;
1131 return result;
1132}
1133
1134#pragma endregion
1135
1136} // namespace SDL
1137
1138#endif /* SDL3PP_INIT_H_ */
void LogUnformatted(LogPriority priority, StringParam message) const
Log an unformatted message with the specified priority.
Definition SDL3pp_log.h:226
constexpr SDL(SDL &&other)
Move ctor.
Definition SDL3pp_init.h:595
SDL(FLAGS... flags)
Init given subsystems.
Definition SDL3pp_init.h:572
constexpr SDL()=default
Default ctor.
bool reset()
reset the value of this instance, acts like it was destroyed and then newly instantiated with empty c...
Definition SDL3pp_init.h:630
SDL & operator=(SDL rhs)
Assignment operator.
Definition SDL3pp_init.h:605
bool release()
release locking such as reset() does, but never calls SDL_Quit() or SDL_QuitSubSystem()
Definition SDL3pp_init.h:618
Helpers to use C++ strings parameters.
Definition SDL3pp_strings.h:43
Definition SDL3pp_init.h:1023
Definition SDL3pp_init.h:950
Definition SDL3pp_init.h:999
Definition SDL3pp_init.h:1092
bool SetErrorUnformatted(StringParam message)
Set the SDL error message for the current thread.
Definition SDL3pp_error.h:66
constexpr void CheckError(bool result)
Check and throw if returned value from SDL is an error.
Definition SDL3pp_error.h:206
void SetAppMetadata(StringParam appname, StringParam appversion, StringParam appidentifier)
Specify basic metadata about your app.
Definition SDL3pp_init.h:789
void QuitClass(T *state, AppResult result)
Destroy state with given result.
Definition SDL3pp_init.h:1108
AppResult IterateClass(T *state)
Iterate the state.
Definition SDL3pp_init.h:1009
std::function< void()> MainThreadCB
Definition SDL3pp_init.h:683
void InitSubSystem(InitFlags flags)
Initialize the SDL library.
Definition SDL3pp_init.h:283
AppResult DefaultCreateClass(T **state, AppArgs args)
Allocate and initialize state with new.
Definition SDL3pp_init.h:932
constexpr AppResult APP_FAILURE
Value that requests termination with error from the main callbacks.
Definition SDL3pp_init.h:153
std::span< char const *const > AppArgs
Represents application parameters.
Definition SDL3pp_init.h:917
constexpr AppResult APP_CONTINUE
Value that requests that the app continue from the main callbacks.
Definition SDL3pp_init.h:143
SDL_AppIterate_func AppIterate_func
Function pointer typedef for SDL_AppIterate.
Definition SDL3pp_init.h:195
const char * GetAppMetadataProperty(StringParam name)
Get metadata about your app.
Definition SDL3pp_init.h:900
SDL_MainThreadCallback MainThreadCallback
Callback run on the main thread.
Definition SDL3pp_init.h:674
SDL_AppResult AppResult
Return values for optional main callbacks.
Definition SDL3pp_init.h:138
bool WasInit(InitFlags flags)
Check if all of the specified subsystems which are currently initialized.
Definition SDL3pp_init.h:489
SDL_AppInit_func AppInit_func
Function pointer typedef for SDL_AppInit.
Definition SDL3pp_init.h:180
void RunOnMainThread(MainThreadCallback callback, void *userdata, bool wait_complete)
Call a function on the main thread during event processing.
Definition SDL3pp_init.h:710
AppResult DefaultEventClass(T *state, const SDL_Event &event)
Default handle by finishing if QUIT is requested.
Definition SDL3pp_init.h:1035
void DefaultClassDestroy(T *state)
Destroy state with delete;.
Definition SDL3pp_init.h:1085
void SetAppMetadataProperty(StringParam name, StringParam value)
Specify metadata about your app through a set of properties.
Definition SDL3pp_init.h:856
#define SDL3PP_APPCLASS_LOG_PRIORITY
The default log priority for app class.
Definition SDL3pp_init.h:911
AppResult EventClass(T *state, const SDL_Event &event)
Iterate the state.
Definition SDL3pp_init.h:1051
void Quit()
Clean up all initialized subsystems.
Definition SDL3pp_init.h:541
void QuitSubSystem(InitFlags flags)
Shut down specific SDL subsystems.
Definition SDL3pp_init.h:431
SDL_AppEvent_func AppEvent_func
Function pointer typedef for SDL_AppEvent.
Definition SDL3pp_init.h:211
AppResult InitClass(T **state, AppArgs args)
Init state with arguments.
Definition SDL3pp_init.h:968
bool IsMainThread()
Return whether this is the main thread.
Definition SDL3pp_init.h:658
SDL_AppQuit_func AppQuit_func
Function pointer typedef for SDL_AppQuit.
Definition SDL3pp_init.h:225
constexpr AppResult APP_SUCCESS
Value that requests termination with success from the main callbacks.
Definition SDL3pp_init.h:148
constexpr LogCategory LOG_CATEGORY_APPLICATION
APPLICATION.
Definition SDL3pp_log.h:489
constexpr InitFlags INIT_SENSOR
INIT_SENSOR implies INIT_EVENTS
Definition SDL3pp_init.h:103
Uint32 InitFlags
Initialization flags for SDL.
Definition SDL3pp_init.h:66
constexpr InitFlags INIT_JOYSTICK
INIT_JOYSTICK implies INIT_EVENTS, should be initialized on the same thread as INIT_VIDEO on Windows ...
Definition SDL3pp_init.h:94
constexpr InitFlags INIT_VIDEO
INIT_VIDEO implies INIT_EVENTS, should be initialized on the main thread
Definition SDL3pp_init.h:88
constexpr InitFlags INIT_AUDIO
INIT_AUDIO implies INIT_EVENTS
Definition SDL3pp_init.h:82
constexpr InitFlags INIT_EVENTS
EVENTS.
Definition SDL3pp_init.h:101
constexpr InitFlags INIT_GAMEPAD
INIT_GAMEPAD implies INIT_JOYSTICK
Definition SDL3pp_init.h:98
constexpr InitFlags INIT_HAPTIC
HAPTIC.
Definition SDL3pp_init.h:96
constexpr InitFlags INIT_CAMERA
INIT_CAMERA implies INIT_EVENTS
Definition SDL3pp_init.h:106
the main namespace where all SDL3pp public functions and types live
Definition SDL3pp_assert.h:7
Definition SDL3pp_callbackWrapper.h:66
Initialization flags for SDL satellite libraries.
Definition SDL3pp_init.h:80